01 前言
80多年来,人们一直在为计算机编写程序,但令人惊讶的是,关于如何设计这些程序或什么是好程序的讨论却少之又少。关于软件开发过程(如敏捷开发)和开发工具(如调试器、版本控制系统和测试覆盖工具),已经有了相当多的讨论。还广泛分析了编程技术,如面向对象编程和函数式编程,以及设计模式和算法。所有这些讨论都是有价值的,但是软件设计的核心问题在很大程度上仍然没有触及。David Parnas的经典论文“关于将系统分解成模块的标准”发表于1971年,但是在随后的45年里,软件设计的技术水平并没有超过这篇论文。
计算机科学中最基本的问题是问题分解:如何把一个复杂的问题分解成可以独立解决的几个部分。问题分解是程序员每天都要面对的核心设计任务,然而,除了这里描述的工作,我还没有在任何一所大学里找到一个以问题分解为中心主题的类。我们教循环和面向对象编程,但不教软件设计。
此外,程序员之间在质量和生产力方面存在巨大差异,但是我们很少尝试去理解是什么让最好的程序员变得更好,或者在我们的课堂上教授这些技能。我曾与一些我认为是优秀的程序员的人交谈过,但是他们中的大多数人都很难清楚地表达出那些给他们带来优势的特定技术。许多人认为软件设计技能是一种天生的天赋,是不能被教授的。然而,有相当多的科学证据表明,在许多领域的杰出表现更多地与高质量的实践有关,而不是天生的能力(例如,杰夫•科尔文高估了才能)。
多年来,这些问题一直困扰和困扰着我。我想知道是否可以教授软件设计,我假设设计技能是区分优秀程序员和一般程序员的关键。我最终决定,回答这些问题的唯一方法是尝试教授一门软件设计的课程。结果是斯坦福大学的CS 190。在这门课上,我提出了一套软件设计的原则。然后学生通过一系列的项目来吸收和实践这些原则。这门课的教学方式与传统的英语写作课类似。在英语课上,学生们使用一种迭代的过程,他们先写一份草稿,得到反馈,然后重写以做出改进。在CS190中,学生们从零开始开发了大量的软件。然后,我们进行广泛的代码审查,以确定设计问题,学生修改他们的项目来解决问题。这让学生看到如何通过应用设计原则来改进他们的代码。
我现在已经教过三次软件设计课,这本书是基于这门课的设计原则。这些原则是相当高水平的,接近于哲学(“定义错误不存在”),所以学生很难理解抽象的思想。学生通过编写代码、犯错误,然后查看他们的错误和随后的修复如何与原则相关,从而获得最佳的学习效果。
此时您可能会想:是什么让我认为我知道关于软件设计的所有答案?老实说,我不知道。当我开始学习编程的时候,我没有上过软件设计的课程,也没有导师来教我设计原则。在我学习编程的时候,代码评审几乎是不存在的。我对软件设计的想法来自于编写和阅读代码的个人经验。在我的职业生涯中,我用各种语言写了大约250,000行代码。我的团队从零开始创建了三个操作系统、多个文件和存储系统、基础设施工具(如调试器、构建系统和GUI工具包)、脚本语言以及用于文本、绘图、演示和集成电路的交互式编辑器。在此过程中,我亲身体验了大型系统的问题,并尝试了各种设计技术。此外,我还阅读了大量其他人编写的代码,这使我接触到各种方法,有好的也有坏的。
在所有这些经验中,我尝试提取一些常见的线索,包括要避免的错误和要使用的技术。这本书反映了我的经验:这里描述的每一个问题都是我个人经历过的,每一个建议的技术都是我在自己的编码中成功使用过的。
我不希望这本书成为软件设计的最后定论;我确信我错过了一些有价值的技巧,从长远来看,我的一些建议可能会变成糟糕的主意。然而,我希望这本书能够开启一个关于软件设计的对话。将本书中的思想与您自己的经验进行比较,然后自行决定这里描述的方法是否真的降低了软件的复杂性。这本书是一篇观点文章,所以有些读者会不同意我的一些建议。如果你不同意,试着去理解为什么。我感兴趣的是那些对你有用的东西,那些没用的东西,以及你对软件设计的其他想法。我希望接下来的对话将提高我们对软件设计的整体理解。我将把我学到的东西写进这本书的未来版本里。
与我沟通这本书的最好方式是发邮件到以下地址:
software-design-book@googlegroups.com
我对听到关于这本书的具体反馈很感兴趣,比如bug或改进建议,以及与软件设计相关的一般想法和经验。我特别感兴趣的是可以在本书未来版本中使用的引人注目的例子。最好的例子说明了一个重要的设计原则,并且简单到可以用一两段话来解释。如果你想知道其他人在电子邮件地址上说了什么,并参与讨论,你可以加入谷歌组软件设计书籍。
如果因为某种原因,软件设计书籍谷歌组将来应该消失,在网上搜索我的主页;它将包含如何沟通这本书的更新说明。请不要将与书籍相关的邮件发送到我的个人邮箱。
我建议你对这本书中的建议有所保留。总的目标是减少复杂性;这比你在这里读到的任何特定的原则或思想都要重要。如果你从这本书中尝试了一个想法,发现它并没有减少复杂性,那么不要觉得有义务继续使用它(但是,一定要让我知道你的经验;我想要得到关于什么可行什么不可行的反馈)。
许多人提出了批评或建议,以提高这本书的质量。以下这些人对这本书的不同版本提供了有益的意见:杰夫·迪恩、桑杰·格玛沃特、约翰·哈特曼、布莱恩·克尼汉、詹姆斯·科佩尔、艾米·奥斯特豪特、凯·奥斯特豪特、罗伯·派克、帕莎·兰加纳坦、基思·施瓦茨和亚历克斯·斯纳普斯。Christos Kozyrakis建议用“深”和“浅”来表示类和接口,而不是以前的“厚”和“薄”,这两个词有些模棱两可。我很感激CS 190的学生们;阅读他们的代码并与他们讨论代码的过程有助于明确我对设计的想法。