People have been writing programs for electronic computers for more than 80 years, but there has been surprisingly little conversation about how to design those programs or what good programs should look like. There has been considerable discussion about software development processes such as agile development and about development tools such as debuggers, version control systems, and test coverage tools. There has also been extensive analysis of programming techniques such as object-oriented programming and functional programming, and of design patterns and algorithms. All of these discussions have been valuable, but the core problem of software design is still largely untouched. David Parnas’ classic paper “On the Criteria to be used in Decomposing Systems into Modules” appeared in 1971, but the state of the art in software design has not progressed much beyond that paper in the ensuing 45 years.
人类通过电脑编程已经有 80 年的历史了,但是令人震惊的是,关于如何进行软件设计、好的软件究竟是怎样的的对话竟然如此之少。关于开发进度控制的讨论有相当多,包含敏捷开发、开发工具比如调试器、版本控制系统、测试覆盖工具等。大范围的关于面向对象编程、函数式、设计模式、算法的分析也不少。这些讨论都很有价值,但是软件设计的核心问题仍未被涉及。David Parnas 的经典论文《系统分解成模块的标准》发表于 1971,但是关于软件设计的艺术的描述,自从 45 年前被这篇论文提及以来,并没有多大的进步。
The most fundamental problem in computer science is problem decomposition: how to take a complex problem and divide it up into pieces that can be solved independently. Problem decomposition is the central design task that programmers face every day, and yet, other than the work described here, I have not been able to identify a single class in any university where problem decomposition is a central topic. We teach for loops and object-oriented programming, but not software design.
计算机科学最基础的问题,是复杂度控制:如何把复杂问题分解成可以被解决的小块。复杂度控制是程序员每天都要面对的核心任务。但是除了现在对这个话题的讨论,我从来没有见过大学里有一门课教授这个话题。我们教授循环语句和面向对象,但是不教软件设计。
In addition, there is a huge variation in quality and productivity among programmers, but we have made little attempt to understand what makes the best programmers so much better or to teach those skills in our classes. I have talked with several people I consider to be great programmers, but most of them had difficulty articulating specific techniques that give them their advantage. Many people assume that software design skill is an innate talent that cannot be taught. However, there is quite a bit of scientific evidence that outstanding performance in many fields is related more to high-quality practice than innate ability (see, for example, Talent is Overrated by Geoff Colvin).
另外,程序员之间的产出质量和效率之间有巨大的差异,但是我们却少有尝试去理解为什么最好的程序员,在技巧上比我们课堂上的各位强这么多。我跟一些厉害的程序员交流过,但是他们大多数并不能准确描述,是哪些技能让他们获得优势的。很多人觉得软件设计能力是一项天赋,是不能传授的。然而,大量的科学证据表明,在多个领域中的出色表现,高质量的练习的相关性比天生的才能更多。(可以看看 Geoff Colvin 的《被高估的天赋》)
For many years these issues have perplexed and frustrated me. I have wondered whether software design can be taught, and I have hypothesized that design skill is what separates great programmers from average ones. I finally decided that the only way to answer these questions was to attempt to teach a course on software design. The result is CS 190 at Stanford University. In this class I put forth a set of principles of software design. Students then work through a series of projects to assimilate and practice the principles. The class is taught in a fashion similar to a traditional English writing class. In an English class, students use an iterative process where they write a draft, get feedback, and then rewrite to make improvements. In CS 190, students develop a substantial piece of software from scratch. We then go through extensive code reviews to identify design problems, and students revise their projects to fix the problems. This allows students to see how their code can be improved by applying design principles.
多年来这些问题一直让我困惑沮丧。我有考虑过软件设计是否能被教授,曾经也假设过是否拥有设计的技巧,就是区分伟大程序员与普通程序员的指标。最后我决定尝试通过开设软件设计课程这种方式,来尝试解开这个问题。结果就是 CS 190 这门课在斯坦福大学诞生了。在这门课里,我提出了一系列软件设计的准则。学生们可以通过一系列的项目去理解和实践这些准则。这门课以一种类似于传统英语写作的时尚方式,学生反复地进行打草稿、获得反馈、重构优化。他们从头开始学习软件设计中极为重要的一环。然后我们通过大量的代码评审,去认识设计问题,再让学生修正项目。这种方式让学生们看到,应用这些准则后,他们的代码是如何得到改进的。
I have now taught the software design class three times, and this book is based on the design principles that emerged from the class. The principles are fairly high level and border on the philosophical (“Define errors out of existence”), so it is hard for students to understand the ideas in the abstract. Students learn best by writing code, making mistakes, and then seeing how their mistakes and the subsequent fixes relate to the principles.
如今我已经教授这门课 3 次了,并把其中总结到的设计准则作为这本书的根基。这些准则在哲学层面上(定义不存在的问题),水平高并且广度大。所以对于学生来说很难在抽象层面去理解这些思想。最好的学习方式是通过编写代码,然后犯错,最后看看这些准则如何与修正错误是相关的。
At this point you may well be wondering: what makes me think I know all the answers about software design? To be honest, I don’t. There were no classes on software design when I learned to program, and I never had a mentor to teach me design principles. At the time I learned to program, code reviews were virtually nonexistent. My ideas about software design come from personal experience writing and reading code. Over my career I have written about 250,000 lines of code in a variety of languages. I’ve worked on teams that created three operating systems from scratch, multiple file and storage systems, infrastructure tools such as debuggers, build systems, and GUI toolkits, a scripting language, and interactive editors for text, drawings, presentations, and integrated circuits. Along the way I’ve experienced firsthand the problems of large systems and experimented with various design techniques. In addition, I’ve read a considerable amount of code written by other people, which has exposed me to a variety of approaches, both good and bad.
到这里也许你就疑惑了:是什么让我觉得我掌握了软件设计的所有答案?老实说,我没有掌握。我当初学习编程的时候,没有软件设计这门课,也没有导师叫我设计准则。我学编程那会代码评审甚至还没诞生。我的那些关于软件设计的思想,来自于编写和阅读代码的经验。职业生涯中,我编写了 250,000 行代码,用过多种语言。我曾经在从头开始设计过 3 种操作系统的团队里工作过,设计过文件存储系统、基础开发工具比如调试器、构建系统、GUI 工具包、一种脚本语言、文本的交互式编辑器、绘画、幻灯片、集成电路。一路走来,我亲身经历了大量大型系统的问题,并实践过多种设计技术。另外,我还阅读过非常大量的别人写的代码,从中接触到了各种各样的方法,有好的也有坏的。
Out of all of this experience, I’ve tried to extract common threads, both about mistakes to avoid and techniques to use. This book is a reflection of my experiences: every problem described here is one that I have experienced personally, and every suggested technique is one that I have used successfully in my own coding.
从所有的经验中,我尝试从中提取出共同点,包括要避免的错误和要实行的技巧。这本书就是我的经验的反映:书中的每个问题都是我亲身经历的,每个提议的技巧都是我亲自在编码中成功实践过的。
I don’t expect this book to be the final word on software design; I’m sure there are valuable techniques that I’ve missed, and some of my suggestions may turn out to be bad ideas in the long run. However, I hope that the book will start a conversation about software design. Compare the ideas in this book with your own experiences and decide for yourself whether the approaches described here really do reduce software complexity. This book is an opinion piece, so some readers will disagree with some of my suggestions. If you do disagree, try to understand why. I’m interested in hearing about things that work for you, things that don’t work, and any other ideas you may have about software design. I hope that the ensuing conversations will improve our collective understanding of software design. I will incorporate what I learn in future editions of this book.
我不认为这本书是软件设计的最终答案,我十分确定还有重要的技巧被我遗漏了,还有,一些建议从长远看来也许并不少好主意。但我还是希望这本书能开启关于软件设计的讨论。用书中的想法与你的实际经验去比较,再去看看这些方法是否减少了软件复杂度。这本书只是一些个人意见,肯定会有人不同意当中的一些看法。如果你也不同意,请理解一下其中的缘由。我很想听听哪些对你有用,哪些没有,还有你对于软件设计的看法。我希望后续的讨论能促进我们对软件设计的集体理解,我也会在这本书的后续版本中增加我进一步的学习成果。
The best way to communicate with me about the book is to send email to the following address:
[email protected]
要与我讨论书中的内容,最好的方式就是发送到以下邮箱:
I’m interested in hearing specific feedback about the book, such as bugs or suggestions for improvement, as well as general thoughts and experiences related to software design. I’m particularly interested in compelling examples that I can use in future editions of the book. The best examples illustrate an important design principle and are simple enough to explain in a paragraph or two. If you would like to see what other people are saying on the email address and participate in discussions, you can join the Google Group software-design-book.
我十分欢迎关于这本书的具体的反馈,比如 BUG 或者改进的建议,还有关于软件设计的一般思想和经验。特别是引人注目的实际例子,这样我就能把它加入到书的再版中。最好例子能阐述一个重要的设计准则,并且能用一两句话就能描述清楚了。如果你想看看其他人在这个邮件地址里说什么,讨论什么,可以加入 software-design-book 谷歌小组。
If for some reason the software-design-book Google Group should disappear in the future, search on the Web for my home page; it will contain updated instructions for how to communicate about the book. Please don’t send book-related email to my personal email address.
如果某种原因导致这个小组消失了,请搜索我的主页,里面会更新探讨这本书的联系方式。请不要发送到我的个人邮箱。
I recommend that you take the suggestions in this book with a grain of salt. The overall goal is to reduce complexity; this is more important than any particular principle or idea you read here. If you try an idea from this book and find that it doesn’t actually reduce complexity, then don’t feel obligated to keep using it (but, do let me know about your experience; I’d like to get feedback on what works and what doesn’t).
我建议你从听取书中的提议的时候,持保留态度。因为整体来说,目的是减少复杂度,这比任何一个你从中读到的特定的指标都要重要。如果用了书中的思想,然后发现复杂度并未实质性地减少,那就不需要再觉得仍有义务去使用它(但是还请通知我关于你的经历,因为我获得哪些有用哪些没有的反馈)。
Many people have offered criticisms or made suggestions that improved the quality of the book. The following people offered helpful comments on various drafts of the book: Jeff Dean, Sanjay Ghemawat, John Hartman, Brian Kernighan, James Koppel, Amy Ousterhout, Kay Ousterhout, Rob Pike, Partha Ranganathan, Keith Schwartz, and Alex Snaps. Christos Kozyrakis suggested the terms “deep” and “shallow” for classes and interfaces, replacing previous terms “thick” and “thin”, which were somewhat ambiguous. I am indebted to the students in CS 190; the process of reading their code and discussing it with them has helped to crystallize my thoughts about design.
已经有很多人为这本书提供了建议或者批评,来提升本书的质量。以下这些朋友为初稿提供了有用的评价:Jeff Dean, Sanjay Ghemawat, John Hartman, Brian Kernighan, James Koppel, Amy Ousterhout, Kay Ousterhout, Rob Pike, Partha Ranganathan, Keith Schwartz, 还有 Alex Snaps。Christos Kozyrakis 建议使用词语“深度的”和“浅层的”,代替之前有些模糊的词汇“厚的”和“薄的”。我对 CS 190 班的学生们深表感激,阅读和讨论他们的代码的过程,帮助我验证了关于设计的想法。