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

项目 内容
这个作业属于哪个课程 2026年春季软件工程 (北京航空航天大学 - 计算机学院)
这个作业的要求在哪里 [I.3] 个人作业:结课总结
我在这个课程的目标是 掌握现代软件工程的核心玩法,不光是背理论,更是想弄明白怎么把书上的模型用到真实的、充满变数的开发环境里,培养架构规划和风险规避的能力。
这个作业在哪个具体方面帮助我实现目标 回过头检验学期初提出的问题,用一个学期"做中学"的真实经历去回答、修正甚至推翻当初的想法

写在前面

学期开始的时候,我在阅读《构建之法》之后提了五个问题。当时的我,更像是站在岸上看游泳:问题大多是从管理学、经济学、心理学里"借"来的漂亮框架,再硬套到软件工程上。

一个学期过去了,我们做完了一个结对项目、两个阶段的团队项目,中间还经历了一次转会。正所谓"实践是认识的来源、目的、动力以及检验认识真理性的唯一标准",等到真正实践了一个学期,再回头看这五个问题,感受完全不同。

学期初提问题的博客: [I.1] 个人作业:阅读和提问

回望初心: 对当初五个问题的再回答

问题一: PM 有责无权,如何推进项目?

当初的困惑:

在推崇技术精英主义、又相对"平等"的环境里,没有行政权和绩效考核权的 PM,会不会变成一个名存实亡的虚职?当 PM 的商业目标和资深架构师的技术倾向硬碰硬时,不"打小报告"还能怎么推进?

实践给的答案:

在我们团队里,PM 并没有变成虚职——但它的"权力"来源和我当初想象的完全不一样。
PM 的影响力不是来自"我能扣你绩效",而是来自三个实打实的支点:一是团队约定的拍板权,遇到分歧"由一位有决定权的人拍板决定,在本门课程的场景下,这个人就是 PM";二是对集成接口的掌控,项目里前后端如何交互、关键 API 长什么样,都是由 PM 统一确定的,谁想绕开都绕不开;三是承担整合性的脏活累活,功能设计、文档这些没人愿意碰但又必须有人做的事,PM 兜了底。这其实就是管理学里说的"无职权影响力"(Influence without Authority)——靠的是信息枢纽和协调价值,而不是大棒。
但实践也狠狠教训了我一把,让我看到这把"权力"用过头的代价:

  • 我们一度把具体实现接口都攥在 PM 手里,事后复盘才意识到"这一部分如果交给前后端的同学做决定可能会更高效"。过度集权反而降低了效率。
  • PM 主导的每两天一次 Scrum Meeting,被证明是"事后看来没多大价值的事":组员普遍不乐意,开会时明显处在"汇报进度的高压状态",这反而不利于相互协作。
    所以对于问题一我如今的答案是:PM 推进项目靠的不是行政权,而是当好那个掌握集成点、营造安全氛围的协调者;真正会把 PM 拖垮的,恰恰是想用"虚职"去硬充"实权"——比如靠频繁开会去施压。至于真实公司里 PM 与 CTO 级架构师的死锁,我们这种小团队还没遇到那么极端的场面,这部分我留到后面"还没想明白"里继续说。

问题二: KPI 的两面性——量化指标会逼着程序员刷数据吗?

当初的困惑:

既然几乎所有局部量化指标(代码行数、故事点、缺陷密度)都逃不过古德哈特定律,那管理层到底该建一套什么样的框架,才能真实评估一个工程师对系统生命周期的贡献?

实践给的答案:

我现在的体会是——与其追求一个完美的"超级指标",不如换掉被度量的对象本身。
敏捷宣言里那句"可工作的软件是衡量进度的主要标准",是我们整个团队感受最深、也实践得最好的一条原则。我们刻意"减少了不必要的文档说明,把大部分时间直接用于代码编写",因为我们清楚地意识到:纯为应付检查而写的文档"只可能为了应付要求而敷衍了事"——这正是古德哈特定律的现场。
具体到怎么用指标,我们摸出了两条经验:一是把指标当"门禁"而不是"目标",比如约定单元测试覆盖率达到某个预设值(如 75%)才允许合入主分支,它是一道质量底线,而不是一个让人去刷的 KPI;二是优先用结果性指标,慎用过程性指标,我们衡量重构是否成功,看的是"Bug 是否被解决、性能提升了多少百分比",而不是改了多少行代码。
频繁汇报进度这件事本身就是个反面教材:把"进度可见性"当成目标去频繁度量,结果度量动作(开会)反而毁掉了被度量的东西(协作氛围)。
所以问题二我想明白了一半:指标要为团队服务,而不是团队为指标服务。但那个能"无损评估生命周期贡献"的终极框架,我现在更倾向于认为它根本不存在,只能用"结果性指标 + 定性评审"去逼近。

问题三: 结对编程与心流状态如何平衡?

当初的困惑:

结对编程逼着人高频交流,会打断深度专注的"心流",到底有没有成熟的方法论来平衡两者?

实践给的答案:

这个问题被我们的结对项目(花见小路 + Wasm)正面回答了,而且答案出乎意料地朴素——不存在一刀切的方法论,关键是让协作模式去匹配任务类型。
我们的实际做法分成了两种节奏:一是复杂、易错、共享的逻辑,就老老实实结对,比如 T1 的规则判定模块,"驾驶员-领航员"模式让搭档提前拦住了我一个人根本想不到的边界情况(刚好 11 分、刚好 4 个标记、第三小轮同分……),这种地方两个人盯着,BUG 当场就被摁住了;二是需要深度探索的部分,就拆开各写各的,再回来比对,到了 T3 设计博弈策略时,我们"两人分开写不同的策略,要来其它组的策略,进行多次测试,不断修正对比",这恰恰是在用拆分来保护各自的心流,等深度思考有了成果,再合到一起用数据 PK。
所以我对结对编程的理解,从"一个人写一个人看"变成了"两个人一直在同步想法、同步修正"。它在规则复杂、容易出错的任务里特别有用;而在需要长时间孤独沉浸的任务里,最好的"结对"反而是阶段性地分开。心流和结对不是敌人,是需要按任务切换的两挡。

问题四: 重复造轮子,还是老实维护排雷?

当初的困惑:

既然课本和数据都证明"维护并平滑演进"最有经济价值,为什么待遇和光环都给了造轮子的人?该怎么规范考核,给"排雷工程师"公平的待遇?

实践给的答案:

我们整个 Beta 阶段,本质上就是一次大型"排雷"。
我们没有从零开整新功能,而是在 Alpha 的烂摊子上做维护演进:重写了规则引擎(这是 Alpha 留下、当时根本跑不通的核心功能),修掉了用户重名不提示、SMTP 配置错误等一堆缺陷。事实证明,平台真正的价值(规则能被合理地玩起来)恰恰是在这段"不起眼"的维护工作里才落地的。而且最容易出 Bug 的规则执行引擎,也正是最需要小心维护的地方。
在"如何给这群人公平关注"这件事上,我们小团队至少做了一点实践:在事后分析里显式地、公开地点名感谢那些做兜底和救火的同学——感谢承担了大部分功能开发的努力,感谢稳稳搞定每一个紧急需求,感谢对项目的整体部署与维护。把维护的贡献写进白纸黑字,本身就是一种"看见"。
但说实话,这个问题在组织/行业层面我并没有真正解决。一个学生项目的影响力太小,撼动不了真实世界里"晋升偏爱绿地开发"的结构性偏好。我能确认的只是:维护确实是价值所在;至于如何设计出一套公平的考核制度,我还没有答案——详见后面"还没想明白"。

问题五: UX 极简 vs 后端复杂度的取舍

当初的困惑:

为了给用户省那 1% 的操作成本,把后端搞成灾难,到底划不划算?有没有一个经验模型能果断叫停这种过度优化?

实践给的答案:

布鲁克斯那句"复杂性是不灭的,它只能被转移",我们是用一整个学期亲身验证的。我们团队感受最深的就是"没有银弹"。
我们最初的设想很美好:做一套图形化的自定义规则构建系统,让规则开发者不用学编程语言。结果呢?一方面,复杂性确实没有消失,只是被转移了:前端把"写代码"这件事藏起来,代价是后端要扛起一个极其复杂的规则执行引擎——而它恰恰成了整个项目产生 Bug 最多的模块;另一方面更扎心的是,这个 UX 目标本身都没完全达到:图形化语言虽然免去了学编程语言的门槛,却又引入了学我们这套图形化语言的新门槛,而且"组件原子化相当高,使用起来远提不上好用"。
所以问题五我想明白的是:没有一个干净的概率公式能告诉你"何时该叫停",这更多是工程判断。但实践给了我一条相当好用的启发式——如果你想隐藏的那点复杂度,会落到系统里最关键、最易错的子系统上(比如我们的规则引擎),而这点 UX 提升又不是产品的核心价值主张,那就别做这个转移;反之,如果它就是核心卖点(对我们而言图形化构建确实是),那即便代价高昂也得认——但要做好"简化本身可能根本没你想得那么爽"的心理准备。

二、还没完全想明白的问题

实践之后,仍有几个问题我没能彻底想通:

第一,真实公司里 PM 与顶级架构师的死锁。我们小团队靠"团队约定的拍板权"就化解了分歧,但那是因为大家本就认同 PM 的协调价值。在一个权责严重不对等、又没有共识基础的大组织里,无职权影响力到底还撑不撑得住,我没有第一手经验,仍然存疑。

第二,维护贡献的公平考核制度。学生项目里我们能靠"公开感谢"去看见排雷的人,但这套办法在真实的晋升答辩、薪酬体系里几乎无效。如何设计一套能抵抗"绿地偏好"的制度,我依然没有答案。

第三,复杂度转移的"叫停阈值"。我得到了定性的判断准则,但当初想要的那个能定量测算的经验模型,我现在怀疑它压根不存在——可这又让我不甘心,工程界真的只能靠"老师傅的直觉"吗?

三、新产生的问题

实践之后,我反而冒出了一些当初根本想不到的新问题:

第一,"计划不如变化快"和"凡事预则立"之间的边界在哪? 我们一开始把各阶段任务、分工、起止时间都规划得极细,结果在变更管理一节我们诚实地承认:这种过度规划让我们"处理意料之外工作请求的能力有限"。那么,计划到底该做到多细,才能既不裸奔、又不把自己捆死?这个度我至今没拿准。

第二,缓冲区究竟该是"保险"还是"加餐"? 我们 Alpha 和 Beta 都留了最后一周做缓冲,但每次都被未完成的任务吃掉了,从来没机会拿它去做更充分的测试。是我们的估计永远偏乐观,还是缓冲区天然就会被工作填满(类似帕金森定律)?

第三,小团队验证不了的工程规律,到底该信几分? 比如"维护比开发更有价值",我们在 5~7 人、几个月的尺度上体会到了一点,但这和一个十年老系统、上百人维护团队的尺度差了好几个量级。我开始怀疑:很多软件工程"规律"是不是高度依赖规模,在不同体量下结论甚至会反转?

四、做中学:六个阶段各学到的一个知识点

软件工程有很多"知识点",这门课强调在实践中学。下面每个阶段我只挑一个体会最深的。

需求阶段 —— 典型用户与典型场景。 选题时我们就死磕"软件到底为谁解决什么问题",明确定义了平台管理员、规则开发者、玩家三类典型用户和各自的场景。事后看,正是这一步把后面所有功能的优先级(图形化构建最高、回放靠后)都钉死了。需求不是列功能清单,而是先想清楚"谁在什么场景下用"。

设计阶段 —— 关注点分离。 结对项目里我们刻意把"字符串解析"和"业务逻辑"分开写。这样后面 T2 改输入格式、T3 换策略时,都"不容易牵一发动全身"。抗变更能力不是靠多写代码堆出来的,而是靠在设计时就划清边界。

实现阶段 —— 代码复用,不重复造轮子。 T2 复用了 T1 的牌面索引映射和解析框架,T3 又复用了 T2 的状态重建逻辑。每一步都站在上一步的肩膀上,而不是推倒重来。这也反过来让我对问题四里"重复造轮子"的批判有了更切身的体会。

测试阶段 —— 边界测试 + 自动化回归。 结对项目里那些刁钻的边界用例(刚好 11 分、刚好 4 个标记、第三小轮同分)抓出了最隐蔽的 BUG;团队项目里我们用单元测试 + GitHub Actions 的 CI/CD 把回归测试自动化,"每改一次逻辑就跑一遍核心用例",防止改好的地方被改坏。测试的价值不在跑得多,而在卡住边界、守住回归。

发布阶段 —— 出口条件(Exit Criteria)。 我们给"什么叫做好了"下了清晰定义:前端能按预期展示交互、后端能执行预期逻辑、测试能通过所有预期用例。有了这条线,"发布"才不是拍脑袋说"差不多了",而是有据可依。也正是在发布过程中,我们才暴露出 SMTP 配置这类只有真上线才会现形的问题。

维护阶段 —— 重构。 Beta 阶段我们重写了规则引擎,让用户真正能用图形化界面设计出可玩的规则。重构不是"推倒重来",而是在不破坏已有行为的前提下改善内部结构——而要对症下药,前提是先搞清楚"现在已知的 Bug 是什么、性能瓶颈在哪"。这一阶段也让我真切体会到:维护和演进,才是软件生命周期里真正的主战场。

五、个人 / 结对 / 团队,三段经历的心得

个人项目(阅读提问)让我学会了"别在岸上谈游泳"。 回看学期初那五个问题,它们漂亮、宏大,却大多是从别处借来的理论框架硬套。真正下水之后我才发现,软件工程的很多答案不是公式,而是判断:没有银弹,没有终极指标,没有叫停过度优化的概率模型。承认"这事没有标准答案、只能靠工程判断",本身就是一种成长。

结对编程让我学会了"用数据代替感觉"。 T3 阶段我们有些改动"看着很聪明,结果一测不一定更强",是批量自动对局的数据告诉我们哪些改动是真有用。同样深刻的还有那句"能跑通不代表写得好"——结构清不清楚,等到要改规则的时候差别巨大。还有就是搭档的价值:很多我没想到的边界,是他提醒的,少走了不少弯路。

团队项目让我学会了"计划不如变化快"和"人比流程重要"。 我们最大的教训来自 Alpha 阶段:后端只交给一个人,又不强制沟通进度,结果开发严重滞后。Beta 阶段我们加了人手、要求及时同步,问题才解决——这恰好印证了"给定有限人力,做好分工至关重要"。中途的转会也让团队人员有了变动,逼着我们重新调整分工,反而促成了"把任务分配较少的测试同学也拉进前后端开发"的更合理配置。

而最反直觉的一课,是关于人的:我们一度迷信频繁的 Scrum Meeting,后来才醒悟,把人聚在一起轮流汇报,制造的是高压而不是协作;进度同步,"发一条短信、看一眼 Commit"就够了。营造一个安全、低压的氛围,远比用开会和查进度去推着项目走更有效。这一点,恰恰和我在问题一里对"PM 如何推进项目"的最终答案对上了。

一个学期下来,如果只让我留一句话,那就是——软件工程真正难的从来不是写代码,而是在理想模型和现实妥协之间,反复做出不完美但负责任的判断。 这趟"做中学",让我从背框架的人,慢慢变成了一个愿意为自己的判断负责的人。

posted @ 2026-06-30 13:34  Tanhhhhtjy  阅读(7)  评论(0)    收藏  举报