JoelOnSoftware

Joel on Software

Painless Functional Specifications - Part 1: Why Bother?

无痛功能规范-第一部分:为什么需要?

by Joel Spolsky Monday, October 02, 2000

When The Joel Test first appeared, one of the biggest sore points readers reported had to do with writing specs. It seems that specs are like flossing: everybody knows they should be writing them, but nobody does.

当Joel测试最早出现的时候,用户反馈的最大困难就是关于编写规范。看起来写规范就像用牙线:所有人都知道应该要写规范,但是就是没人去做。

Why won't people write specs? People claim that it's because they're saving time by skipping the spec-writing phase. They act as if spec-writing was a luxury reserved for NASA space shuttle engineers, or people who work for giant, established insurance companies. Balderdash. First of all, failing to write a spec is the single biggest unnecessary risk you take in a software project. It's as stupid as setting off to cross the Mojave desert with just the clothes on your back, hoping to "wing it." Programmers and software engineers who dive into code without writing a spec tend to think they're cool gunslingers, shooting from the hip. They're not. They are terribly unproductive. They write bad code and produce shoddy software, and they threaten their projects by taking giant risks which are completely uncalled for.

为什么人们不写规范?他们会宣称因为他们跳过了书写规范阶段从而节省了时间。他们觉得似乎书写规范是只有NASA宇宙飞船工程师,或者是大保险公司的员工才能享用的奢侈品。胡说八道。首先,不写规范是你在软件项目中承担的最大的不必要风险。就跟仅穿着你身上的衣服然后想着“飞过去”去穿越莫哈韦沙漠一样蠢。不写规范马上钻到代码里的程序员和软件工程师会把自己想象成很酷的神枪手,从关键部位开始设计。不是这样的,他们会非常低没有效率。他们会写出糟糕的代码并且会写出以次充好的软件,他们的行为给他们所在的项目带来了完全没必要的巨大风险。

I believe that on any non-trivial project (more than about 1 week of coding or more than 1 programmer), if you don't have a spec, you will always spend more time and create lower quality code. Here's why.

我觉得在所有的非简单项目上(要花费超过1周编码,或者超过1个程序员),如果你没有规范,你总是会花更多时间并且写出低质量的代码,下面是为什么。

The most important function of a spec is to design the program. Even if you are working on code all by yourself, and you write a spec solely for your own benefit, the act of writing the spec -- describing how the program works in minute detail -- will force you to actually design the program.

规范的最重要功能是设计程序,哪怕就你自己要来实现代码,你写代码纯粹是从自己的利益出发,写规范的过程 –详细具体的描述程序如何工作 – 会迫使你自己去设计这个程序 。

Let's visit two imaginary programmers at two companies. Speedy, at Hasty Bananas Software, never writes specs. "Specs? We don't need no stinkin' specs!" At the same time, Mr. Rogers, over at The Well-Tempered Software Company, refuses to write code until the spec is completely nailed down. These are only two of my many imaginary friends.

我们来看看两个假想公司的程序员。快香蕉软件公司的Speedy,从来不写规范,“规范?我们不需要讨厌的规范!”,同时,来自好脾气软件公司的Roger先生除非规范已经完全敲定否则不开始写代码。他们只是我众多想象朋友中的两个。

Speedy and Mr. Rogers have one thing in common: they are both in charge of backwards compatibility for version 2.0 of their respective products.

Speedy和Roger先生有一个共同点:他们都负责他们自己产品2.0的前向兼容性。

Speedy decides that the best way to provide backwards compatibility is to write a converter which simply converts 1.0 version files into 2.0 version files. She starts banging that out. Type, type, type. Clickety clickety clack. Hard drives spin. Dust flies. After about 2 weeks, she has a reasonable converter. But Speedy's customers are unhappy. Speedy's code will force them to upgrade everyone in the company at once to the new version. Speedy's biggest customer, Nanner Splits Unlimited, refuses to buy the new software. Nanner Splits needs to know that version 2.0 will still be able to work on version 1.0 fileswithout converting them. Speedy decides to write a backwardsconverter and then hook it into the "save" function. It's a bit of a mess, because when you use a version 2.0 feature, it seems to work, until you go to save the file in 1.0 format. Only then are you told that the feature you used half an hour ago doesn't work in the old file format. So the backwards converter took another two weeks to write, and it don't work so nice. Elapsed time, 4 weeks.

Speedy决定提供前向兼容性的最佳方式就是编写一个转换器,然后把所有1.0的文件全部转换成2.0的文件。她就开始实现这个。代码敲,敲,敲,嘀嗒,嘀嗒,嘀嗒。硬盘旋转。时光飞逝(baxiaguoxi)。大约过了两周,她写出了合理的转换器。但是Speedy的客户不开心了。Speedy的代码会迫使他们公司的所有人都升级到最新版本。Speedy的最大客户NannerSplits(分裂讨人厌)有限公司希望在不转换1.0格式的情况下2.0仍然能工作。Speedy决定编写一个前向转换器,然后将其挂进“保存”功能。这有点混乱,因为你在2.0特性的版本的时候看起来似乎是行的,直到你将其保存为1.0格式,它才会告诉你:你在半个小时之前使用的功能在旧文件格式上是不能工作的。因此前向转换器又花了两个礼拜编写,而且似乎工作起来也不那么顺畅,总共花了4个星期。

Now, Mr. Rogers over at Well-Tempered Software Company (colloquially, "WellTemperSoft") is one of those nerdy organized types who refuses to write code until he's got a spec. He spends about 20 minutes designing the backwards compatibility feature the same way Speedy did, and comes up with a spec that basically says:

现在,好脾气软件公司(口语,“脾气好”)的Roger先生,是那种自我组织的很好的书呆子类型,他在得到规范之前拒绝编写代码。就像Speedy那样,他花了大约20分钟设计前向兼容功能,得到了一份这样的软件规范:

: When opening a file created with an older version of the product, the file is converted to the new format.

: 当打开一份该产品旧版本产生的文件时,该文件会被转换为新格式。

The spec is shown to the customer, who says "wait a minute! We don't want to switch everyone at once!" So Mr. Rogers thinks some more, and amends the spec to say:

客户看了这份规范,然后说“等等!我们不想要一次把每个人的都转换!”所以Roger先生又想了一下,然后修正了下规范说:

: When opening a file created with an older version of the product, the file is converted to the new format in memory. When saving this file, the user is given the option to convert it back.

Another 20 minutes have elapsed.

当打开一份该产品旧版本产生的文件时,文件在内存里被转换为新格式。当保存这份文件时,用户将有权选择是否将其转换回旧版本。

又花了20分钟。

Mr. Rogers' boss, an object nut, looks at this and thinks something might be amiss. He suggests a different architecture.

Roger先生老板,是个对象狂人,看了下这个然后觉得好像缺了点什么,然后他建议了一个不同的架构。

: The code will be factored to use two interfaces: V1 and V2. V1 contains all the version one features, and V2, which inherits from V1, adds all the new features. Now V1::Save can handle the backwards compatibility while V2::Save can be used to save all the new stuff. If you've opened a V1 file and try to use V2 functionality, the program can warn you right away, and you will have to either convert the file or give up the new functionality.

: 代码将被重构来使用两个接口:V1和V2.V1包含了所有第一版本的功能,V2继承于V1,并添加新功能。然后V2::Save可以用来保存所有新的东西。如果你打开V1文件但是尝试使用V2功能,程序将马上警告你,你要么选择转换文件要么选择放弃新功能。

20 more minutes.

又20分钟过去了。

Mr. Rogers is grumpy. This refactoring will take 3 weeks, instead of the 2 weeks he originally estimated! But it does solve all the customer problems, in an elegant way, so he goes off and does it.

Roger先生是个乖乖先生。这项重构将花费3个礼拜而不是他原来预计的两个礼拜!但确实优雅地解决了客户的所有问题,所以他就开始这样做了。

Total elapsed time for Mr. Rogers: 3 weeks and 1 hour. Elapsed time for Speedy: 4 weeks, but Speedy's code is not as good.

Roger先生花费的总时间是3个礼拜加一个小时。Speedy花费的时间是4个礼拜,而且Speedy的代码没有Roger先生的一样好。

The moral of the story is that with a contrived example, you can prove anything. Oops. No, that's not what I meant to say. The moral of the story is that when you design your product in a human language, it only takes a few minutes to try thinking about several possibilities, revising, and improving your design. Nobody feels bad when they delete a paragraph in a word processor. But when you design your product in a programming language, it takes weeks to do iterative designs. What's worse, a programmer who's just spend 2 weeks writing some code is going to be quite attached to that code, no matter how wrong it is. Nothing Speedy's boss or customers could say would convince her to throw away her beautiful converting code, even though that didn't represent the best architecture. As a result, the final product tends to be a compromise between the initial, wrong design and the ideal design. It was "the best design we could get, given that we'd already written all this code and we just didn't want to throw it away." Not quite as good as "the best design we could get, period."

这个故事的寓意是,通过一个矫揉造作故事,你能证明一切事情。 啊额, 不,那不是我想说的。这个故事的寓意是当你使用人类语言设计你的产品的时候,只要花几分钟就能想出几种可能来修改,改进你的设计。没有人会因为删除字处理器里的一个段落而感到难过,但是如果你使用编程语言来设计你的产品,将花费数周来做迭代设计。更糟的是,不管代码有多错,那些花费了两周来编写代码的程序员会非常粘在他们的代码上。不论Speedy的老板或者客户说什么都没法让她扔掉她漂亮的转换代码,哪怕她的代码并不是最好的架构。结果,最后的产品就变成了开始错误设计和理想设计之间的妥协。“这是我们能达到的最佳设计,基于我们已经写了这些代码然后我们不想舍弃这些代码”,不过它还是没有在这段时间内我们能获得的“最佳设计”那么好。

So that's giant reason number one to write a spec. Giant reason number two is to save time communicating. When you write a spec, you only have to communicate how the program is supposed to work once. Everybody on the team can just read the spec. The QA people read it so that they know how the program is supposed to work and they know what to test for. The marketing people use it to write their vague vaporware white papers to throw up on the web site about products that haven't been created yet. The business development people misread it to spin weird fantasies about how the product will cure baldness and warts and stuff, but it gets investors, so that's OK. The developers read it so that they know what code to write. The customers read it to make sure the developers are building a product that they would want to pay for. The technical writers read it and write a nice manual (that gets lost or thrown away, but that's a different story). The managers read it so that they can look like they know what's going on in management meetings. And so on.

因此这就是要编写规范的第一大原因。第二大原因是它节省了交流时间。当你编写规范的时候你只需要表达出该程序应该如何工作一次就可以了。QA人员读到了,他们就知道了该程序应该如何工作,他们应该如何测试。销售人员会拿它来写他们的模棱两可的跳票软件销售白皮书,然后扔到网站的产品页面,虽然这个时候产品还没产生。商业开发人员误读了该文件,然后产生了一些关于该产品如何治疗秃顶,肿瘤之类的奇怪幻想,不过居然吸引了投资者,那也还好。 开发者阅读了就知道如何如何开始写代码。客户阅读该文件确保开发人员开发的是他们想要买的产品。技术作家阅读了该文件之后就会编写漂亮的使用手册(通产会被丢掉或者扔掉,不过那是另一码事儿了)。经理们阅读该文件,这样他们就可以在开管理会议的时候看上去知道在进行着什么。等等。

When you don't have a spec, all this communication still happens,because it has to, but it happens ad hoc. The QA people fool around with the program willy-nilly, and when something looks odd, they go and interrupt the programmers yet again to ask them another stupid question about how the thing is supposed to work. Besides the fact that this ruins the programmers' productivity, the programmers tend to give the answer that corresponds to what they wrote in the code, rather than the "right answer." So the QA people are really testing the program against the program rather than the program against the design, which would be, um, a little bit more useful.

当你没有规范,所有的这些交流仍然会发生,因为必须要发生,但这回就会特定的发生。QA人员就会毫无选择的被这个层序弄的团团转,当有些东西看上去很奇怪的时候,他们就会去再一次地打断程序员然后再问一个关于这个程序究竟如何工作的愚蠢问题。除了会打断程序员的效率之外,程序员们倾向于给出他们在代码里写出的东西,而不是正确的答案。所以最后QA实际上在用程序来测试程序,而不是用设计来测试程序。嗯用设计来测试才有点儿用嘛。

When you don't have a spec, what happens with the poor technical writers is the funniest (in a sad kind of way). Tech writers often don't have the political clout to interrupt programmers. In many companies, if tech writers get in the habit of interrupting programmers to ask how something is supposed to work, the programmers go to their managers and cry about how they can't get any work done because of these [expletive deleted] writers, and could they please keep them away, and the managers, trying to improve productivity, forbid the tech writers to waste any more of their precious programmers' time. You can always tell these companies, because the help files and the manuals don't give you any more information than you can figure out from the screen. When you see a message on a screen which says

当你没有规范的时候,可怜的技术作家的表现是最有意思的(悲哀的那种)。技术作家通常没有什么途径来打扰程序员。在很多公司,如果技术作家养成了去打扰程序员问某样东西怎样工作的时候,那些程序员就会跑到他们经理那儿去哭诉:因为这些【咒骂着删掉】作家 ,他们无法完成任何工作,然后经理们,为了改善效率,禁止技术作家去浪费他们程序员的宝贵时间。你总是能跟这些公司说,因为那些帮助文件和手册提供的信息并不比你能从屏幕上获得的多。当你在屏幕上看到一个信息:

: Would you like to enable LRF-1914 support?

: 你要启用LRF-1914支持么?。

... and you click "Help", a tragicomic help topic comes up which says something like

。。。然后你点击“帮助”,一个悲喜交加的帮助话题就跳出来,内容大概是:。

: Allows you to choose between LRF-1914 support (default) or no LRF-1914 support. If you want LRF-1914 support, choose "Yes" or press "Y". If you don't want LRF-1914 support, choose "No" or press "N".

: 允许你在LRF-1914支持(默认)或者没有LRF-1914支持之间作出选择。如果你想要LRF-1914支持,选择“是”或者按“Y”。如果你不想要LRF-1914支持,那么选择“NO”或者按“N”。

Um, thanks. It's pretty obvious here that the technical writer was trying to cover up the fact that they didn't know what LRF-1914 support is. They couldn't ask the programmer, because (a) they're embarrassed, or (b) the programmer is in Hyderabad and they're in London, or (c) they have been prohibited by management from interrupting the programmer, or any other number of corporate pathologies too numerous to mention, but the fundamental problem is that there wasn't a spec.

嗯,谢谢。这里很明显技术作家在尝试掩盖他们并不知道LRF-1914支持是什么。他们不能询问程序员,因为一,他们会觉得尴尬。或者二,程序员在海得拉巴或者伦敦, 或者三,因为管理层禁止他们打扰程序员, 或者是其他的公司的太多而无法提及的章程规定,但是最根本的问题是:没有一个规范。

Number three giant important reason to have a spec is that without a detailed spec, it's impossible to make a schedule. Not having a schedule is OK if it's your PhD and you plan to spend 14 years on the thing, or if you're a programmer working on the next Duke Nukem and we'll ship when we're good and ready. But for almost any kind of real business, you just have to know how long things are going to take, because developing a product costs money. You wouldn't buy a pair of jeanswithout knowing what the price is, so how can a responsible business decide whether to build a product without knowing how long it will take and, therefore, how much it will cost? For more on scheduling, readPainless Software Schedules.

要编写规范的第三大原因是:没有详细的规范,你无法制定详细的进度计划。如果是你的PhD而且你打算在那件事情上花上14年,或者你是工作在“毁灭公爵”上的程序员,准备好了就会发布,那没计划也是可以的。但是对于几乎任何真正的生意,你必须知道事情要花多长时间,因为开发一个产品是要花钱的。不知道牛仔裤花多少钱你是不可能去买的,因此一桩负责的生意如何在不知道产品要花多长时间今儿无法知道要花多少钱的情况下决定是否要构建一个产品呢? 关于更多制定进度的话题,请阅读“无痛软件进度” 。

A terribly common error is having a debate over how something should be designed, and then never resolving the debate. Brian Valentine, the lead developer on Windows 2000, was famous for his motto "Decisions in 10 minutes or less, or the next one is free."

In too many programming organizations, every time there's a design debate, nobody ever manages to make a decision, usually for political reasons. So the programmers only work on uncontroversial stuff. As time goes on, all the hard decisions are pushed to the end. These are the most likely projects to fail. If you are starting a new company around a new technology and you notice that your company is constitutionally incapable of making decisions, you might as well close down now and return the money to the investors, because you ain't never gonna ship nothing.

一个可怕的常见错误就是开一场关于某样东西该如何设计的辩论会,但是永远没办法解决争论。Windows2000的主开发师 Brian Valentine因他的格言“10分钟以内的决定,或者下一个决定是免费的”而成名。在很多程序开发企业,每次一有一个设计争论,就没有人能够做决定,通常是由于政治上的原因。因此程序员通常工作在非争议性的内容上。随着时间流逝,所有的困难决定都被推到了最后。这就是那些最容易失败的项目。如果你用新技术创办一家新公司,然后你注意到你的公司规章式的无法做出决定,你最好把这家公司关闭然后把钱还给投资者,你不会做出什么东西来的。

Writing a spec is a great way to nail down all those irritating design decisions, large and small, that get covered up if you don't have a spec. Even small decisions can get nailed down with a spec. For example, if you're building a web site with membership, you might all agree that if the user forgets their password, you'll mail it to them. Great. But that's not enough to write the code. To write the code, you need to know the actual words in that email. At most companies, programmers aren't trusted with words that a user might actually see (and for good reason, much of the time). So a marketing person or a PR person or some other English major is likely to be required to come up with the precise wording of the message. "Dear Shlub, Here's the password you forgot. Try not to be so careless in the future." When you force yourself to write a good, complete spec (and I'll talk a lot more about that soon), you notice all these things and you either fix them or at least you mark them with a big red flag.

写规范是敲定那些让人惹人生气的设计决定的最佳方案,不管大还是小,如果没有规范,那么这些就会被掩盖起来。有了规范,甚至是小的决定都会被敲定。例如,你在构建一个有会员的网站,你们也会都会同意如果用户忘记了密码,那么你就发邮件告诉他。很好。但那还没到要写代码的程度。要开始写代码,你需要知道电子邮件里的具体的用词。在大部分公司,程序员不会被写的用户最终看见的东西是不被信任的(通常是大部分时间都看见的东西,理由十足)。因此一个营销人员或者是个公共关系人员或者是其他英语专业的人员会被要求来写这些具体的措辞。“亲爱的Shlub,这是你忘记的密码。将来不要再这么不小心了。”当你强迫自己去写优秀的,完整的规范(我马上会大量的讨论这些),你会注意到所有这些东西,然后你要么纠正它们要么用红旗标出他们。

OK. We're on the same page now. Specs are motherhood and apple pie. I suspect that most people understand this, and my rants, while amusing, aren't teaching you anything new. So why don't people write specs? It's not to save time, because it doesn't, and I think most coders recognize this. (In most organizations, the only "specs" that exist are staccato, one page text documents that a programmer banged out in Notepad after writing the code and after explaining that damn feature to the three hundredth person.)

好,现在我们都知道了。规范是母性和苹果派。我怀疑大部分人不能理解这段,我的胡言乱语,虽然很娱乐,但是没有教你任何新的东西。那么为什么人么不愿意写规范呢?不是为了节省时间,因为那没有,我觉得所有的码农都认同这一点(在很多企业里,唯一存在的规范就是程序员在写完代码和向第三百个人解释了那个该死的功能之后在记事本里匆匆赶出的断断续续的文本。)

I think it's because so many people don't like to write. Staring at a blank screen is horribly frustrating. Personally, I overcame my fear of writing by taking a class in college that required a 3-5 page essay once a week. Writing is a muscle. The more you write, the more you'll be able to write. If you need to write specs and you can't, start a journal, create a weblog, take a creative writing class, or just write a nice letter to every relative and college roommate you've blown off for the last 4 years. Anything that involves putting words down on paper will improve your spec writing skills. If you're a software development manager and the people who are supposed to be writing specs aren't, send them off for one of those two week creative writing classes in the mountains.

我觉得是因为很多人不喜欢写作。盯着空白的屏幕实在是太令人沮丧了。就个人而言,我是通过参加大学时候课程来克服恐惧的,课程需要我们每周写3-5页的散文。写作是项肌肉训练。你写的越多,你就越会写。如果你要编写规范但是你不行,那就开个日记吧,创建个网志,参加创意写作班,或者就给在过去4年里被你无情忽视的亲戚大学同学写封漂亮的信吧。 任何包含在纸上记下字来的活动都会改善你写规范的能力。如果你是软件开发经理,而那些应该编写软件规范的人却没有编写,把他们派去参加那种山里的双周创意写作班吧。

If you've never worked in a company that does functional specifications, you may never have seen one. In the next part of this series, I'll show you a short, sample spec for you to check out, and we'll talk about what a good spec needs to have. Read on!

如果你从来没有在一个有功能规范的企业做过,那么你可能从来没见过。在接下来的这系列中,我将向你展示段的示例规范,以供你参考,我们会讨论好的规范需要有哪些点。继续读下去吧!