114
社区成员
发帖
与我相关
我的任务
分享这门软件工程课是我大学以来最具挑战性也最有收获的一次工程实践。过去,我写代码的目标是“让功能跑起来”;而这次,作为主开发,我必须思考:系统是否安全?是否可维护?是否能被他人理解?是否在三个月后依然可靠?
我们的项目开发像一场高强度的系统设计模拟战:每天从零开始构建一个核心模块,同时确保代码结构清晰、接口契约明确、错误处理完善、文档同步更新。
我逐渐意识到:软件工程的本质不是写代码,而是降低协作成本、控制系统熵增、构建可持续演进的数字资产。而主开发的角色,就是这个系统的“首席建筑师”与“质量守门人”。
背景:
系统需支持两类管理员:超级管理员可管理全校数据,而辅导员仅能查看和审核本学院的学生材料与用户信息。
初始方案与问题:
早期,我在每个接口中手动加入学院过滤逻辑。这种方式看似直接,但很快暴露出严重问题:重复代码多、易遗漏、难维护。在一次联调中,辅助开发同学发现某个查询接口未做学院过滤,导致辅导员可越权查看全校学生信息——这是一个典型的权限漏洞。
演进与重构思路:
我意识到,权限控制不能依赖“开发者记得写”,而应通过架构设计强制执行。于是,我将权限逻辑下沉到服务层基类中,并通过上下文自动注入当前用户所属学院。所有涉及数据隔离的接口,必须调用统一方法获取过滤条件,从而确保安全逻辑无一遗漏。
成果与反思:
重构后,系统再未出现越权问题。更重要的是,该设计具备良好扩展性:未来若新增“专业负责人”角色,只需在认证信息中增加专业字段,服务层扩展过滤逻辑即可。这让我深刻体会到:好的架构应让正确的事变得简单,错误的事变得困难。
背景:
认定奖励数据需同时存入 MySQL(用于事务性操作)和 Elasticsearch(用于全文检索)。然而,由于网络抖动、服务宕机等不可控因素,双写操作可能部分成功、部分失败,导致数据不一致。
初始方案与风险:
在 Beta 阶段,我采用同步双写策略:先写 MySQL,再写 ES。若 ES 写入失败,系统仅记录日志,不回滚 MySQL。这意味着:MySQL 有数据,ES 无索引,搜索功能将缺失该记录。
权衡与决策:
考虑到项目时间紧迫,且认定数据变更频率较低,我决定接受最终一致性,并将该问题明确标记为“技术债”。同时,我增加了健康检查接口,暴露最近同步失败的记录,便于人工干预。
长期优化方向:
为彻底解决该问题,我规划了基于“本地消息表”的最终一致性方案:在 MySQL 事务中同时写入业务数据和同步任务,由后台任务异步重试 ES 写入,成功后清理任务。此外,还将提供索引重建接口和每日自动比对机制,确保数据长期一致。
反思:
这次经历让我明白:在工程实践中,完美方案往往不如“可接受的务实方案”。关键在于——是否清晰识别风险、是否显性化技术债、是否有明确的后续优化路径。
| 阶段 | 收获与能力提升 |
|---|---|
| 需求 | 学会将模糊需求(如“辅导员只能看本院”)转化为可验证的验收标准,并与辅助开发共同确认边界条件 |
| 设计 | 掌握分层架构设计: - Controller:协议转换、参数校验 - Service:业务逻辑 + 权限控制 - Repository:数据存取 - Pack:响应封装 各层职责清晰,高内聚低耦合 |
| 实现 | 深入理解: - Hertz 框架机制(Bind/Validate、中间件、Context 传递) - JWT 权限透传与角色隔离 - ES 与 MySQL 协同的实践权衡 - Thrift IDL 驱动的接口契约管理 |
| 测试 | 认识到 Service 层是测试重点(业务逻辑集中),编写了关键路径的集成测试; 接受辅助开发的“破坏性测试”,提前暴露安全与边界问题 |
| 发布 | 掌握生产级部署要素: - 数据库迁移脚本(init.sql) - ES 索引初始化(go run cmd/es-init/main.go) - 环境变量配置(JWT_SECRET, DB_DSN) - 健康检查端点(/health) |
| 课程目标 | 自评 分 | 详细说明 |
|---|---|---|
| 目标1:职业道德与社会影响 | 88 | 通过权限设计保障教育公平(辅导员仅看本院);但在数据隐私(如学生材料存储)、算法透明度(积分规则可解释性)上思考不足 |
| 目标2:需求分析 | 85 | 能将用户需求转化为 Thrift IDL 接口契约,并与辅助开发共同确认验收标准;但未使用 UML 用例图/活动图等专业工具 |
| 目标3:软件开发全过程 | 92 | 最大收获:独立完成从架构设计(分层/权限/数据同步)到核心编码、测试、部署的全链路,具备完整工程视角 |
| 目标4:技术评测 | 80 | 主导 ES vs DB 搜索选型(ES 支持分词),但未做性能压测(如 10k 并发下响应时间);创新点体现在“辅导员权限基类”设计 |
| 目标5:文档规范 | 85 | 接口文档齐全(含字段说明、错误码),但系统设计说明书较简略(缺少架构图、数据流图) |
| 目标6:团队协作 | 90 | 有效组织辅开发,建立代码/文档规范;每日站会高效同步;主动采纳反馈,营造开放协作氛围 |
| 目标7:项目管理 | 78 | 采用敏捷冲刺,任务拆分合理;但未做工作量估算(如 story point),依赖经验判断;未使用 Jira/TAPD 等工具 |
在“准备篇”中,我为自己制定了学习路线:深入 Go 后端工程化实践,掌握高可用系统设计。本次项目中,我作为主开发,主导了后端整体架构,并解决了以下关键技术问题:
我选择 “MySQL 与 Elasticsearch 双写一致性保障” 进行深入总结:
为什么选择敏捷?
具体实践:
效果评估:
优势:
劣势:
不同软件开发模式对比与场景建议
| 开发模式 | 核心思想 | 适用场景 | 不适用场景 |
|---|---|---|---|
| **瀑布模型 ** | 严格线性推进,需求冻结后不可变,阶段间需正式评审 | 需求明确稳定、技术成熟、合同驱动型项目(如政府系统、嵌入式固件、医疗设备软件) | 需求模糊、需频繁变更、创新探索类项目 |
| 快速原型模型 | 先构建可运行原型,用户试用后反馈,定型再正式开发 | 需求模糊、需验证用户交互或核心流程(如新 App 创意、UI/UX 探索) | 对可靠性要求极高、不允许试错的系统(如航天控制) |
| 增量模型 | 将系统拆为多个完整功能增量,分批交付 | 中大型项目,需提前交付核心价值(如电商平台、企业 ERP) | 系统高度耦合、难以模块化拆分的项目 |
| 螺旋模型 | 迭代 + 风险驱动,每轮包含风险分析与原型验证 | 高风险、高复杂度、高可靠性要求的大型项目(如金融核心系统、航空软件) | 小型项目、资源有限、风险较低的场景 |
| 敏捷开发 | 小步快跑,高频迭代(1–4 周),拥抱变化,重视协作 | 互联网产品、需求多变、需快速试错(如社交 App、SaaS 工具、内部管理系统) | 需强合规审计、文档强制要求的行业(如军工、核电) |
| 迭代模型 | 分版本逐步完善,每次交付功能更完整的系统 | 需求大致明确,但需通过多轮反馈优化(如教育平台、科研系统) | 需一次性交付完整功能的合同项目 |