1. 轻松撰写功能规格书 - 第一部分: 为什么要写?

    2000年10月2日,星期一

    乔尔测试面世之初, 读者反映其中最难做到的部分就是写规格书。 写软件规格书就好像像漱口: 大家都觉得是件好事, 但就是没人做。

    为什么人们不写规格书? 有人说跳过写规格书的阶段可以节省时间。 这些人眼中写规格书是一种奢侈, 只有那些为NASA制造太空飞船的工程师, 或是大型知名保险公司的工作人员们才配享有。 胡说八道。 首先, 不写规格书是软件项目开发中最大的不必要风险, 其愚蠢程度就像不带装备就横穿莫哈维沙漠,心存侥幸能逃过一劫。 那些不写规格书就一头扎进代码中的程序员和软件工程师, 以为自己是耍枪高手, 不用瞄准就能拔枪射击。 他们在做梦。 他们的效率非常低。 他们写的代码烂、做出的软件更烂, 并且为项目平添了非常大的、完全不必要的风险。

    05. 轻松撰写功能规格书 - 第一部分: 为什么要写? - 图1 我认为对于任何非玩票性质的项目(开发时间超过一周或人员多于一名), 不写规格书会导致项目花费的时间更长、代码的质量更差。 原因如下。

    规格书最重要的功能就是对程序进行设计。 即使只有你自己在写代码, 规格书也只写给自己看, 在写规格书的过程中, 通过详细描述程序的工作原理, 你会被迫对程序做真正的设计。

    让我们虚构来自两家公司的两个程序员。 来自急速香蕉软件的史比迪小姐,从不写规格书。“规格书?我们才不需要那玩意!” 来自好脾气软件公司的罗杰斯先生, 在写代码之前总会完成详细的规格书。 我有好几位假想中的朋友,这两位也在其中。

    史比迪和罗杰斯有一个共同点: 他们都负责维护各自产品2.0版本的历史兼容性。

    史比迪决定提供历史兼容性的最好方法是写一个简单的转换器, 把1.0版本文件转换为2.0版本。 她立刻开始敲代码。 敲,敲,敲。点,点,点。 硬盘飞转, 尘土飞扬。 两周后, 她的转换器完工了。 但史比迪的客户不满意,因为她的代码强迫公司的所有人都必须立即升级到新版本。 史比迪最大的客户 Nanner Splits Unlimited公司拒绝购买新的软件。

    Nanner Splits需要2.0版本不用转换就能处理1.0版本的文件。 史比迪决定写一个降级转换器, 并把它 绑到“保存”按钮上。 这下乱套了, 因为虽然看上去你可以使用2.0版本的功能, 但在保存时,由于只支持1.0版本的格式, 软件会提示你半个小时前用过的功能在旧文件格式上不可用。 写降级转换器不仅又花了两周时间, 而且效果还不好。 这样总共花费 了4周时间。

    再来看好脾气软件公司的罗杰斯先生,他古怪偏执的一面表现在没有规格书就拒绝写代码。 他花了20分钟来做历史兼容功能的设计,想法和史皮迪差不多, 规格书大致的意思是:

    • 打开一个用旧版本产品创建的文件, 自动将其转换成新版本的格式。

    这个规格书拿给客户一看, 客户急了:“等一下! 我们不想强迫每个人立刻升级!” 于是罗杰斯先生又想了想, 修改了说明书,如下:

    • 打开一个用旧版本产品创建的文件, 会在内存中自动将其转换成新版本的格式。 保存文件的时候, 用户可以选择把文件转换回旧版本。

    又过了20分钟。

    罗杰斯先生的上司是一个面向对象编程的狂人, 他看到规格书,觉得缺点什么。 他给出了一个不同的架构。

    • 重构代码, 使用两个接口:V1和V2。 V1包含所有版本一的功能, V2继承自V1, 增加所有的新功能。 V1::Save负责处理历史兼容性, V2::Save用新格式来保存文件。 如果你打开V1文件时想使用V2的功能, 软件会发出提醒, 用户要么转换文件, 要么放弃使用新功能。

    20分钟过去。

    罗杰斯先生郁闷了。 重构将耗时3个星期, 而不是他预计的2个星期! 但是这么做确实优雅地解决了用户的所有问题, 所以他接受了方案, 开始编程。

    罗杰斯先生总共用了3周零1小时。 史皮迪总共用了4周, 但代码的质量不那么好。

    这个故事的教训是, 瞎编一个例子你可以证明任何事情。 额, 我不是这个意思。 故事的教训是, 当你用人类的语言设计产品时, 可以在几分钟的时间里权衡几种方案的利弊,然后修正、改进你的设计。 谁也不会为了在文字处理器里删除一段话而难过。 但如果你选择编程的语言里做产品的设计, 可能要花 数周的时间才能做出可以让人反馈的设计。 更糟的是, 程序员对于耗时两周时间写出的代码是有感情的, 不管这些代码错得多离谱。 无论史皮迪的上司或是客户说什么, 她都不会愿意丢掉她辛苦写出的、漂亮的转换器代码, 尽管这段代码在架构上完全谈不上漂亮。 结果是, 最后交付的产品形态介于最初错误的设计以及理想的设计之间。 人们会评论它“是我们能做的最好的设计了, 毕竟我们辛辛苦苦写了那么多代码, 总不能全都推倒重来吧。” 这个评价远比不上:“这是我们能做的最好的设计,没有之一。”

    05. 轻松撰写功能规格书 - 第一部分: 为什么要写? - 图2 以上是写规格书的第一大理由。 第二大 理由是节省沟通的时间。 通过写规格书,你只需要和别人沟通一次, 团队的其他成员只要去读规格书, 就能知道程序的很多方面。 测试人员通过规格书,可以了解程序有哪些符合预期的功能和行为, 也就是该从哪些角度去测试。 营销人员以规格书为蓝本,撰写出充满溢美之词的产品白皮书,然后放到 网站上去宣传你们还未出世的杰作。 业务拓展人员经常误读规格书,然后用天马行空般的想象力把产品 塑造成秃顶或是皮肤疣(warts)的克星, 不过只要他们能忽悠到投资,你就没什么可抱怨的。 开发者读了规格书,就知道 该写哪些代码。 客户读了规格书, 就能确信开发者们正在做的产品是物有所值的。 技术文档编写者以规格书为参考, 写出给客户看的图文并茂的说明书(就是那些经常遗失或被丢弃的小册子, 不过那是另一个故事了)。经理们读了规格书, 然后就可以在管理会议上假装一切尽在他们掌控之中。 等等。

    如果你没写规格书,所有这些沟通的过程还是要发生, 因为它们总会发生, 不过这种情况下,它们会一次又一次地发生。 测试人员拿到软件只能随便点点看看, 因为他们不清楚软件怎么样才算正常工作, 一旦发现有奇怪的程序行为, 他们就会一再地问程序员各种愚蠢的问题。 这不仅会导致程序员的工作效率被破坏殆尽 ,而且程序员在回答这些问题时 倾向于用代码实现细节来解释, 而给不出所谓“恰当的答案”。 也就是说, 测试人员是基于程序来测试程序, 而不是基于程序来测试设计, 而后者可能,嗯,还稍微更有用一点。

    如果不写规格书, 发生在可怜的技术文档编写者身上的事才叫滑稽(带有一丝悲凉的感觉)。他们通常 比较弱势, 不敢打扰程序员大人们。 许多公司的情况是, 如果技术文档编写者养成了向程序员提问的习惯, 比如某个软件 怎么样才算正常工作, 程序员就会向经理告状, 说自己被那些[形容词已被和谐]的文档编写者烦得什么都干不成, 能不能 别让他们靠近我。 经理们为了提高工作效率, 只能禁止文档编写者再去浪费程序员们的宝贵时间。 至于这种情况发生在哪些公司, 你从他们的帮助文件和产品手册上就看得出来, 里面包含的信息比运行软件时你自己得到的信息还少。 当你看到屏幕上出现如下提示信息

    • 你想开启LRF-1914支持功能吗?

    然后你点“帮助”, 弹出的帮助主题会让你哭笑不得:

    • 让你在使用LRF-1914支持功能(默认)和不使用LRF-1914支持功能之间切换。 如果你想使用LRF-1914支持功能, 选择“是”或按“Y”。 如果你不想使用LRF-1914支持 功能, 选择“否”或按“N”键。

    额,谢谢了。 很明显文档编写者在努力掩盖自己根本不知道LRF-1914支持功能是什么的事实。 他们不能问程序员,可能因为(a)他们不好意思开口,或者(b)程序员人品很差而且远在伦敦,或者(c) 管理层禁止他们打扰程序员, 或是因为其他的难以列举的大公司通病。 但是最根本的问题在于, 没有规格书可以做参考。

    写规格书的第三大理由是没有详细的说明, 就无法制定计划表。 如果你在攻读博士学位而且做好了为之奋斗14年的准备,你可以没有计划表。 或者如果你写的程序有望成为下一个“毁灭公爵”* 一个划时代的3D游戏——译者注,那我们可以理直气壮地说“什么时候把程序做结实做漂亮了,我们就什么时候交付”, 你也可以没有计划表。 但几乎所有面向实际业务的开发工作, 你必须要知道要做某件事需要多长的时间, 因为开发产品是要花钱的。 买牛仔裤之前还要看价格呢, 何况是自负盈亏的投资者,他们在决定是否开发某个产品时, 当然需要先知道开发的时间成本,进而换算成经济成本。 关于如何做计划,请阅读我写的轻松掌控软件开发进度

    公司常犯的一个重大错误是, 当大家对某些设计有争议时,争议从来都得不到解决。 Windows 2000 的开发主管布莱恩·瓦伦丁有一句名言: “如果10分钟以内无法达成决议, 那就一直商量到达成决议为止。”

    太多的软件开发机构都有这个问题: 一旦出现设计上的争议, 通常出于某种政治原因, 没有人站出来力挽狂澜,促成一个决议。 这导致程序员们只能就无关痛痒的设计进行开发。 随着时间的推移, 所有困难的决定 都被推迟到了最后一刻。 这样的项目是最有可能失败的项目。 如果你开了一家研发某项新技术的初创公司, 并且发现 公司经常性地无法做出决定, 那你还不如趁早关门, 把钱还给投资者, 因为这样下去公司什么也做不成。

    在写规格说明书的过程中,所有那些令人不悦的或大或小的设计决定都会统统暴露出来,如果不写,它们很容易就被掩盖过去了。 即使是非常琐碎的决定, 也能从规格书中看出问题的端倪。 比如你们在做一个会员制的网站, 可能大家都同意如果会员忘了密码, 就通过邮件告知他们。 很好。 但是这还不足以指导开发。 要写出代码, 你需要知道那封电子邮件的确切措词。 大部分公司都不信任程序员的文字水平,不让他们直接撰写真正要展示给客户看的文案(而这种不信任通常是有道理的)。所以消息的具体措词,需要交给某个营销、公关或是文学专业的人去拟定。

    “亲爱的客户, 这是你忘记的密码。 下次别这么大意了。” 当你强迫自己把规格书写得规范、完整的时候(我马上就会讲这个), 你就会注意到很多细节的问题, 要么你可以立即解决他们, 要么就在旁边做一个大大的红色记号。

    好,现在大家意见一致了吧。 规格书必不可少,就好像每个人都有母亲,每个人都爱苹果派。 我怀疑大部分人都明白这一点, 而我发了 这么多牢骚, 只是贻笑大方, 并没有什么教育意义。 问题是为什么人们不写规格书呢? 肯定不是为了节省时间, 实际上恰恰相反, 而且我觉得大多数程序员都对此深有体会。(在大部分机构里 唯一能算作“规格书”的东西是那种生硬的,篇幅只有一页的文本文档,还是程序员在向300个人解释过那些该死的功能之后,愤愤然一挥而就的。)

    05. 轻松撰写功能规格书 - 第一部分: 为什么要写? - 图3 我认为是因为有太多的人不喜欢写作了。 面对一张空白的屏幕, 很多人都会发怵。 我个人克服了这种恐惧, 得益于我在大学里选过一门课, 课程要求每周交一篇3至5页的小品文。 写作能力也是一种肌肉。 你写得越多,就越能写。 如果你需要写规格书但写不出来, 可以先开始记日记,写博客,参加一个创作培训班, 或者干脆给认识的人写信,不管是亲戚也好, 你4年多没联系的大学室友也罢。 不要放过任何一个把词写在纸上的机会,持续改进你的规格书写作技巧。 如果你是软件开发活动的管理者, 要是你手下的人不愿意写规格书, 就把他们送去参加一个为期两周的创作培训班, 最好是在深山里举办的那种。

    如果你没有在一个要求写功能规格书的公司工作过, 你可能不知道这种文档时什么样的。 在这个系列的下一篇文章里, 我会示范一个简短的规格书,供你参考, 然后再看看一份好的规格书应该包括什么。 请继续阅读!