“做者简介: 常柱,微信公众号【架构将来】做者,十多年一线互联网研发从业经验;前五八同城商业会员技术负责人,宝驾租车技术总监,现58 到家业务中台技术负责人。程序员
好的软件设计最重要的元素之一是在处理编程任务时采用的思惟方式。许多组织鼓励一种战术心态,专一于让特性尽量快地工做。然而,若是你想要一个好的设计,你必须采起一种更有策略的方法,投入时间来产生干净的设计并解决问题。本章讨论了为何战略方法能够产生更好的设计,而且从长远来看实际上比战术方法更便宜。编程
大多数程序员使用一种我称为战术编程的思惟方式来进行软件开发。在战术方法中,您的主要关注点是让某些东西工做起来,好比一个新特性或一个 bug 修复。乍一看,这彷佛是彻底合理的:还有什么比编写有效的代码更重要呢?然而,战术规划使它几乎不可能产生一个良好的系统设计。微信
战术编程的问题在于它是短视的。 若是你在战术上编程,你是在试图尽快完成一项任务。也许你有一个艰难的最后期限。所以,规划将来并非优先事项。你不会花不少时间去寻找最好的设计;你只是想尽快开始工做。你告诉本身,若是可让当前的任务更快完成,增长一点复杂性或者引入一两个小的封装是能够的。架构
这就是系统变得复杂的缘由。如前一章所述,复杂性是递增的。使一个系统变得复杂的不是某一件特定的事情,而是数十个或数百个小事情的积累。若是你有策略地编程,每一个编程任务都会增长一些复杂性。为了快速完成当前的任务,它们中的每个彷佛都是合理的妥协。然而,复杂性迅速增长,特别是若是每一个人都在战术上编程。tornado
不久以后,一些复杂的问题就会开始产生,你会开始后悔当初没有走那些捷径。可是,您会告诉本身,让下一个功能正常工做比返回并重构现有代码更重要。从长远来看,重构可能会有所帮助,但它确定会下降当前任务的速度。所以,您须要寻找快速补丁来解决遇到的任何问题。这只会产生更多的复杂性,这就须要更多的补丁。很快,代码就乱成一团了,但到目前为止,状况已经很是糟糕,须要几个月的时间才能清理干净。你的时间表不可能容忍这样的延迟,并且解决一两个问题彷佛也不会有太大的不一样,因此你只是在战术上继续编程。学习
若是您已经在一个大型软件项目中工做了很长时间,我怀疑您已经在工做中看到过战术编程,并体验过它所致使的问题。一旦你开始走上战术道路,就很难改变。测试
几乎每一个软件开发组织都至少有一个将战术编程发挥到极致的开发人员:战术旋风。战术旋风是一个多产的程序员谁泵出的代码比别人快得多,但工做在一个彻底战术的方式。 当涉及到实现快速特性时,没有人比战术性 tornado 完成得更快。在一些组织中,管理层将战术旋风视为英雄。然而,战术旋风留下了破坏的尾迹。他们不多被未来必须使用他们的代码的工程师视为英雄。一般,其余工程师必须清理战术旋风留下的混乱,这使得那些工程师(真正的英雄)看起来比战术旋风进展缓慢。翻译
成为一名优秀的软件设计师的第一步是认识到仅仅为了完成工做编写代码是不够的。为了更快地完成当前的任务而引入没必要要的复杂性是不可接受的。最重要的是这个系统的长期结构。 任何系统中的大多数代码都是经过扩展示有的代码库来编写的,所以做为开发人员,您最重要的工做就是促进这些将来的扩展。所以,您不该该认为“工做代码”是您的主要目标,尽管您的代码固然必须工做。您的主要目标必须是产生一个伟大的设计,这也碰巧工做。这是战略规划。设计
战略规划须要一种投资心态。 您必须投入时间来改进系统的设计,而不是以最快的方式来完成当前的项目。这些投资在短时间内会让你慢下来一点,但在长期内会让你加快速度,如图 3.1 所示。blog
一些投资将是积极的。例如,花一点额外的时间为每一个新类找到一个简单的设计是值得的;与其实施第一个出如今脑海中的想法,不如尝试几个替代的设计,选择最干净的一个。试着想象一些系统在将来可能须要改变的方式,并确保你的设计是简单的。编写好的文档是主动投资的另外一个例子。
其余投资将是被动的。 不管您预先投入多少,在您的设计决策中都会不可避免地出现错误。随着时间的推移,这些错误将变得显而易见。当你发现一个设计问题时,不要忽视它或修补它;花一点额外的时间来修复它。若是您有策略地进行编程,您将不断地对系统设计进行小的改进。这与战术编程相反,在战术编程中,您不断地添加小的复杂性,这些复杂性会在未来致使问题。
那么,正确的投资额是多少呢?一笔巨大的前期投资,好比试图设计整个系统,是不会有效的。这就是瀑布法,咱们知道它行不通。随着您对系统的经验的积累,理想的设计每每会零零碎碎地出现。所以,最好的方法是在连续的基础上进行大量的小额投资。 我建议您将总开发时间的 10-20%用于投资。这个量足够小,不会对您的日程安排产生重大影响,可是足够大,随着时间的推移会产生显著的好处。所以,您最初的项目将比纯战术方法多花费 10-20%的时间。这些额外的时间将致使更好的软件设计,而且您将在几个月内开始体验这些好处。用不了多久,你的开发速度就会比战术编程至少快 10-20%。在这一点上,你的投资是免费的:从你过去的投资中得到的收益将节省足够的时间来弥补将来投资的成本。你将很快收回最初投资的成本。图 3.1 说明了这种现象。
图 3.1:在开始阶段,一种战术的编程方法将比一种战略方法更快地取得进展。然而,在战术方法下,复杂性积累得更快,从而下降了生产率。随着时间的推移,战略方法取得了更大的进展。注意:这个数字只是一个定性的说明;我不知道任何经验测量的准确曲线形状。
相反,若是你有策略地进行编程,你将会以 10-20%的速度完成你的第一个项目,可是随着时间的推移,你的开发速度会随着复杂性的增长而减慢。用不了多久,您的编程速度至少会下降 10-20%。您将很快地归还您在开始时节省的全部时间,而且在剩下的系统生命周期中,您将比采用策略方法时开发得更慢。若是您从未在严重降级的代码库中工做过,请与曾经工做过的人交谈;他们会告诉你,糟糕的代码质量至少会下降 20%的开发速度。
在某些环境中,有强大的力量反对战略方法。例如,处于早期阶段的初创公司会感到巨大的压力,要求他们尽快发布本身的早期版本。在这些公司,彷佛 10-20%的投资都是负担不起的。所以,许多初创公司采起战术性的方法,在设计上花费的精力不多,在出现问题时进行清理的时间更少。他们认为这样作是合理的,若是他们成功了,他们就会有足够的钱聘请更多的工程师来清理垃圾。
若是您所在的公司倾向于这个方向,那么您应该意识到,一旦代码库变成了意大利面条,就几乎不可能修复了。您可能要为产品的生命周期支付高昂的开发成本。此外,好的(或坏的)设计的回报来得很快,因此颇有可能战术方法甚至不会加快您的第一个产品发布。
另外一件须要考虑的事情是,公司成功最重要的因素之一是工程师的素质。下降开发成本的最佳方法是雇佣优秀的工程师:他们的成本并不比平庸的工程师高多少,但却拥有惊人的高生产率。 然而,最好的工程师都很是关心好的设计。若是你的代码库是一个残骸,消息会传出去,这将使你更难招募。结果,你极可能以平庸的工程师而了结。这将增长您将来的成本,并可能致使系统结构进一步退化。
Facebook 就是一个鼓励战术编程的初创公司。多年来,公司的座右铭是“快速行动,打破常规”。“刚从大学毕业的新工程师被鼓励当即投入到公司的代码库中;对于工程师来讲,在工做的第一周将提交推动到生产中是很正常的。从积极的一面来看,Facebook 创建了一个赋予员工权力的公司声誉。工程师有很大的自由度,几乎没有什么规则和限制来阻碍他们。
Facebook 做为一家公司已经取得了惊人的成功,但它的代码基础却由于公司的战术方法而受损;不少代码都不稳定,很难理解,只有不多的注释和测试,并且很难处理。随着时间的推移,公司意识到它的文化是不可持续的。最终,Facebook 改变了它的座右铭,“以坚实的基础设施快速发展”,以鼓励它的工程师在好的设计上投入更多。Facebook 可否成功地解决多年战术编程积累的问题仍有待观察。
公平地说,我应该指出,Facebook 的代码可能并不比创业公司的平均水平差多少。战术编程在初创公司中很常见;Facebook 就是一个特别明显的例子。
幸运的是,在硅谷,战略方法也有可能得到成功。谷歌和 VMware 与 Facebook 差很少是在同一时期成长起来的,但这两家公司都采起了更具战略性的策略。两家公司都很是重视高质量的代码和良好的设计,而且都构建了可以用可靠的软件系统解决复杂问题的复杂产品。两家公司强大的技术文化在硅谷广为人知。不多有公司能与他们竞争顶尖的技术人才。
这些例子代表,一个公司能够用任何一种方法取得成功。然而,在一家关心软件设计并拥有干净代码库的公司工做要有趣得多。
好的设计不是免费的。它必须是你不断投资的东西,这样小问题就不会积累成大问题。 幸运的是,好的设计最终会收回成本,并且比你想象的要快。
在应用战略方法时保持一致是相当重要的,要把投资看做是今天要作的事情,而不是明天要作的事情。当你陷入困境时,很容易把清理工做推迟到危机结束后。然而,这是一个滑坡;在当前的危机以后,几乎能够确定会有另外一个危机,在那以后又会有一个。一旦你开始延迟设计改进,延迟就很容易变成永久性的,你的文化也很容易滑入战术方法。解决设计问题的时间越长,问题就越大;解决方案变得更加使人生畏,这使得人们更容易把它们推迟。最有效的方法是让每一个工程师持续地对好的设计进行小的投资。
“免责声明:本文翻译仅供学习使用,本文的版权归英文原做者或出版方,如有侵权,请联系删除。