个人博客作业 1:提 5 个问题
笔者最近在北京中关村学院修读邹欣老师的《现代软件工程》课程。我是一名数学背景的学生,目前研究大模型强化学习和大模型 Agent 系统,跨入 CS/AI 领域的时间较短,自然代码能力较为浅薄。作为软件工程领域的初学者,我希望通过这门课能够提升编我的编程能力,更好地跟团队协作进行代码创作。以下是我在阅读课程材料《构建之法》时,思考出来的几个问题,希望能和更多开发者交流。
前言
笔者最近在北京中关村学院修读邹欣老师的《现代软件工程》课程。我是一名数学背景的学生,目前研究大模型强化学习和大模型 Agent 系统,跨入 CS/AI 领域的时间较短,自然代码能力较为浅薄 。作为软件工程领域的初学者,我希望通过这门课能够提升编我的编程能力,更好地跟团队协作进行代码创作。以下是我在阅读课程材料《构建之法》时,思考出来的几个问题,希望能和更多开发者交流。
问题 1:代码简洁性与可测试性的权衡是否必然存在?
《构建之法》第二章第 2 页,关于 MCDC(修正条件/判定覆盖)的讨论,有这个问题:在开发复杂(尤其是安全攸关)的系统时,追求逻辑上简洁、数学上“优美”的布尔表达式,与将其分解为更冗长但易于独立测试的嵌套 if-else
结构之间,是否存在一种根本性的、难以调和的矛盾?
- 上下文和资料:
- 书中原文:书中用
(isLanding && !isPilotInput) || isCriticalFault
的例子说明了一个微小的逻辑错误(将!isPilotInput
错写为isPilotInput
)可能导致灾难性后果。作者随后通过将代码分解为嵌套的if-else
结构来简化逻辑路径,使其更容易理解和测试。 - 我的思考:从数学角度看,一个简洁的逻辑表达式是清晰和优雅的。但从工程角度,如书中所展示,这种“优雅”可能隐藏了极难发现的缺陷。作者提倡将复杂的逻辑拆分,这似乎是一种为了“可测试性”和“可维护性”而牺牲“简洁性”的工程妥协。对于逻辑的详细表述以及代码的可读性,完全可以在注释中体现清楚。
- 书中原文:书中用
- 提问原因: 我的问题是这种妥协是否是必要的?我认为可以既保持逻辑表达式的简洁性,又能通过更先进的测试工具或形式化验证方法来保证其正确性,从而避免将其“降级”为繁琐的嵌套
if-else。
换句话说,作者推荐的“最佳实践”(Keep It Simple and Stupid),究竟是一种普适的工程智慧,还是在当前工具链能力不足的情况下的一种无奈之举?同时当一个逻辑条件变得极其复杂时,分解它本身也可能引入新的错误。
问题 2:在 AI 辅助编程时代,我们如何系统性地规避“Zune Bug”式的经典错误?
《构建之法》第二章第 4 页,关于 YearConverter
函数的 bug 和 Zune 播放器在闰年会“变砖”的例子,有这个问题:既然像闰年、时区、浮点数精度这类问题是众所周知的编程“雷区”,在 AI 大模型辅助生成代码的今天,我们如何系统性地确保 AI 能够主动规避这些陷阱,而不是大规模地、更隐蔽地复制这些经典错误?
- 上下文和资料:
- 书中原文:书中详细分析了一个
numberToYear
函数的 bug,它在处理days = 366
的闰年边界情况时会出错。作者通过增加一个专门的测试用例EXPECT_EQ(converter.numberToYear(366), 1981);
发现了这个 bug,并提到了著名的 Zune 播放器在 2008 年 12 月 31 日因为类似闰年算法问题而集体“罢工”的事件。 - 我的思考:这些问题可能对于有经验的程序员来说是常识。但 AI 模型是通过学习海量代码来“思考”的,如果训练数据中充满了这类有缺陷的实现,AI 很可能会把错误当成“标准答案”来学习。仅仅依靠人类在事后进行 Code Review 来发现这些问题,效率低下且不可靠。
- 书中原文:书中详细分析了一个
- 提问原因: 我对 AI 能够自然解决这类问题的假设持怀疑态度。书中强调通过增加测试用例来“事后”发现问题。但在 AI 时代,我们更应该关注“事前”预防。我的困惑是:除了依赖工程师在给出 Prompt 时主动提醒 AI “注意闰年问题”之外,是否存在更工程化的方法?例如,我们能否通过特定的数据集对通用大模型进行微调,使其对这些“经典难题”有更高的“警惕性”?或者开发专门用于“校验”AI 生成代码中特定领域(如日期处理)常见错误的静态分析工具?
问题 3:“伙伴测试”的非正式性会不会削弱其在敏捷开发中的价值?
《构建之法》第十三章第 7 页,对“伙伴测试 (Buddy Test)”的描述,有这个问题:“伙伴测试”被描述为一种发生在开发人员和测试人员之间的非正式协作,它与更正式的“结对编程”或“结对测试”有何本质区别?在追求快速迭代的敏捷开发流程中,这种非正式性是否反而可能导致它被简化或跳过,从而使其有效性难以保证?
- 上下文和资料:
- 书中原文:书中提到,“伙伴测试”是开发人员写好代码,在自己的机器上编译通过后,邀请一位测试人员来进行的“友好”测试。目的是在代码签入主干(check-in)之前,尽早发现明显的问题。
- 网上搜索:根据资料,Buddy Testing 确实是一种由开发者和测试者共同参与的协作技术,旨在通过结合开发者对代码的理解和测试者发现问题的专长来尽早捕获缺陷。它通常被视为一种非正式的检查。
- 提问原因: 我不太理解这种“非正式”协作在实际项目管理中的定位。如果它完全依赖于开发和测试人员的自觉性,那么在项目进度紧张时,会不会很容易变成“我帮你简单点两下,没问题就赶紧提交吧”的走过场形式?一个有效的流程不应过度依赖个人关系或自觉性。我的困惑是:企业在实践中是如何量化或保证“伙伴测试”的效果的?它是否应该有最低的标准,例如一个必须完成的检查清单 (Checklist)?
问题 4:稳定性和可预测性是否应该总是优于潜在的创新突破?
《构建之法》第三章第 2 页,关于 Fred 和 Bob 两位程序员交付时间的对比,有这个问题:书中通过标准差论证了交付时间更稳定的 Bob 是比平均时间更短但波动巨大的 Fred 更好的员工。这个模型是否过于简化了程序员的价值?一个团队是否应该为了追求整体的可预测性,而放弃那些像 Fred 一样虽然不稳定,但偶尔能带来巨大效率提升或创新突破的“黑马”型成员?
- 上下文和资料:
- 书中原文:表格 3-1 对比了 Fred 和 Bob。Fred 的平均交付时间是 7 天(标准差 5.3),而 Bob 是 8 天(标准差 1)。作者得出结论:“Bob 比 Fred 的交付时间要稳定得多……稳定、一致的交付时间是衡量一个员工能力的重要方面。”
- 我的实践经验:在解决数学问题或编程挑战时,有时会长时间没有头绪,但一旦找到关键思路,就能迅速完成,这和 Fred 的模式很像。而按部就班的方法虽然稳定,但往往难以产生最优解。
- 提问原因): 我部分反对作者将稳定性作为压倒性优势的观点。虽然对于大型工程项目,可预测性至关重要。但 Fred 的数据(1天、9天、11天)也可能解读为:对于某些他擅长的任务,他的效率极高(1天完成7天的估时);而对于不擅长的任务,他会陷入困境。这种专才难道没有价值吗?我的困惑是:一个健康的团队难道不应该是“稳定可靠的 Bob”和“具有爆发力的 Fred”的组合吗,我们是不是不应该简单地用标准差一个指标来否定其价值。
问题 5:AI 自动化了低层次任务,是否会阻碍新工程师形成真正的“技能”?
《构建之法》第三章,关于“技能的反面是解决问题”的论述,有这个问题:既然书中的“技能”被定义为将低层次问题(如IDE操作、基本语法)内化为“肌肉记忆”,从而解放认知资源去解决高层次问题。那么,当下的 AI 编程助手(如 Copilot)正以前所未有的方式将这些低层次问题自动化,这是否会造成一个悖论:新一代工程师因为跳过了“解决低层次问题”的痛苦挣扎过程,而永远无法形成扎实的底层“技能”,最终成为无法离开 AI 的“高级用户”?
- 上下文和资料:
- 书中原文:作者以一个不熟悉 Visual Studio 的面试者为例,说明他把所有脑力都耗费在了“解决”如何创建项目、如何定义数组等低层次问题上,根本无暇顾及真正的算法设计。作者认为,技能的提升就是不断将“学习区”的知识转化为“舒适区”的“肌肉记忆”。
- 间接经验:我观察到很多初学者过度依赖 AI 直接给出答案,当 AI 的回答有误或需要调试时,他们便束手无策,因为他们不理解 AI 生成代码的底层逻辑。
- 提问原因: 书中描绘的技能成长路径是清晰的:通过重复和练习,将“有意识的解决”变为“无意识的技能”。但 AI 似乎提供了一个“捷径”,让使用者可以直接操作高层次的抽象概念。我的困惑在于,这条捷径是否是一条“断头路”?如果一个工程师从未亲手处理过内存泄漏,他能否真正理解 AI 生成的关于指针操作的代码的风险?我们培养的到底是“能驾驭 AI 的软件工程师”,还是“被 AI 驾驭的提示词工程师”?教育和企业培训应该如何调整,以应对这个新的挑战?
更多推荐
所有评论(0)