[l.1] 个人作业:阅读与提问
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | 2026年春季软件工程 - 北京航空航天大学 |
| 这个作业的要求在哪里 | [I.1] 个人作业:阅读和提问 |
| 我在这个课程的目标是 | 在课程中体验软件工程开发的完整流程,通过团队合作产出我们自己的产品。 |
| 这个作业在哪个具体方面帮助我实现目标 | 学习软件工程中的概念和理论知识 |
一、避免“过早扩大化”和保持可扩展性之间是否存在清晰边界?
教材3.2软件工程师的思维误区部分点出了软件工程师在开发过程中可能造成延迟交付的几种思维误区。其中过早扩大化/泛化这个例子是我在过往的开发过程中最常遇到的问题之一。特别是“画扇面”这个例子——从画美女变成张飞,再变成怪石、山水,最后扇面被涂黑,讽刺了那些一开始就想“搞个大平台”而导致项目失败的现象,让我回忆起自己在面向对象程序设计课程中,迭代开发过程遇到的典型问题:
一方面,在实现功能时,容易一开始就陷入想做一个“通用的大平台”的凌云壮志中,导致耽误项目进程,连基本的功能需求都没有完整实现,最终草草收场。另一方面,我也经历过“代码写死了”的教训。尤其在课程要求的迭代开发中,经常会因为忽视数据或功能需求的可扩展性,将代码逻辑写死。在后面的迭代中就不得不经历反复的重写和重构。
书中是这样描述这个问题的:

我的困惑是如何在实际开发中,准确辨识自己正在滑向“过早扩大化”的误区?
- 是否存在一些警示信号或者红线,可以帮助我在软件设计时主动判断,我现在考虑的这个泛化,到底是未雨绸缪,还是在画扇面。
- 在“完全不考虑扩展”和“过度泛化”之间,是否有一个可操作的决策框架?比如说,我能不能遵循一个原则,快速判断我目前考虑的这个泛化是否是对于目前不太重要的扩展,或者是在不久的交付或者维护期可能会容易发生变动的需求扩展。
- 有没有一些具体的实践方法,让我在考虑代码可扩展性的同时,避免陷入“过早扩大化”?比如,我是否可以先使用比较简单直接的方式来实现,但用一些设计原则来保证我无需重构就能够扩展开发;或者直接用最简单的方式实现,等到确实需要扩展时再重构,类似等同样的模式出现三次后再抽象。上面两种方式在实际项目中有可行性么?
二、当领航员无事可做时,结对编程还有效吗?
教材4.5结对编程中介绍了一种对于我来说比较新的合作概念:结对编程。其中领航员的职责描述让我产生了一些问题。
书中是这样描述领航员的职责的:

书中强调领航员要起到“导航、检查、掩护”的作用,并指出“结对编程让两个人所写的代码不断地处于‘复审’的过程“。
我仔细地阅读这一部分关于领航员的介绍,对于结对编程的工作模式有一个清晰具体的疑问:当驾驶员正在处理的代码逻辑非常简单、清晰,没有任何需要审阅或帮助的地方时,领航员应该做什么?
我查了一些资料,团队之间对于结对编程的意见似乎并不统一:
有些敏捷团队提倡”随时结对“,他们认为即使是简单任务,两个人一起做仍然可以避免低级错误,并且保持”共同拥有代码“的意识可以提高代码质量,提高复审效率。另外也有团队认为,让两个人结对做简单任务是对人力资源的浪费,建议只对高风险、复杂、探索性的任务进行结对。
我的困惑是:在结对编程中,是否存在一个”任务复杂度阈值“——低于这个阈值的任务不适合结对,高于这个阈值的任务才值得结对?
- 如果领航员无事可做(这个无事可做指的是任务简单到即使驾驶员自行完成也可以保证高的代码质量),结对编程还有继续的必要吗?领航员在这个时候难道应该”放空”,等遇到复杂问题高效投入?
- 如果继续,领航员是否有办法高效利用这段时间?或者思考更高层次的问题,解决代码的可扩展性或者与思考与其他部分的隐式耦合;或者去搜索开发必要的其他工具、技术文档等,提前阅读提高后续工作效率。
- 是否有可能实现“动态结对”?——只在复杂、关键的任务上进行结对,而简单的任务让一个人完成。提高简单独立任务的工作效率和并行度。如果是这样的话,我们应该如何定义“复杂”的阈值?如果状态频繁的在结对和独立开发中切换,会不会破坏合作的连续性?出现包括代码风格不统一、代码不兼容和共同代码意识减弱等问题。
三、敏捷流程中的“欢迎变化”和“保持敏捷性”之间,到底应该如何平衡?
教材6.1敏捷的流程简介中介绍了敏捷原则,其中的第2条提到:“敏捷流程欢迎需求的变化,并利用这种变化来提高用户的竞争优势。”另外在6.2敏捷流程的问题和解法中,也提到了冲刺中途变更需求的困难:


我结合本篇教材中介绍的敏捷开发流程,发现了一个开发过程中的矛盾:敏捷流程中的”欢迎变化“和”保持敏捷性之间,可能存在内在的张力?
敏捷原则中明确:欢迎需求变化,并把这当作竞争优势。但另一方面,敏捷的具体实践又要求团队在一个Sprint内专注燃尽自己分工的任务,不受外界干扰。原文中提到,这种专注是敏捷团队能够快速交付、保持可持续节奏的基础。
那么如果在Sprint途中,真的发生了重要的需求变化,团队应该如何应对?
如果团队坚持原则,拒绝变更,等到Spring结束再处理。那么是否延迟了需求变化的处理效率,而且让“欢迎变化”实际上编程一句空话,让利益相关者可能觉得团队“不敏捷”,进而错过市场机会。
如果团队接受变更,立即调整计划。原Sprint的承诺就会被打破。或者团队需要暂停所有正在执行的开发来保证进度重新分配,或者团队被迫加班赶工,甚至砍掉原计划中已经承诺的功能。这可能会打破团队稳定的节奏,起码燃尽图就会变得混乱。这样会不会让团队从一个敏捷的团队,变成一个随时被打断、疲于应付的团队(用户的需求变化可能是源源不断的)。
上面书中那个例子似乎是在主张”Spring期间不接受变更“,但这是否与”欢迎需求的变化“主张是否矛盾?
我的困惑是:敏捷流程的”欢迎变化“和”保持敏捷性“之间,到底应该如何平衡?
- 如果接受Spring中途变更,会不会破坏敏捷流程的核心优势,如可预测性、可持续节奏?
- 如果拒绝变更,又会不会让团队变得僵化,违背”响应变化“的初衷?
- 是否存在一个决策框架,可以帮助团队判断什么样的变化值得或者需要打破Sprint,什么样的变化应该延迟处理。
四、如何确保我们通过“人类学调查”发现的是用户的“真实需求”,而不是认知偏差?
阅读了教材8.3获取用户需求——用户调研中关于人类学调查的论述,那段学生的感想给我留下了相当深刻的印象,也引起了我关于发现用户群体真实需求的思考:

这个学生体现出了一个明显的工程师偏见的例子——他以前鄙视360和hao123这种服务,后来发现自己错了,他认为中国市场的用户没有很多精力管理电脑,他们更需要傻瓜式的一键解决。但是如何确定这个结论真的是中国市场用户的真实需求呢?
我考虑的是,其实这两种思考都可能是”工程师偏见“,本质上两者都包含了思考者的主观考虑。前者按照”极客标准“衡量用户,后者又使用”下沉市场标签“来理解用户。但这两种思考本质上都比较极端地标签了用户,都可能错过更深层的、更本质的真实需求。
比如,用户用hao123,真的是因为不会输入网址吗?有没有可能是”懒得记住详细复杂的网址名”?或者“习惯性在集成的导航页开始上网?亦或者是”导航页提供的信息可以帮助他们选择自己感兴趣的网站“?这就可以做出不同的产品:如更加轻量化的收藏网站工具;更加吸引用户兴趣的新闻短讯投放。
我认为观察者的文化背景、认知框架等主观因素会决定他看到什么或如何解释自己看到的。即使我真的和老人在一起生活了一段时间,我看到的也可能只是我能理解的。
我的困惑是:当我们通过人类学调查发现了一些“反直觉”现象时,我们该如何判断或挖掘真实用户需求?
- 这些我们认为的用户需求,是不是我们主观的工程师偏见的认知偏差?
- 有没有一套方法可以让我们验证观察的准确性,或者尽量让我们可以客观地发掘出真实的客户需求,避免用新的偏见代替旧的偏见?
五、当风险来自团队内部(如人员离职)时,PM能做什么?
我阅读了教材9.5PM和风险管理,这一节详细地辨析了PM需要识别风险、评估影响、指定应对方案。但在教材中,虽然举了很多例子来分析项目进展过程中可能会出现的风险,但是对于“人员离职”这种来自团队内部的风险,并没有深入讨论,我认为这是一个相对棘手的问题。
“人员离职”作为一个风险,和一般的技术风险、需求风险有很大不同,它牵涉到更多关于团队的问题。PM不能像对待“服务器可能宕机”那样,公开讨论某某可能要离职。也不可能简单地写在风险清单上那样简单:“核心开发人员某某有20%的概率下个月走人”,量化并等待大家公开讨论解决方案。
书中讨论的解决方案中:

没有点出能够直接缓解上述问题的方案。我也构思了几个困境:
- 如何准确地识别风险,而不是过于愚笨或者疑神疑鬼。PM需要提前知道谁可能离职,但又不能直接问“你想不想走”,那作为PM应该观察那些指标才能分析出离职信号,过度的关注会不会伤害团队信任。
- 当离职真的发生时,PM第一时间应该做什么?如果最坏的情况发生了,一个核心成员真的撂挑子了。这个时候PM是应该直接开始交接工作,还是和即将离职的核心成员谈条件。又如何能够稳定住其他观望的成员,不让核心成员的离职影响团队的士气。
- 如何从离职中获取团队状态。作为PM,面对这种严重的突发情况,应该关注团队状态,特别是PM不理解离职行为的时候。PM如何巧妙地设计一些访谈,听到离职人员的真实原因,才能够及时补救自己的团队管理。
因此,我的困惑是:对于人员离职这种来自团队内部的风险,PM到底能做什么?
六、“小强地狱”的困境:Bug数量阈值能平衡开发与修复吗?
我阅读了教材上11.5.5小强地狱的内容,这一节通过一个真实开发的场景来引出了一个具体的问题:开发人员的手头挤压了大量的Bug,但是他们总是倾向于优先开发新功能,导致测试人员没有办法收到Bug修复,不能进行下一步测试。教材中给到的方案是:

如果超过Bug阈值,开发人员就会被送入所谓“小强地狱”,被迫地只能修复Bug,不能开发新的功能,直到Bug修复到阈值以下。
听起来相当直观的一个机制,为了解决开发人员手上Bug数量累计过多以至于耽误测试进程的问题,人为规定阈值来保证Bug稳定修复,强制手段打破“重开发轻修复“的惯性。但是深入思考之后,我发现一些困惑:
- 是否存在一个方法确定一个合适的阈值。如果阈值调整过高,可能就会导致开发人员无法重视修复Bug的必要性,惯性地将Bug积累起来再统一修复。这样仍然打破了测试的连续性,失去了阈值的作用;如果阈值调整很低,所有开发人员都进了地狱,新功能的开发进度就可能被经常搁置,就会让开发变得不再敏捷。
- Bug数量是否能充分反映问题的严重性值得考虑。故事中是以一个测试人员的视角来审视开发问题,但是从客观来看,开发人员手里积压了一些自认为不影响大局的Bug,真的值得停下新功能开发的角度去做紧急修复吗?比如说,一个开发人员手上有30个”按钮颜色不对“的UI小Bug,另一个开发人员手上有一个”支付可能会丢单“的核心逻辑Bug。数量真的是评价问题严重性的指标吗?如果不是,那我们应该使用怎样合适的指标来判断。
- 这个机制会不会对开发产生阻力?我们设想一个开发人员知道自己快进地狱了,他会不会在进地狱之前赶紧把新功能的半成品赶紧提交,反正Bug可以慢慢修。或者他会不会故意留存很多救命Bug,让自己轻易保持在阈值以下?这些心里会不会给开发团队带来阻力,甚至干扰团队开发状态?
因此,我的困惑是:”小强地狱“这个机制,在实际项目中应该怎样表现,才能够有效推动Bug修复,同时保证士气,稳定开发效率?是否存在一个比”计数+阈值“更加精细的方法,来动态平衡”开发新功能“和”修复旧Bug"的关系?
七、软件的“防呆设计”和“功能强大”之间如何平衡?
我阅读了教材重12.1用户体验的要素中关于不让用户犯简单的错误这一节的内容,作者通过USB接头设计等例子从正反面分别辨析了不让用户犯简单的错误这个观点,减少了认知阻力和设备损坏的风险。
但这可能引出一个经典的矛盾:防呆设计和功能强大之间往往存在张力。
比如,微信的界面相当简单,不太可能进行误操作。但是这也导致你如果想做一些稍微复杂的事(批量管理聊天记录、自定义消息提醒规则),会发现根本找不到入口。相反,Photoshop功能非常强大,但是新手打开软件的时候面对密密麻麻的菜单和工具时,也是无所适从的,误操作的概率也会变高。
我认为这两种软件的设计背后是不同的用户假设:前者假设用户需要简单、安全、不用思考的软件;后者假设用户愿意学习、探索、换取更多的控制权。但很多软件可能会同时服务于这两种用户,或者用户在不同的阶段有不同的需求。
我的困惑是:软件的“防呆设计”和“功能强大”能不能平衡?
- 是否存在一个相对系统决策框架,可以帮助设计者判断某个功能应该防呆保证安全,还是应该提供强大的复杂控制。
- 如果真的需要在两者间进行取舍,是否存在一个标准来衡量用户群体,帮助我做决定。
- 有没有可能在不牺牲功能强大的前提下,通过巧妙的交互设计能够同时满足两类用户的需求。
八、创新在软件工程课程作业中,是必须的吗?
我阅读了教材16.2创新的时机和16.3创新的招数。书中详细讨论了不同类型的创新,分析了先发优势与后发优势的辩证关系。书中特别指出:
创新并非凭空产生的灵感,而是在深入理解用户痛点、技术趋势和商业模式的基础上,自然生长出来的解决方案。
如果我们将目光从工业界转向高校课堂,一个现实的困惑就是:在为期16周、5-7人规模的软件工程课程项目中,是否应该鼓励”创新“?如果在如此规模的开发中强调创新可能会出现的几种问题:
- 为了创新而创新,陷入形式主义陷阱。团队可能为了让评委眼前一亮,强行给出一个基于早已成熟定型的系统嫁接一些花哨但不适用的创新功能。比如熟知的图书管理系统。
- 画扇面的骗局。团队可能会产生一些”雄心壮志“,市面上的所有工具都不太好,我们打算实现一个通用的平台,一个颠覆性的框架。这个想法可能值得鼓励,但是业界都没能解决的问题,短时间内以这样的规模基本不可能解决,反而会沦为一个千疮百孔的半成品。
- 忽视用户需求的自嗨。可能团队可以想出一个自认为绝妙的点子,团队认为这个功能绝对会火。但是创新带来的好处,可能不足以覆盖用户放弃旧习惯、学习新工具、投入新行为的成本,这个创新就很难走出实验室。
因此,我的困惑是:在高校的软件工程课程这个特定场景下,”创新“到底应该摆在什么位置?PM应该如何引导团队在不偏离项目目标的前提下,进行适度的、有价值的创新?

浙公网安备 33010602011771号