时效性 or 高质量,程序员在发布软件时该如何选择?
一般来说,你只能选择按时发布软件,或者发布高质量的软件,但两者不可兼得——除非你处于一个成熟的、高效率的团队,且次数屈指可数。
以下为译文:
过去几个月内,我一直在思考为什么我们不能在遵守预算和计划的同时发布高质量软件。在我的职业生涯中我经历了许多不同的项目(瀑布式,真正的敏捷开发,以及敏捷加瀑布等),但所有项目的共同点就是:无论是哪种项目,如果想“做好”(即不使用任何会造成麻烦的捷径),那就必然不能按期完成。
另一方面,如果项目能“如期”发布,那么一定是项目范围被删减了,或者我们不得不抄近路从而积累下许多技术债务,导致上线后不久就得重写。我不禁想:如果一个项目做得很丑、无法维护、充满bug,或者用最直接的话来说,如果它只是最初计划的一个垃圾实现,那这个项目还能算是“如期”完成吗?
我也经历过没有截止日期的项目。当然,“截止日期”还是有的,但不会放在里程碑里,大家都同意截止日期是灵活的,与如期发布相比,项目的质量更重要。这种项目能产生最好的软件,开发者也十分愉快,是我经历过的所有项目中最成功的项目。但我们都知道这种项目很罕见,否则我就不用写这篇文章了。
那么,究竟为什么在固定的截止日期前按照计划发布高质量软件如此困难?我认为这与创造性、工匠精神和不可预见性有很大关系。
编程的创造性
我认为,软件开发本身是个创造性的行为。当然,一些程序员做的是重复性的、不重要的工作,但他们的工作只发生在自动化尚未实现的情况下。因此,这些工作并不重要,也不是这篇文章的重点。
在我看来,软件开发中包含了一些特别的东西,那就是创造新事物并寻找原创解决方案的行为。我相信不止我一个人有这种看法。实际上,我相信创造性正是开发者喜欢工作的原因。以我的经验来看,如果我在有严格、无法改变的“实践指南”(可以是技术栈、过程、指南等)的环境下,也就是说环境越不自由、越没有创造性,我的参与感就越低。我会想,“毕竟,他们都已经全搞定了,还要我干什么?”而另一方面,如果环境中很少有从上至下的指令,并可以发挥自己的创造性,而且别人信任我的技术决定的话,我会感到非常满足、非常兴奋,效率也会非常高。
很重要的一点是,创造性和自由越多,越会导致解决问题的路上出现许多试错的过程。这其实很正常。一些人认为,写代码之前可以预先知道最好的解决方案。而我认为,对于创造性的活动,发现给定问题的解决方案的过程(不仅限于软件)是个修补的过程。不可能预先知道最优解,相反,你需要通过实践和反复的尝试来找出解决方案,并通过不断优化解决方案(如果采用敏捷开发,可能还包括发布给客户的行为),直到找到满意的方案为止。
想想你曾经多少次为了设计一个功能在纸上花掉许多时间,结果一开始实现就发现整个设计都要修改。我们永远都不知道有多少未知数,发现未知的唯一办法就是通过实践,实际地去写代码,而不是花上很多时间去研究理论,并假装我们能事先发现完美的信息。这种修补的过程并不能很好地适应估算。
进一步来说,和其他创造性行为类似,编程可以从“战略性拖延”中获益。这个词(https://www.meaningfulhq.com/strategic-procrastination.html)是由Adam Grant发明的,它的命题是,创造性并不是随叫随到,它是思维背后的一种“推送”式的活动:
“经常拖延的员工会在发散式思维上花费更多时间,但拖延并不一定会产生创造性,如果员工本质上没有解决某个主要问题的动机,那么无所事事只会让他们落后。但当他们热衷于考虑新想法时,延后任务可以让他们想出更有创造性的方案。”——Adam Grant,《原创:不墨守成规的人如何改变世界》
同样,处于中心的计划者试图计划一切并度量软件开发项目的每一分钟,并不是好消息。
构建软件的工匠精神
我所知的最好开发者都是工匠。“工匠精神”是高质量软件的标志:你不仅是在构建能用的软件,而且是用最好的方式构建。做个能用的东西很容易,但做个能用一辈子的东西很难。
作品的质量成就了工匠自身。你不断追求质量,只因为你不想写出垃圾软件,虽然你知道只要让软件“看上去不错”,就算里面一团糟,也能在产品经理面前过关。我称后者为“惊喜开发”。你知道在编写高质量软件上投入时间是值得的,而且你会拒绝那些“快点完成”的眼里,因为你知道,现在走越多的捷径,代码的生命就越短,而且会造成越多的问题。
我也是醉了
# 你可能觉得这个函数没用,而且貌似什么都没干。
# 相信我你不是一个人。但要是删掉这个函数的话,
# 整个程序就会蜜汁崩溃,我也不知道为什么。
# 所以先放在这儿吧。
工匠精神的核心就是在乎。在乎做好每项工作,在乎以后维护代码的人,在乎软件使用者的心情,在乎团队成员,等等。你在乎这一切,因为你知道自己不是混蛋,也知道只有在乎才能想让项目成功。
长话短说,好的工程师能完成最难的任务——在乎质量。在这个一切求快的世界里,只有这样才会有长期的结果。
在实践中,这句话的意思是:
在封装、可扩充性、可扩展性等之间找到合适的组合。同样,你需要反复试错,没人能一下子写出最好的方案;
发现坏代码时花时间重构;
写高质量且完备的测试用例,甚至采用TDD;
与同事进行结对编程。
毋需多言,这一切都不能提前预测,所以没办法帮你遵守任何截止期限。
预测总是错的
“需求从来不会明确,但就算有了明确的需求,也几乎不可能知道某项需求需要的时间,因为我们从来没做过这个需求。我们要是做过,那早就告诉你了。”——Ron Jeffries,《拒绝估算运动》
软件项目是个复杂系统,它们由人类创造,因此会受到人际关系、动机、交流问题、人类心理学等的影响,其中任何一项都很难建模并在数据表中量化。因此,软件工程很难建模,进而很难预测。Nassim Taleb在他的书《反脆弱》(Antifraigle)中说:
“复杂系统充满了难以检测到的相互依赖,和非线性的响应。‘非线性’是说,比如将药物的剂量加倍,或者将工厂里的员工数量加倍,得到的效果不会是两倍,而是更多或者更少。就像是你在费城度假两周,并不能得到度假一周的两倍的快乐一样。”——Nassim Nicholas Taleb,《反脆弱》
更糟的是,如果考虑到时间不能为负数,那么任何计划外的“意外”都会延长完成所需的时间,因为产出是不对称的:
“由于时间不能为负,三个月的项目不可能用零或负数时间完成。因此,在从左至右的时间线上,错误会加在时间线的右侧,而不会加在左侧。假如不确定性是现行的,我们一定会看到一些项目能提前很长时间完成(就像我们到达的时间有时会很早,有时会很迟一样)。但实际情况显然不是这样。”
这是个坏消息,因为我们唯一能确定的就是不确定,即使是估算单个任务时产生的最小的错误,在整个项目的范围上也会以指数形式叠加。这还是假设了最好的情况,其中截止日期是在开发者们进行谨慎估算后得出的,但真实情况经常更荒谬:大多数情况下,“业务人员”随意设置截止日期,之后工程团队才能按照这个随机选择的时间点来制定完成需求的计划,最坏的情况就像是盖房子先盖屋顶,把马车套在马的前面一样。
下面这些例子描述了编写软件过程中的一些非线性反馈循环:
你假设你要使用的API会接受accountId,但实际上它只接受memberId。因此你不得不在估算中加上四天时间来重构API代码,进一步导致代码需要经过一整套审查流程,从而再增加两天。
一项估算时间为两天的任务画了一个星期,因为在审查过程中,一名团队成员(正确地)让你去做代码重构,以改进很久以前遗留的一段糟糕的代码。
一项只有一个故事点的任务需要实现一些新功能,而这些功能碰巧需要更新一些依赖,进一步造成了许多编译错误,于是像链式反应一样不得不更新许多依赖,最终花了四天才完成。
我们搞砸了吗?
我们一直在做估算和计划的游戏,来保证自己知道自己在做什么,但其实我们什么都不知道,而且软件项目是完全不可预测的。因此我的观点是,还不如把精力花在做事情上,而不是计划上。都来做 #拒绝估算(https://ronjeffries.com/xprog/articles/the-noestimates-movement/) 运动吧?当然这个运动不会多数组织接受,他们会说:“我们不能让工程师来导演没经检查的事情,我们需要审计!”就这样。
那该怎么做?我认为应该用某种方法来填补工作表和IDE这两个世界间的空白,为工程师们提供最大的创造性、灵活性和工匠精神,同时谨慎地管理任何错误,以及项目干系人的期望。工程经理就是担任这个桥梁的最佳人选,可以很好地填补两个世界间的空白。这项工作并不容易,却是必须的。Aaron Longwell在他的文章里解释了这一点:
“因为工程经理位于业务和技术之间的位置,他们应该负责解决估算和现实之间的冲突。就像是一条绳子的两端,哪一端的人都可能会赢。如果业务的人赢了,开发者就会陷入泥潭。如果开发侧的顾虑压过了业务的人,那预算和截止期限就没办法遵守了。不论哪种情况都是失败。成功的软件经理要找到灵活的方式,柔和地解决这些冲突。找到这种灵活方式的最好方法就是仆从式领导。”——Aaron Longwell,《为什么软件开发需要仆从式领导》
此外,在产品和工程之间建立基于信任的强大关系也是非常重要的。有了信任,才能自信地用诚实、开放的方式沟通时间线。如果你之前的行为证明了团队能够发布高质量软件,那就有了足够的“社会资本”,项目干系人就会在你推后计划时信任你是出于好意。
我个人作为经理的另一个“技巧”就是避免设定固定的日期,因为固定的日期必然会被当做截止日期。模糊的日期范围最好,比如“三到五周之间”。然后,越是临近这个模糊的日期范围,就越应该给它加上更明确的定义:四月初的时候“在四月到五月之间”变成“4月15日到5月3日之间”,4月10日左右变成“4月20日那一周”,等等。这样可以向其他人开诚布公,同时给团队提供解决不可预见的问题的灵活性。
最后,别忘了开发者才是对产品质量负责的人,而不是项目干系人。组织间出现似乎有分歧的冲突是很自然的。其中的关键是,你要认识到大家的目标都是一致的,即用最快的方式为客户发布高质量的软件。只有优秀的开发者才懂得,你应该避免采用“快速且容易”的方式,因为长期来看,这种方式实际上会降低开发速度。
软件项目虽然是个复杂且常见的问题,但并不是无解的。我想说,如果你觉得你的经理或公司不给你提供构建高质量软件的条件,那么你可以找他们谈话并谋求改变,即便这样还是不行的话,就换份工作吧。
原文:https://hackernoon.com/you-have-to-choose-between-software-delivered-on-time-and-good-software-44f4af1249b1
作者:Joan Gamell,LinkedIn的软件工程师。
译者:弯月,责编:郭芮