综观软件设计的历史,你可以看到大量的、相互矛盾的设计方法被各自的支持者们所鼓吹。当我在20世纪90年代早期发表《代码大全》第1版时,设计方案的信徒们正在鼓吹说在着手编码之前,应该完善设计的每一处细节。这种推荐事实上根本没有任何意义。
当我在21世纪前十年的中期撰写现在这个版本时,一些软件学者正在争辩说根本不需要做任何的设计。“预先做大量的设计(Big Design Up Front)是BDUF”他们说,“BDUF很不好。你在着手写代码之前最好不要做丝毫的设计!”
十年之内,设计的钟摆就从“设计一切”摆动到了“不做设计”。不过,BDUF的替换方案却不是不做预先设计,而是预先做一点设计(Little Design Up Front, LDUF),或者预先做足够的设计(Enough Design Up Front,ENUF)。
那么你怎样才能判断出需要多少设计才够呢?这是一个主观判断,没有人能完美地回答它。不过,在你没有足够的信心去判断最佳设计量的时候,请记住有两种情况一定是不对的:设计所有的细节和不做任何设计。这两个由位于立场两端的极端主义者所倡导的做法,恰恰被证明是仅有的两个永远是错误的做法。
正如P.J. Plauger所言,“你在应用某种设计方法时越教条化,你所能解决的现实问题就会越少”(Plauger 1993)。请把设计看成是一个险恶的、杂乱的和启发式的过程。不要停留于你所想到的第一套解决方案,而是去寻求合作,探求简洁性,在需要的时候做出原型,迭代,并进一步迭代。你将对自己的设计成果感到满意。
Additional Resources
更多资源
软件设计是个非常富饶的领域,有大量的资源可以使用,你面临的挑战是找出哪些资源最有用。下面就此给出一些建议:
Software Design, General
软件设计,一般性问题
Weisfeld, Matt. 《The Object-Oriented Thought Process》(《面向对象的思考过程(第二版)》), 2d ed. SAMS, 2004. 这是一本易于理解的介绍面向对象编程的书。如果你已经很熟悉面向对象编程,那么可能需要一本更高级的书,不过如果你刚刚涉足面向对象领域,那么这本书介绍了面向对象的一些基本概念,包括对象、类、接口、继承、多态、重载、覆盖、抽象类、聚合和联合、构造函数和析构函数、异常等等。
Riel, Arthur J. 《Object-Oriented Design Heuristics》(《OOD启思录》). Reading, MA: Addison-Wesley, 1996. 这本书关注在类这一层次上的设计,非常容易理解。
Plauger, P.J. 《Programming on Purpose: Essays on Software Design》. Englewood Cliffs, NJ: PTR Prentice Hall, 1993. 我从这本书里学到的有关软件设计的好点子和我从所有读过的其他书中学到的一样多。Plauger精通大量的设计方法,他很注重实效,同时也是个伟大的作家。
Meyer, Bertrand. 《Object-Oriented Software Construction》(《面向对象软件构造》), 2d ed. New York, NY: Prentice Hall PTR, 1997. Meyer在这里极力提倡彻底的面向对象编程。
Raymond, Eric S. 《The Art of UNIX Programming》(《UNIX编程艺术》). Boston, MA: Addison-Wesley, 2004. 这本书从Unix的角度很好地研究了软件设计。第1.6节用12页的篇幅简明扼要论述了17项关键的Unix设计原则。
Larman, Craig. 《Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and the Unified Process》(《UML和模式应用》), 2d ed. Englewood Cliffs, NJ: Prentice Hall, 2001. 这是一本很流行的基于统一过程(Unified Process)介绍面向对象设计的著作。书中同时还讨论了面向对象分析。
Software Design Theory
软件设计理论
Parnas, David L., and Paul C. Clements. “A Rational Design Process: How and Why to Fake It.”(一种理性的设计过程:如何以及为何去仿制它) 《IEEE Transactions on Software Engineering》 SE-12, no. 2 (February 1986): 251—257. 这篇经典文章描述了在程序的设计理想和实际之间的巨大差距。关键之处在于没有人真正经历过理性的、有序的设计过程,但是以此为目标的确能在最后产生出更好的设计方案。
我不知道是否有全面论述信息隐藏的资料。大多数的软件工程书里都只是简单地提了一下,通常都是在讲述面向对象技术的语境中提及。下面列出的Parnas的三篇文章,是他关于这一想法的学术论文,大概也是到目前为止有关信息隐藏的最好的资料了:
Parnas, David L. “On the Criteria to Be Used in Decomposing Systems into Modules.”(论将系统分解为模块的准则) 《Communications of the ACM》 5, no. 12 (December 1972): 1053—1058.1
Parnas, David L. “Designing Software for Ease of Extension and Contraction.”(设计易于扩展和收缩的软件) 《IEEE Transactions on Software Engineering》 SE-5, no. 2 (March 1979): 128—138.
Parnas, David L., Paul C. Clements, and D. M. Weiss. “The Modular Structure of Complex Systems.”(复杂系统的模块化架构) 《IEEE Transactions on Software Engineering》 SE-11, no. 3 (March 1985): 259—266.
Design Patterns
设计模式
Gamma, Erich, et al.《Design Patterns》(《设计模式》). Reading, MA: Addison-Wesley, 1995. 这本由“四人组(GoF)”写成的著作是设计模式领域的开山之作。
Shalloway, Alan, and James R. Trott. 《Design Patterns Explained》(《设计模式精解》). Boston, MA: Addison-Wesley, 2002. 这本书对设计模式做了深入浅出的介绍。
Design in General
广义的设计
Adams, James L. 《Conceptual Blockbusting: A Guide to Better Ideas》, 4th ed. Cambridge, MA: Perseus Publishing, 2001. 尽管这本书不是专门讲解软件设计的,但斯坦福大学用它来向工科学生讲解设计。哪怕你从不做任何的设计,这本书也对创新思维过程做了非常棒的描述。书中包含了很多有效设计所需的思维训练,同时还给出并且很好地评荐了一份有关设计和创造性思维的书目。如果你喜欢解决问题,那么你会喜欢这本书的。
Polya, G. 《How to Solve It: A New Aspect of Mathematical Method》, 2d ed. Princeton, NJ: Princeton University Press, 1957. 这本书讲解了数学领域中的启发式方法和问题求解,但是也同样适用于软件开发。Polya的这本书首次在数学问题求解领域内引入启发式方法。他在书中清楚地区分了用于探索问题的杂乱无章的启发式方法,和一旦找到解决方案后如何呈现解法的整理方法。这本书读起来并不容易,可是如果你对启发式方法感兴趣,那么不管你想不想,最终都会去读它。Polya在书中明确说明,问题求解并不是一个确定性的活动,如果你固执在某一种方法之上,那么无异于作茧自缚。曾经有一段时间,Microsoft把这本书送给了她的所有新员工。
Michalewicz, Zbigniew, and David B. Fogel. 《How to Solve It: Modern Heuristics》(《如何求解问题——现代启发式方法》). Berlin: Springer-Verlag, 2000. 这本书对Polya的书做出了更新,相比之下更容易阅读,而且包含了一些非数学领域的例子。
Simon, Herbert. 《The Sciences of the Artificial》, 3d ed. Cambridge, MA: MIT Press, 1996. 这本书对与自然界相关的科学(生物学、地质学等)和与人造世界相关的科学(商业、建筑以及计算机科学)之间的差异做了非常精彩的描述。接下来,书中讨论了与人造世界相关的科学的特征,并着重强调了设计科学。对于那些渴望在软件开发或者任何“人造的”领域内工作的人来说,这都是一本很好的学院派论著,值得一读。
Glass, Robert L. 《Software Creativity》. Englewood Cliffs, NJ: Prentice Hall PTR, 1995. 软件开发更多地是由理论指导还是由实践指导?软件开发从根本上而言是创造性的还是确定性的?软件开发人员需要什么样的智力资质?这本书针对软件开发的本质展开了有趣的讨论,并且特意关注了设计。
Petroski, Henry. 《Design Paradigms: Case Histories of Error and Judgment in Engineering》. Cambridge: Cambridge University Press, 1994. 这本书主要讨论土木工程领域(特别是桥梁设计)的情况,作者的观点是:成功的设计至少应该同等地依赖于从过去的失败中学习和从过去的成功中学习。
Standards
标准
IEEE Std 1016—1998, Recommended Practice for Software Design Descriptions. 这份文档包含了用于描述软件设计的IEEE-ANSI标准。它说明了应该把哪些放入软件设计文档中。
IEEE Std 1471—2000. Recommended Practice for Architectural Description of Software Intensive Systems. Los Alamitos, CA: IEEE Computer Society Press. 这份文档是用于创建软件架构规范的IEEE-ANSI指南。
|
CHECKLIST: Design in Construction 核对表:软件构造中的设计 设计实践 q 你已经做过多次迭代,并且从众多尝试结果中选择最佳的一种,而不是简单选择第一次尝试的结果吗? q 你尝试用多种方案来分解系统,以确定最佳方案吗? q 你同时用自下而上和自上而下的方法来解决设计问题吗? q 为了解决某些特定的问题,你对系统中的风险部分或者不熟悉的部分创建过原型、写出数量最少的可抛弃的代码吗? q 你的设计方案被其他人检查了吗(无论正式与否)? q 你一直在展开设计,直到实施细节跃然纸上了吗? q 你用某种适当的技术——比如说Wiki、电子邮件、挂图、数码照片、UML、CRC卡或者在代码写注释——来保留设计成果吗? 设计目标 q 你的设计是否充分地处理了由系统架构层定义出并且推迟确定的事项? q 你的设计被划分为层次吗? q 你对把这一程序分解成为子程序、包和类的方式感到满意吗? q 你把对这个类分解成为子程序的方法感到满意吗? q 类与类之间的交互关系是否已设计为最小化了? q 类和子程序是否被设计为能够在其他的系统中重用? q 程序是不是易于维护? q 设计是否精简?设计出来的每一部分都绝对必要吗? q 设计中是否采用了标准的技术?是否避免使用怪异且难以理解的元素? q 整体而言,你的设计是否有助于最小化偶然性的和本质性的复杂度吗? |
Key Points
要点
■ 软件的首要技术使命就是管理复杂度。以简单性作为努力目标的设计方案对此最有帮助。
■ 简单性可以通过两种方式来获取:一是减少在同一时间所关注的本质性复杂度的量,二是避免生成不必要的偶然的复杂度。
■ 设计是一种启发式的过程。固执于某一种单一方法会损害创新能力,从而损害你的程序。
■ 好的设计都是迭代的。你尝试设计的可能性越多,你的最终设计方案就会变得越好。
■ 信息隐藏是个非常有价值的概念。通过询问“我应该隐藏些什么?”能够解决很多困难的设计问题。
■ 很多有用有趣的、关于设计的信息存在于本书之外。这里所给出的观点只是对这些有价值资源的一点提示而已。







