为什么我们应该像盖房子那样写程序?
转自:http://blog.jobbole.com/33103/
英文原文:wired.com,编译:AllanChen
在砌上一块砖或钉下一支钉子之前,建筑设计师会制定好详细的计划。程序员或者软件工程师却不会。这难道就是房子很少塌倒而程序经常会崩溃的原因?
蓝图保证建筑设计师的设计的建筑按规划建成。“建成”不仅仅意味不会塌倒,还意味达到业主要求的功能。建筑设计师和他们的客户在着手建造之前,通过蓝图来沟通,以理解他们将要建造成的建筑的样子。
但是很少有程序员在编码之前,会勾画哪怕是简单的草图来说明他们的程序将是会怎么样子。
大多数程序员认为做任何不产生代码的事情都是浪费时间。思考并不会产生代码,没有想好就开始编码,那只会产生出糟糕代码。我们应该理解这些代码到底要实现哪些功能。理解需要思考,而思考很难。借用一句漫画家迪克·圭尼登的话:
写作是一种让你知道你想法有多伤感的本能方法
蓝图让我们想清楚我们打算要建造的建筑。在写下一段代码之前,我们应该先写蓝图。软件的蓝图称为技术说明书。
已经有太多的借口说撰写技术说明书只是浪费时间。比如:技术说明书毫无用处,我们不能通过它来产生代码。这就好像说建筑设计师应该不要画蓝图,因为他们最终还是需要承包商去建造房子。另外一个反对撰写技术说明书的争论也能够用蓝图的例子来反驳。
还有一些程序员争辩说,把蓝图和技术说明书作比较是无用功,毕竟程序不是建筑物。他们认为推倒一堵墙要比改变代码难多了,所以程序的蓝图不是必须的。
错!改变代码也很难,特别是如果我们不想让程序有缺陷的话。
我最近需要修改一些不是我写的代码,从而给程序增加一个小小的功能。要完成它需要理解一个接口。我花一整天用调试器来研究该接口到底是干什么的——这种事读读技术说明书只要5分钟就能搞定。为了避免导入缺陷,我不得不弄清楚我每次修改之后的结果。因为没有技术说明书,这个事情变得更加困难。我必须要阅读上千行代码,我花了数天来琢磨怎样才能修改尽可能少的代码。最后,我花了一周,新增、修改了180行代码。这可仅仅是这个程序的一个很小的变更啊。
修改代码只是一项大任务中小小的一块工作,大多数代码已经是我十几年之前写的了。尽管我几乎不记得这些代码是干嘛的,要修改它还是挺容易的——通过阅读我写的技术说明书,很容易就能找到我要修改的地方。尽管这些修改工作量不少,而且还影响到其它代码,我还是能很快搞定它。
我所说的技术说明书到底是什么?通常它被认为是以正式的技术语言写就的东西。但是撰写正式的技术说明只需要偶尔为之,如果我们仅仅是盖个工具棚的话,就不需要画摩天大楼所要求的那种蓝图。对于大多数软件来说,我们不需要正式的技术说明书。然而就算是写小程序也不能不写技术说明,否则就像没做任何计划就要盖工具棚一样。
这些日子,我写的程序往往只是小房子级别,不是摩天大楼级的。通常我会写下每个算法的实现方式,大多数算法很简单,可能只需要一两句话就能写清楚。有时写清楚一个算法到底是怎么起作用的需要好好构思,并且可能得花上一段话或者几页纸才能写清楚。我有一个简单的原则:技术说明书应该写清楚该算法的使用者需要知道的每一件事情。在代码写好、编译好之后,估计没有人会再去阅读它了。
一旦我弄明白了一段代码的目的所在,写代码的工作就容易了。但有些代码并不是这样,它们要求很复杂的算法。想让一个算法运作起来需要精心构思,这就需要有技术说明书了。
我写的大多数技术说明书都是非正式的。偶尔一段代码很精妙,也很关键,这就需要正式地写。要保证准确性,甚至要使用编写工具仔细检查。这种正式的事情过去十几年只是有那么十几次罢了。
对于复杂系统的设计师,一份正式的技术说明书是必须的,就好像摩天大楼的蓝图一样。但很少有工程师会撰写技术说明书,因为他们根本没有时间去学如何做好这件事,而且学校里也不教。一些学校会讲授技术说明书用语,但是很少教怎么在实际工作中应用。如果你连一个工具棚的蓝图都不会画的话,怎么能会画摩天大楼的蓝图?
要学会撰写技术说明书,需要实践。没有简单的规则能保证你写出一份好的技术说明书。不过一个应该避免的事情就是不要用代码。通过代码去理解代码是一个糟糕事情。建筑设计师不会用砖来制作蓝图。
理解一件复杂的事情的关键是抽象,这意味着技术说明比代码要高一个层次。最简单最准确的语言是数学,初等数学就教过这些了:集合、函数和简单的逻辑。不过,大多数正式的技术说明书使用的语言不在初等数学班里,比如:类型。然而,越是远离简单数学的语言,越会妨碍我们去理解一个复杂的程序或系统。
无论是为复杂系统使用正式的技术说明书还是简单代码的非正式的技术说明书,撰写技术说明书都会提升我们代码的质量。它有助于我们理解我们正在做的事情并减少出错。当然,即使撰写技术说明书也不保证你的程序就不会崩溃。我们依然要使用已有的其它方法和工具来减少代码缺陷。
思考不会保证我们不会犯错误。但是不思考肯定会犯错误。
本文作者莱斯利.兰伯特是计算机科学家,擅长分布式系统、时态逻辑和并行算法。他是工程和国家科学院国家科学院成员。兰伯特在麻省理工学院攻读数学本科,在布兰迪斯大学赢得了他的硕士和博士学位。他为微软研究所工作。