[I.3] 个人作业:结课总结

[I.3] 个人作业:结课总结

项目 内容
这个作业属于哪个课程 2026年春季软件工程 (北京航空航天大学 - 计算机学院)
这个作业的要求在哪里 [I.3] 个人作业:结课总结
我在这个课程的目标是 了解现代软件工程的思想和开发方法,并把它们应用到真实的软件开发过程中
这个作业在哪个具体方面帮助我实现目标 回顾一学期以来从阅读、个人项目、结对项目、团队项目和实习经历中获得的认识

一、提问回顾

学期开始时,我在 [I.1] 个人作业:阅读和提问 中提出了 5 个问题。当时这些问题更多来自阅读材料后的直观疑惑,现在经历了个人项目、结对项目、团队项目,以及最近在字节实习中接触到的实际研发流程后,再回头看这些问题,就不只是概念上的讨论了。很多问题都和自己做项目时遇到的取舍联系起来了。

Q1、如何量化判断一项创新技术是否值得发展?

当时我用铱星和星链的对比提出了这个问题:一项技术的普及,到底是高技术力创新的胜出,还是市场博弈中的幸存者偏差?

现在我的理解是,软件工程里很难只用“技术先进程度”来判断创新是否值得发展。一个创新是否有价值,至少要看它解决的问题是否真实存在,相比旧方案是否有明显收益,以及这些收益能不能覆盖迁移和维护成本。换句话说,创新不只是“我能做出一个新的东西”,还要看这个新东西能不能在现实约束下持续创造价值。

这个认识主要来自团队项目和案例分析。在分析 Niri 时,我一开始很容易被它新颖的交互和 Rust 实现吸引,但真正评估软件质量时,稳定性、兼容性、学习成本和生态成熟度反而更重要。团队项目也是这样,一个看起来很酷的功能,如果没有明确的用户场景,最后很可能只是消耗开发时间,还会增加测试和维护成本。因此,我现在更倾向于从“价值/成本”的角度判断创新,而不是只看技术够不够新。

Q2、AI 可以作为技能的替代,解决“低层次”问题吗?

当时我的想法其实比较乐观:既然 LLM 已经可以生成没有语法错误的程序,也许程序员可以只负责上层设计,而不用再亲自处理很多编码细节。

经过结对项目和实习中的观察后,我的看法变得保守了一些。AI 确实可以替代一部分重复性的编码动作,但还不能替代工程能力本身。真正困难的地方经常不是“写出一段代码”,而是判断需求有没有歧义、接口边界是否合理、异常情况是否覆盖、生成的实现是否和上下文一致,以及出了问题之后应该如何定位。

在结对项目里,我们确实使用了 Codex 辅助生成测评程序和改进版策略。它能明显提高试错速度,但前提是我们已经知道要测什么、怎么判断结果是否正确、生成的代码应该放在怎样的结构里。否则 AI 只是更快地给出一份看似合理但难以验证的代码。实习中也有类似感受:真实项目里的“低层次问题”不只有语法和 API 调用,还包括代码风格、历史包袱、依赖关系、上线风险和团队约定。这些都需要程序员有足够的基本功,才能正确地使用 AI。

所以我现在的答案是:AI 可以减少低层次劳动,但不能让程序员跳过低层次技能。低层次技能不再只是“会不会敲语法”,而是“能不能审查、组织、验证和维护由人或 AI 产生的代码”。

Q3、从小处着手解决问题和不要重复造轮子是冲突的吗?

我当时困惑的是:如果社区里已经有很多类似方案,我们继续从小目标出发开发,会不会和“不要重复造轮子”冲突?

现在我认为二者并不冲突,关键要看我们重复造的是“结果”还是“理解”。如果目标是交付一个软件,就应该尽量复用成熟工具和框架;如果目标是理解一个问题或验证一个局部设计,那么适度地重新实现一些小模块也是有价值的。课程里的结对项目就是一个例子。花见小路的规则判定和策略搜索当然可以借鉴许多已有的博弈算法思想,但我们仍然需要自己拆解规则、设计中间量、写测试用例,因为这些过程训练的是问题建模能力。

从团队项目角度看,“不重复造轮子”更像是工程决策原则,而不是绝对禁令。成熟轮子能降低风险,但也会带来依赖、学习成本和适配成本。自己实现可以更贴合需求,但要承担质量和维护责任。因此真正的问题不是“能不能造轮子”,而是“这个轮子是不是项目目标所必需,以及团队有没有能力长期维护它”。

Q4、对于实际生产中不会触碰到的边界情况,是否有必要单独考虑?

当时我以千年虫问题为例,思考是否需要为看似无用的边界情况设计测试。

现在我的答案是:边界情况当然要考虑,但不能无限制地考虑。测试不是“宁可错杀一万”的堆砌,而是基于风险和成本的工程取舍。对于会影响核心功能、数据安全、权限、稳定性的问题,即使触发概率低,也应该单独设计测试;而对于影响很小、恢复成本很低、发生条件极端的情况,可以更多依靠监控、日志、容错和后续维护来覆盖。

结对项目让我更直接地理解了这一点。规则判定类模块的边界情况很多,如果不设计边界测试,很容易出现漏判、错判或分支顺序错误。但如果盲目枚举所有可能牌局,也会浪费时间。因此更合理的方式是先分析规则结构,再用等价类、边界值和随机测试补充覆盖。实践让我认识到,测试不是越多越好,而是越能捕捉风险越好。

Q5、用户调研真的能导向真正的创新吗?

我当时担心,过度依赖用户调研会让产品设计陷入局部最优,甚至导致退步。

现在我认为,用户调研不能直接给出创新,但能帮助我们避免自嗨。用户通常更擅长描述痛点,而不一定能提出最优解。开发者如果机械满足用户提出的每一个功能请求,确实容易陷入局部最优;但如果完全脱离用户反馈,又容易做出没有实际场景的功能。比较合理的做法是,把用户反馈当作问题来源,而不是直接当作方案来源。

这个认识来自个人的软件案例分析和团队项目。在 Niri 的分析中,用户反馈能暴露学习门槛、输入法兼容、休眠恢复等真实问题,但如何解决这些问题仍然需要开发者从架构、协议和交互设计角度做判断。团队项目也是如此,需求阶段听到的往往是“我想要某个功能”,而设计阶段真正要回答的是“这个功能背后的需求是什么,是否有更低成本的实现方式”。因此,用户调研不是创新的终点,更像是创新的起点和校验工具。

二、仍然没有完全弄清楚的问题

这 5 个问题现在都有了阶段性的答案,但也并不是说都已经完全想清楚了。

我仍然没有完全弄清楚的是 Q1 和 Q5。创新价值和用户调研本质上都涉及市场、组织、技术和时间窗口的共同作用。课程项目的规模比较小,我们可以较快看到一个功能是否有用,但真实产品往往需要更长的周期才能验证。一个功能短期数据不好,不一定说明方向错误;一个功能短期数据好,也不一定说明它有长期价值。如何在短期指标和长期产品判断之间做平衡,我目前还没有特别成熟的答案。

此外,AI 对软件工程流程的影响也还在快速变化。现在我能回答“AI 不能替代工程能力”,但还不能回答“未来团队应该如何系统地组织 AI 参与需求、开发、测试和维护”。这个问题可能还需要更多真实项目经验才能判断。

三、新产生的问题

结合最近在字节实习中的经历,我又产生了两个新的问题。

问题一:在实际业务开发中,如何判断一个技术方案已经“足够工程化”,而不是短期堆出来的 patch,也不是成本过高的过度设计?

在课程项目中,一个方案好不好,通常可以通过作业要求、测试结果和团队讨论较快判断。但在实习接触到的真实业务里,需求变化更快,代码也往往承载着历史逻辑。一个方案可能今天看起来最省事,但以后会变成维护负担;另一个方案架构更完整,却可能赶不上当前业务节奏。如何在上线速度、代码质量、可维护性和团队协作成本之间找到平衡,是我在课堂之外感受到的一个更真实的软件工程问题。

进一步说,AI 编程工具加入以后,这个问题会更加明显。AI 可以快速生成一个可运行方案,但“可运行”不等于“可维护”。那么团队是否需要为 AI 生成代码建立额外的审查标准?AI 生成的测试是否可信?未来的软件工程流程是否应该把提示词、生成记录、人工审查意见也纳入工程资产?这些都是我现在想继续思考的问题。

问题二:产品设计、RD 需求调研、ERD 文档、agent 的 SDD 自动化流程、多轮测试和灰度发布这些工业流程,和课程中强调的敏捷开发是否冲突?

在课程项目中,我对“敏捷”的理解一开始比较简单,觉得它强调快速迭代、快速交付。但在实习中,一个功能从产品设计开始,到 RD 做需求调研、写 ERD 文档,再走 agent 的 SDD 自动化流程,开发完成后还要经历自测、QA 测试和灰度发布,整个链路比课程项目严格得多。表面上看,这似乎和敏捷开发追求快速反馈有些矛盾。

但进一步思考后,我觉得它们并不冲突。敏捷反对的不是必要流程,而是没有反馈、没有价值的流程。实际业务里的这些环节,本质上是在把风险前置:产品设计让目标更明确,ERD 和 SDD 让方案更容易被讨论和审查,自测与 QA 测试降低缺陷流入线上环境的概率,灰度发布则是在真实环境中控制影响范围。真正值得继续思考的是:流程做到什么程度是必要的工程保障,做到什么程度又会变成拖慢迭代的形式主义?

四、六个阶段中学到的知识点

软件工程这门课强调“做中学”。回顾项目中的需求、设计、实现、测试、发布、维护 6 个阶段,我分别学到的一个重要知识点如下。

阶段 学到的知识点 我的理解
需求 需求要从“用户说什么”追问到“用户为什么需要” 用户提出的往往是解决方案或表面诉求,开发者需要抽象出真正的问题,并写成可以验收的需求。
设计 模块边界比局部实现更重要 设计阶段如果没有划清接口和责任,后续实现会不断互相影响,测试和维护也会变得困难。
实现 小步提交和可运行状态很重要 结对项目中几次忘记及时 commit 后,调试和回滚成本明显增加。实现不是一次写完,而是要持续保持可验证。
测试 测试应围绕风险设计 有限时间内不可能测尽所有情况,应优先覆盖核心流程、边界条件和最容易出错的分支。实习中从自测到 QA 测试的流程,也让我认识到测试需要分层负责。
发布 发布不是“把代码交上去” 真正的发布需要考虑版本、环境、依赖、回滚和用户影响。灰度发布的意义就在于先控制影响范围,再逐步验证真实环境中的表现。
维护 可维护性来自文档、规范和上下文 团队项目和转会环节让我意识到,后来者能不能接手,取决于代码本身,也取决于文档、命名、提交记录和沟通记录。

五、结合项目经历的心得与总结

个人项目让我意识到,软件开发不是只把功能写出来,还要主动管理需求理解、资料查阅、环境调试和测试补充这些不确定性。在分析 Niri 的过程中,我也更清楚地认识到,一个软件的质量不能只看技术栈或功能亮点,还要看稳定性、兼容性、学习成本、社区生态和长期维护能力。很多时候,一个功能“能运行”只是最基础的要求,真正决定软件是否可用的,是它在复杂环境中是否稳定,用户是否愿意学习,出现问题后是否能定位和修复。

结对编程和团队项目让我更具体地理解了协作的价值。结对项目中,两个人持续互相校验,能更早发现规则理解偏差和边界遗漏;而两个阶段的团队项目和转会环节则让我意识到,软件工程首先是协作工程。文档、规范、提交记录和上下文交接并不是额外负担,而是在多人协作和人员变化时保存项目记忆的方式。如果这些信息缺失,后来者即使能看懂代码,也很难理解代码背后的取舍。

实习经历进一步加深了我对这门课的理解。在真实业务中,一个功能不是 RD 接到需求后立刻开始写代码,而是要先经过产品设计、需求调研、ERD 文档、SDD 自动化流程,再进入开发、自测、QA 测试和灰度发布。这个过程让我感触很深:流程本身不是为了拖慢开发,而是为了让需求、设计、实现、测试和发布中的风险尽早暴露。尤其是自测、QA 测试和灰度发布这几个环节,让我意识到真实用户环境远比本地开发环境复杂,线上质量需要靠分层验证来保证。

因此,我现在对敏捷开发的理解也发生了变化。敏捷不是省略需求、设计和测试,也不是想到什么就立刻上线,而是在保证反馈速度的同时,让每一次迭代都有明确目标、可验证结果和可控风险。一个学期下来,我对软件工程的理解从“写代码之外的流程”,变成了“让代码可交付、可协作、可维护的方法”。

posted @ 2026-06-30 21:41  Sayo_Hikawa  阅读(9)  评论(0)    收藏  举报