我在《专业嵌入式软件开发》一书中指出,编写言简意骇的文档是保证软件质量的关键要素之一。在此结合自己的工作体会,再谈一谈软件开发活动中文档的重要性。切入正题之前,先让我们浏览二个工作场景。
A君刚加入一个代码规模超过百万行的复杂通讯项目。在熟悉项目的过程中发现,上手新项目只能依靠几份单薄的PPT文档,而无法获得象样的系统架构文档、各子系统的概要设计文档和子系统间的接口文档。面对这样的状况,A君只能无奈而痛苦地面对艰难的学习曲线。
初涉某新项目的B君被安排将其他团队最新发布的平台软件集成到产品中,B君在集成的过程中倍感焦虑。问之为何,答曰:“没有任何文档告诉我如何集成,我根本无法知道集成有哪些关键的检查步骤,集成工作只能找这个人问、那个人聊”。
相信这两个工作场景很多读者并不陌生,或似曾相识。然而,绝大多数经历这些场景的同仁仍麻木地看着后来人经历着同样的痛苦 — 无休止的痛苦。为什么不写文档解决这类问题?很典型的回答是:1)代码就是文档;2)没有时间写。
看来,持“代码就是文档”观点的人认为,读代码与读文档是一回事,具有同样的沟通效果。不!为了解释为什么,我们得先看一看代码是如何在不写设计文档的情况下编写出来的。
程序员在理解需求的情形下,会先通过分析构思出如何通过代码实现需求(这里假设程序员的设计能力很好,所构思的设计有模有样),之后通过编码表达出自己的设计(再假设程序员的编码能力很强)。很显然,设计构思与最后获得的代码在表达层面上处于不同的抽象层次,前者更抽象。基于我们的生活经验我们不难认同,相对抽象(不要偏激地理解为非常抽象)的内容更容易在人与人之间取得良好的沟通效果。
再看一看代码被人掌握的过程。毫无疑问,代码只能一段一段地看,阅读者通过不断地消化最终达到在头脑中重现其所表达的设计。很显然,这种“重构”活动需要阅读者运用自己的综合和记忆能力,是一个从具体到抽象的思维过程。在很多情形下(尤其是大型项目),这是一个很艰难的过程,如果代码是在“意识流”的指导下编写出来的,其难度就更不用说了。
阅读代码如此,那阅读设计文档又有何不一样呢?很简单,设计文档正是用于阐述设计思路的,它直接短路了阅读代码时从代码回塑软件设计的思维过程,因而具有更好的沟通效果。是的,我也间接地表达了一个观点 — 软件设计文档应着力于阐述设计构思。因此,如果你告诉我“代码就是文档”,我会理解成“你的文档在描述代码,而非设计”,对于这样的文档我完全认同“代码就是文档”,而且这种垃圾文档不写也罢。对了,对于没有代码的工作,比如开发环境搭建,你如何主张“代码就是文档”?还有,当你负责实现的软件模块如果要被多个团队采用,在没有设计文档的情况下如何实现高效的并行开发?
文档既然重要,那为什么被人如此忽视?首先,这与技术管理者不无关系。在1999年我刚涉足软件行业时,那时所写的设计文档被一遍又一遍地要求修改,在无耐之下,我对技术管理者说“你能给我一个写得好的样本参考吗?”之后,我再也没有因为文档的编写质量而被“再要求”。为什么?因为技术管理者自己并不知道好的文档应是什么模样、有什么用,也不能以身作责地告知什么是好文档,他只是在《软件工程》这类书中读到要有这么些文档。十多年过去了,请看看你周围的技术管理者,他们是不是与我当年面临的差不多?请不要指责技术管理者,如果那样,十年后在相同的境况下被指责的人就是你!
技术管理者对开发文档的不重视,使得团队在编写文档方面少了很多动力,进而最终形成没有开发文档的“作坊式”软件开发文化。具有这种文化特点的团队有一个很鲜明的特点 — 极大地依赖口口相传传递知识与经验,对出现的异常难以做出快速响应。
忽视文档的另一大原因,是将敏捷思想中的“可工作的软件重于面面俱道的文档”理解为“软件开发可以不写文档”。相信不少团队正是将这一敏捷思想当作不写文档的“挡箭牌”。
文档被忽视的第三大原因与我们的能力现状有关。就我复审文档的经验来看,十个工程师中有九个所写出来的文档要么不知所云、要么复述代码实现,文中内容缺乏总结和抽象,而且文档格式“惨不忍睹”。这类文档所提供的价值非常有限,看了也白看。加之身边存在大量的这类文档,因此我们很容易失调地以为所有文档都无用(正确的认知应是“垃圾文档无用”),恶性循环由此产生。诚然,打破恶性循环的方法是提高我们的写作能力,而非维持现状!
在开源软件项目大行其道并逐渐颠覆传统软件产业格局的今天,不少开源项目没有良好文档但却运作得很好的事实也左右着我们对文档重要性的认知。与开源项目不同的是,大多的商业软件具有产品上市时间的压力,对开发效率和开发进度控制有着完全不同的要求,因而我们不能简单地以开源项目作为类比。另外,工作于开源项目的工程师技术水准相对高,这在某种程度上缓解了开源项目文档缺乏所带来的负面影响。对了,很多著名的开源项目都有人为之出书立著,不是吗?
那文档到底有什么好处呢?先从团队的角度加以审视。首先,文档有助于新手更快地上手项目。软件设计文档能让新手更快地掌握遗留系统的软件实现;开发环境搭建文档能帮助新手高效地构建开发环境以投入到人力紧张的项目中;开发流程文档能让新手遵循已有的开发实践;等等。
其次,文档有助于传承团队知识和沉淀经验教训。相信没有人愿意看到如火如荼的项目因为某位团队成员的离开而“熄火”,也不愿碰到因为人员的流动给自己的工作带来极大的痛苦,知识和经验教训的文档化有助于我们缓解甚至克服这类问题。
再次,文档有助于代表个体为团队所做出的贡献。健康的团队不能只是“生产”代码,还得防范因为人员流动而产生前面所谈到的知识、经验教训的流失,这是团队建设的重要组成部分。个体对团队的贡献不在于你多能说或喊,而在于你多能写(包括代码和文档)。(另:@出版人周筠 老师在微薄中提到“农业社会靠喊,商业社会要写”的观点,很具概括性)
从个体角度,文档写作能力关乎我们的职业发展和职场旅程!
我也是从“代码论英雄”的时期走过来的,也曾以为能写出“好”的代码就行了(没有最好,只有更好!)。然而,现在我知道,当写作能力提高之后,软件设计和代码编写能力也随之更强,容易做到时刻思考“如何通过设计让代码具备更好的沟通性”(编程是一种创造性的沟通!)。写好文档需要我们具备良好的洞察力和概念塑造能力,这些能力都是高质高效软件开发所需要的。总之,写作能力的提高有助于提升软件开发能力。现实之所以有那么多难懂的代码,正因为程序员活在代码世界,而非设计之中。在更具体的代码世界觉得好的代码,一旦站在更抽象的设计层面,会发现仍有很大的提升空间。
在我看来,出色的程序员一定具备良好的写作能力,因为他们喜欢发表自己的意见和影响他人,而输出文档就是一种途径。还有,如果想成为一名合格的软件架构师,写作能力是必过之关,否则即使担纲了软件架构师一职也只能是“坑人害己”,因为软件架构师的能力极大地影响着软件开发的上游质量。
编写文档也是我们职业化的需要。在Motorola工作期间刚涉足系统工程师一职时,“菜鸟”的我分不清何时用SECCB(System Engineering Change Control Board)、何时用BCCB(Business Change Control Board),通过查看流程文档发现,其中定义好了使用两者的标准是什么。当时给我的感觉真的是震惊,写这部分内容的人(或组织自身)一定也经历了我当时的那种成长痛苦,他通过文档化为后人解决了这一苦恼。你敢设想解决这种苦恼的方法经历几年、甚至几十年的口口相传仍“原汁原味”吗?我相信职业化可以包含很多内容,但“我为人人,人人为我”一定应包含其中,这是可持续发展所必须涵盖的,编写文档就是践行这一主张的。
编写文档也是我们更好地学习和享受生活的需要。“勤劳的中国人”生怕在工作中空下来,喜欢乐此不疲地重复解答别人所问和身体力行地传授自己所能。难道不能写成文档与人分享,然后空出时间来学习和享受生活?(好吧,“IT民工”没钱没生活,起得比鸡早,睡得比狗晚。自找的!)
随着职场旅程的变迁,我们不断地通过编写更多的代码收获经验,收获经验之余我们只想在履历上写上“曾工作于某项目”吗?一个项目的代码我们只要三年不去接触,就差不多忘得一干二净了,你以为三年以后会仔细地阅读代码了解当时的设计和教训(那时物是人非了,你不会有这样的激情的!相信我)?为什么不通过文档,以总结的方式记录下来呢?如果在我们的职场旅程中不断地通过文档记录下曾做过的项目,日后浏览起这些文档一定会是一种享受(当然,你留下的是垃圾文档除外)。文档质量与数量是体现我们职场厚度的更高形式!我现在拿起2000年写的设计文档都会很感慨 — 哇,我那时能写出这样水准的文章!(切,其实有很多地方需要改进。别自恋!)
为了让本文不致于产生另一个象“可工作的软件重于面面俱道的文档”那样的误会,我得就文档的要求做一点小小的补充。我并非主张在沉重的“软件工程”面前又倡导另一个复杂的“文档工程”。文档的目的在于沟通,其中内容应突出要点地“点到为止”,以总结和抽象作为写作指导。同样的目的,如果能用最少的页数说清道白就是水平。文档重质不重量!
该死的“文档就是代码”,害得我没有很好地欣赏昨晚的“中国好声音”,还搭上了一晚只睡了六个小时的觉。如果你还得说“文档就是代码”,请准确地说“文档是一种代码”。
对了,都要结束了。还没有指出为什么有人会提出“没有时间写文档”。以我的经历来看,那人没有说实话,他其实是想说“我没有那个写作能力”。