许多人认为程序员不喜欢写文档是因为他们没有好的工具,但我认为软件工程师不喜欢写文档有两个主要原因:第一,写文档很难;其次,代码可以像往常一样发布,无需文档。工具只是它们不重要的原因之一。
写作很难
写作从来都不是一件易事。软件工程师与其他人一样,他们不愿意写文档,是因为想要写得条理清晰、简洁明了,实在是太难了。
写作是一项非常艰巨的任务。我们必须清楚地组织自己的思想,然后经过检查和整理,最后再清楚地表达出来。尽管最后的表达部分可以从某种程度上进行简化(取决于写作的质量),但是正确完成这三个步骤需要付出大量努力。
在编程的世界中,面对所有问题,我们能够给出的最佳答案都是:“视具体情况而定”,一切都需要权衡取舍,但写作则更加复杂。你需要预设上下文,证明决策的合理性,然后论证代码底层思想的推动力。这样的文档只有编写得好才会有用,但写好太难了,所以往往根本做不到。错误的代码仍然可以运行,但错误的文档则不会。
这就是为什么很多人都在争论在代码中添加注释的价值,以及能作为文档使用的代码的优点。Kevlin Henney认为,在复杂的代码周围添加注释实际上是徒劳的,如果开发人员无法通过代码清楚地表达自己,你又怎么期望他能用英语清楚地表达自己呢?
没有文档代码也可以照常发布
即便开发人员不编写文档,他们仍然可以完成自己的工作。没有文档也不会阻碍交付代码(至少不会马上有问题)。没有文档记录的技术决策所造成的损害是累积性的。就像技术负债一样,不会立即造成伤害。
就像我上面所说,写作主要是思考和分析问题。大多数时候,编程只需要凭借自己的经验和判断。一堆杂乱无章的代码照样可以运行,但是一堆乱七八糟的单词和段落则无法形成文章。写作必须清晰才能发挥作用。只要代码能够完成工作,就可以被接受(在某种程度上)。而且,由于大多数组织只在乎产品的交付,因此凡是不会阻碍产品交付的工作都会被忽略。
在许多团队中,单元测试也面临着类似的问题。为了测试代码,我们首先需要理解代码(而且往往花费的时间超过了编写代码),而且没有测试也不会阻碍产品的交付。因此,太好了,代码中没有单元测试。
还有过时的问题。即便是精心编纂的文档也会过时,因此工程师在构建系统时,必须不断重复思考-分析-表达的过程。因此,我们很容易抛弃文档这项重任。因此,我们往往会临时抱佛脚,等到必要时再编写和整理文档。
工具
毫无疑问,如今能够帮助我们编写软件文档的常用工具严重不足。我们不会一次只考虑一个文档,而是会将多个概念汇总起来,思考多个想法和目标。最终的文档只是整个思想过程的一种体现。我们需要工具帮助我们整理思路,以解决眼前的问题。Google Docs、Confluence和Markdown都是此类的写作工具,但都不怎么好用。
虽然工具有一定的影响,但不愿意承担这项任务才是真正的问题所在。
文档该怎么办?
编写软件教会了我一件事。如果你希望用户做某件事情,那么就必须让它变成他们在使用产品的过程中非做不可的事情。同样,如果文档只是代码的附属品,那么永远不会有人主动编写文档。更糟糕的是,文档还没有太大用处。写作需要批判性思维。文档的目的是向自己和听众(比如你的团队)解释你的思维过程和意图。而这个思维过程才是文档提供的价值,而不是编写好的静态文字。
支持结对编程的人经常贬低文档。但是,编写和审核技术文档是团队对他们构建的产品形成统一认识的唯一渠道。这种统一的认识对于团队和代码库的长期健康至关重要。
我认为,想要让文档的编写长期坚持下去,唯一的办法就是让其成为软件开发的阻碍。编写文档应该成为流程的一部分。根据我的经验,下面这些方法或许能起到作用。
-
在编写代码之前,首先编写文档。除非代码改动非常小,否则每位工程师都应该写一份注释,说明他们将要进行的工作,并由团队的其他成员来实际执行。经过详尽的讨论后,实际的代码改动就微不足道了。
-
简化文档的编写工作。不要将文档的编写弄得过于复杂。图表等花里胡哨的东西可以先放一放。你只需要简单地写下你的想法、所做的事情以及原因。即使文档只能为现在和将来的团队其他成员提供基本的说明,也非常有价值。
-
记录下备选方案。无需详细记录实际的实现(因为实现可能随时间而变化),你应该重点记录选择某个方案的原因。这是代码无法解释的内容,因此记录下来很有价值。你可以根据实际情况,投入一定的时间来记录详细信息。
-
便于查找。如果人们找不到文档,那么就没有任何用途。你可以使用支持文本搜索的工具。
-
记录变更。有些组织使用版本控制来记录系统设计随时间推移发生的变更。如果你没有类似的工具,那么请针对每个功能保留一份文档,并在其上不断添加最新的更新信息,以便记录下所有的变更。
最后,希望团队能够在建立文档和查看文档的过程中,逐步认识到文档带来的价值,并养成记录文档的好习惯。但在此之前,你应该将编写文档视为减肥或节食,痛苦而快乐地坚持下去。