(给
伯乐在线
加星标,看经典文章
)
编译:伯乐在线/dimple11
【导读】:如果你有不会写代码却要管理程序员的领导或上级,那本文就是要给他们扫盲软件开发的基本常识。比如:为何软件开发工期难以估计、为何开发速度那么慢、为何程序员要“浪费”时间写测试以及做代码审查(Code Review)?
更快,更好,更便宜——软件开发的艺术
没人想交付延迟的、超过预算的软件,我从没见过一个软件开发者会大早上起床后心里想着“我就想把工作干得很差劲,我怎能让老板花更多钱呢?”但是,有太多的软件项目进行得都并不顺利。而且对于每一个新项目来说,似乎在加快软件开发速度方面的压力变得越来越大。所以,如果我们正在从事软件开发的工作,那么我们应该怎么做呢?我们应该如何在不降低软件质量的前提下加快开发速度呢?
虽然历经 50 多年的历史,已推出无数方法、建议和书籍,但是 IT 项目仍总是经历失败。——Susan Moore [1]
现在,我不是以某种专家的身份在这儿写东西。我从没运营过自己的软件公司,也没传播从丰富的学术研究或对照实验中提炼而出的理念,我写这篇文章是为了组织我自己的想法,因为我想要设法了解我所看到的周遭所发生的一切。
为了正确地看待此事,我们首先需要搞清楚为什么要开发软件?所有软件生产的意义是什么?我们为什么最开始要做的就是开发软件?咱们暂且把开源当做房间里的大象搁置一边,先来探讨一下商业软件。咱们先从生意说起。
生意就是指减少客户的痛苦
按照我的理解,为了达成一笔成功的交易,我们首先应该找到使人们痛苦的东西(找痛点),可能是一种隐喻形式的或字面形式的痛苦(但通常是隐喻形式的),然后我们以钱作为交换,为他们提供减少痛苦的方法。例如,人们发现编程很难(很痛苦),所以开辟了编程书和编程课的市场;有些人不喜欢他们自己的外表,所以带动了健身、化妆品、美容等等整套完善产业的发展。生意从某种程度上给客户传达的观念是它们可以减少客户的痛苦(或对痛苦的感知),而且如果人们相信我们可以减少他们的痛苦,那么他们就会很乐于给我们付钱。
在软件产品业务中,软件就是我们用来减少客户痛苦的东西。对于这种类型的业务,软件开发就是提供价值的关键环节。客户买(或订购)一件产品,那么软件开发这一环节负责把它开发出来。当然,这只适用于产品业务。如果我们把咨询服务或IT作为一种支撑功能进行售卖,那么情况就会有所不同。可是但凡主要核心业务是软件产品的,那么完成该业务的手段就是软件开发。
这不是说软件开发就是增加价值的唯一方式。例如,要是没人知道我们的产品存在,那么还不如说它真的不存在呢,所以产品的营销和推广活动也是至关重要的。我们也需要确保我们的产品实实在在解决了客户的真正痛点,否则,我们就是在浪费时间,所以市场调查(无论是正式的还是自组织的)同样是非常重要的。产品中的摩擦是我们解决客户问题时的拦路虎,我们也需要用户体验(UX)和图形设计活动来减少摩擦,所有的这些活动(营销、销售、市场调研、UX、设计)都很重要,而且如果你略微瞄一下,它们看上去都挺相似。它们就好比同一个核心活动的不同方面,这个核心活动就是理解他人。但是归根结底,所有的这些活动只为客户价值提供计划和承诺,而将所有的计划和承诺转化为实际的产品的则为软件开发。[2]
当你接受了其实“产品”、“设计”和“工程”仅仅是同一件事的不同方面这种观点时,事情便都会进展得更好。——Greg Veen
将开发时间对业务的影响最小化
如果我们能够很好地做到“理解他人”,那么软件开发这项活动就能稳步推进。在软件开发过程中,我们会更加了解那些我们致力于解决的问题,所以我们可以开始设计更优的解决方案,因而我们创造的软件产品也需要有所改进。为了实现此目标,我们需要一支敏锐的开发团队、一支可以快速传播价值并且迅速应对变化的团队,这是软件开发实践中的核心目标。正如 Dan North 指出:
“软件开发的目标是持续尽力降低软件开发时间对于业务的影响。”——Dan North[4]
所以,拥有一支敏锐的开发团队至关重要。但是如何能够拥有一支敏锐的开发团队呢?你会:
-
将开发者像王一样供奉?
-
给他们买超快的、昂贵的计算机?
-
把他们送到任意他们想要参加的疯狂科技研讨会?
我们有很充分的理由做任何这种事:如果你想要维系你那支敏锐的开发团队,那么就要对团队中的每个人都认真上心。运行快的计算机和优良的科技研讨会使开发者表现得更好,这种对开发者的投资总有一天会得到回报。但是这种投资对留住优秀的开发者更有用,而我们想要组建的是一支敏锐的开发团队。
所以如果不给开发者提供他们所想要的,那么我们该做什么呢?简单的答案是,去问开发者。但是,请在合适的时间,用合适的方式问他们。我们需要理解的一点是,开发者往往是天生的问题解决者。优秀的开发者热爱他们的工作,热爱的原因是他们整天能解决有趣的、复杂的难题,并且能够因此而挣钱。优秀的开发者陶醉于迎接复杂的挑战并且找到简约漂亮的解决方法。所以他们应该能想出精彩的点子以变得更加敏锐。但是许多组织鼓励开发者专注于错误的问题,这种鼓励可能既不是深思熟虑的也不是有意而为之,但是却时常发生。
专注于错误的问题
这是怎么发生的?我们怎么可能甚至不知道自己在做错事,以至于最后让开发者专注于错误的问题呢?因为我们将开发者从消费者身边拉开。一个项目一有任何合理的规模,我们就会找来项目经理和业务分析师。[5] 我们拉来这些人是出于一个非常好的理由——开发者无法完成所有的事。软件项目是复杂的,代码已经够复杂了,但是另外更重要的是,还有各种工作诸如决定构建的内容、规划开发的阶段、制定推广部署的计划、联络客户……不一而足。代码已经够让开发者操心了,所以我们需要这些额外人员来帮忙。
但是,这样做使得这些额外人员成为了开发者面向世界的接口。与外部持股者进行协调沟通的是项目经理和业务分析师,尤其是项目经理非常在意项目的交付。项目经理向管理部门汇报情况,管理部门关心的是:
于是我们可以理解为什么之后项目经理开始变得专注于预测项目了。他们想要计划、结构、评估,他们想要知道什么时候在发生什么事。当他们向管理部门汇报的时候,所做的预测和估量会让他们显得更称职,所以他们才会向开发者探讨预估、报告和截止日期。所以之后,开发者开始专注于预估、报告和截止日期,他们将精力集中在这些预估和预测性上来让取悦项目经理。
但是这样做有一点不如人意的是,预估和预测性都是不可能解决的问题。每次一个开发者开始着手一个新任务时,他们就面临一个不安的事实:任何一个给定的任务背后都可能有一个潜在复杂性的大坑,也可能没有。我们都希望任务是简单的,但是它有可能并不简单,你永远都不会知道。这时霍夫史达特定律就起作用了:
霍夫史达特定律:事情总是要比你预期的花费更长的时间,甚至当你把本定律考虑在内时也一样。——Douglas Hofstadter[6]
考虑这种情况:
一个项目经理向一个没经验的开发者问项目的估算,这个没经验的开发者告诉了一个他们认为合理的估算,然后项目经理回去根据估算情况得出截止日期和相应的计划。优秀的项目经理为稳妥起见,甚而会在此基础上加上一点“富余”。但是之后不可避免的事情发生了——项目落后了。所以开发人员开始为赶在截止日期到来之前完成任务,开始加班加点地工作。但是长时间的工作使得开发人员疲惫不堪,他们便开始犯更多的错误。而且不仅如此,项目仍然在落后。项目经理需要知道到底是什么耗费了这么长时间,所以苦恼的开发者图省事,开始投机取巧偷工减料,这一过程中,程序漏洞源源不断地出现,所以此时产品不仅延迟了,而且漏洞频出。
这种情况传达了一种消极的客户价值。当然这种延迟的、漏洞频出的产品可能仍然能够解决某种程度的客户痛苦,但是这些漏洞带来了新的痛苦,这又需要耗费时间来进行修复,这样客户就会对我们可以帮助他们的能力丧失信心,这使得他们更不想为我们付钱,到头来无人从中获益。
经验丰富的开发者知道这种估算是不公平的,所以他们尽其所能不蹚这滩浑水。
想象一下,
一个项目经理来找有经验的开发人员问预算,开发人员便会回复他一个大到离谱的数据,但同时又小到使这个项目还不能立马被取消。接下来,项目经理(销售人员)回头开始质疑这个荒谬的数据:“那个预算看上去比我们希望的多一点,我们有没有可能缩减一下,让预算少点?”这时,有经验的开发者便会问:“我们着手需要的预算是多少?”销售人员回复他一个数,然后有经验的开发者揉揉她的下巴说:“预算有点紧,但是我们会尽量做。这样的话我们难以满足所有要求,只能提供最基本的性能。”然后她会在自己看上去不会不称职的前提下,预估他们可以承诺交付的是多么有限,并且这是她可以承诺的所有。这样的话,如果她最后交付的比自己先前承诺的更多,那么每个人都很开心。但是甚至在这个情况下,霍夫史达特定律还是会出现,过不了多久,我们就会像从前一样,在赶最后期限、交付低质量代码的泥潭中苦苦挣扎。
预算是软件开发过程中一项必不可少却令人生厌的东西。不幸的是,人们往往以为编软件就像建房子或修车一样,承包商或参与的机修工在客户审批工作前,应该能很好地对要完成的工作提供一个可靠的预算。[……]然而对于定制软件,很多系统都是从零开始搭建,而且通常组装、最终运行、应实现的功能、完成的时间等等都在随时发生变动,因此在工作之初,你要选的方法和最终达成的效果都是不确定的,所以很难知道到底什么时候可以完成。——Steve Smith[7]
我这儿的观点不是说要抱怨软件预算,大家都知道它虽然令人生厌但又十分必要,就怪这种软件预算会陷入一种恶性循环。为了赶截止日期,我们投机取巧偷工减料,交付低劣的代码,还一直互相保证我们过后终将回头将代码进行完善,但是“过后”再也不回来。如果我们回头修复那些漏洞的话,我们就已经在下一个阶段中又落后了。所以我们构建的一切都建立在脆弱的、杂乱一气的代码上,这些代码难以应对快速的变化。而且一旦困在这个循环中,那么开发者的注意力将难以继续集中在解决客能户痛苦上,相反,他们将会专注于诸如以下的问题上:
-
有什么可能的方式能使我们最快地将任务标为“已做”并且让项目经理不要再烦我?
-
我怎样才能尽可能少接触脆弱的代码呢?因为这些代码我接触得越多,它们崩溃的可能性越大。
-
我怎样才能在这笔巨大而过火的技术债务中,竭力维持让我引以为豪的那一小块代码呢?
-
我怎样才能向那些不知道我在干什么,或者不知道问题的复杂性的人们证明我的决定是对的呢?
-
当客户开始抱怨那些我没有时间修复的软件漏洞时,我怎样才能将责任推到其他人身上呢?
-
我怎样才能在我的简历中加入一些流行语,帮我另找一份不这样混乱不堪的工作?
我没见过有开发者想要交付一份延迟的、满是漏洞的软件,但是我们因为想要他们速度放快,所以给开发者不断施压。他们为了取悦我们也答应照办,但是由于预估往往是错误的,所以导致他们深陷泥潭,在重压之下交付软件。他们为了取悦我们,加班加点工作,但又在软件开发中偷工减料。因为大家一直在催问他们“完成了吗?”使得他们在软件质量上做出妥协。最终没有人开心,软件仍然拖延,仍然满是漏洞。
所以我知道的大多数开发者都在工作中尽其所能,但却深陷困境。他们为了赶进度忙得焦头烂额,甚至连怎么变得“更快”都顾不上想。因此他们把精力集中在了错误的问题上,他们重点关注的是如何让自己活下来。好比当你饿得快要死了的时候,你很难再去关注为退休攒钱的事儿了。也好比当你因为一个延迟的项目一周连续工作七天后,你很难再去计划怎样才能做得更巧。所以第一步应该承认,想要项目做得更快就需要投资,而且如果事情进展不顺,那么也同时需要时间/财政投资和情感投资两项。
打破这种恶性循环
之前,我建议去问问开发者怎样才能减少软件开发时间对业务的影响,但是当开发者处于“赶进度”模式时,我们不可能得到从他们那儿得到很好的回复。当我们进入这种环境问道:“我们怎样才能开发得更快?”可能会得到两种回复中的一种:
1. 用火烧了它。
“我们需要出走两年,然后重头再来。”这种情况通常在开发者已经被技术债务彻底压垮时发生。技术债务太繁重了,所以他们感觉唯一的出路就是宣告破产。他们这样做可能也有一定的道理,但与此同时,我们可能并没有相应的预算作为支撑,而且当我们过后重建的时候市场必然不会一成不变。
2. 愤慨。
“我们已经开发地更快了,我不敢相信你竟然觉得你只用半个小时的头脑风暴就能修复这个复杂的问题!你怎么敢?!”这种情况通常在开发者觉得自己被迫发行低质量代码时发生。他们感觉当客户抱怨漏洞时,自己受到了客户的谴责。而且他们的愤慨很可能是有一定理由的。开发者怀着这种心态是不会帮我们的,除非我们可以向他们表达我们听到了他们的心声。他们需要知道我们理解他们的顾虑,我们同样也需要表明我们正在严肃地考虑做一些改变。
在以上两种情况中,开发者的顾虑是正当的,但他们只关注了自己。我们希望创造一种每个人都为将软件开发时间对业务的影响降到最低而努力的环境。如果开发者不能摆脱这种心态的话将难以达成以上愿景。一切策略开始的前提是,向他们表明我们正在严肃地考虑做一些改变,这通常包括寻找减压的方式,即使那只是暂时的。
但是即使这样,开发者仍然只会关注自己,除非再做一些改变。他们关于如何提升自己的工作成效会有大量的主意,其中一些想法可能很不错,但是有风险。我们需要让开发者转移对自身压力的关注,而将注意力集中在将软件开发时间对业务的影响降到最低上。我们需要让他们直面客户痛苦。
使开发者直面客户痛苦
我们接下来该如何使开发者直面客户痛苦呢?不计其数的人已经对此写过详尽的文章,所以这里我只是轻描淡写一下。这儿按照从最低效到最高效的顺序有三条观点:
1.让开发者将使用自己制造的产品作为他们日常工作的一部分。
这在业界被称为喝自己的香槟,或吃自己的狗粮。这样做的好处是使开发者变成了产品的用户,所以任何明显的错误或问题也会令开发者自己感到烦恼。这种方法存在一个问题,那就是开发者并不是典型的用户(大多数时候)。开发者使用软件的方式通常有别于大多数的客户,所以尽管这样可以帮开发者修复主要的漏洞,但是可能无法为典型的使用案例提供很好的见解,而且这也并非一直具有实践性。比如说,假想我们正在为牙科保健员生产一个SaaS产品,这时开发者可能很难将这SaaS产品融入他们的工作流。