祛魅设计模式:封神的三十年

楔子

长期以来,设计模式被认为是软件工程师的进阶课程。尝试学习并使用设计模式,意味着编写代码的过程开始变得系统而慎重。从原先胡抡“王八拳”讲究实用主义,到后来事事留意,处处小心,也开始说些什么“设计原则”,什么“艺术”“范式”之类艰涩难懂的话。

可以说,设计模式就是软件开发领域的《三十六计》,是指导编程实践的强大思想武器

自1994年,Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides首次出版了《设计模式:可复用面向对象软件的基础》一书,并提出23种设计模式之后,设计模式就不断应用于各类软件开发实践,并逐步被软件工程师奉为圭臬。

但设计模式过于侧重理论的特点,又引发两个突出问题,进而走向两个极端。

一部分人仍将学习设计模式视为畏途,大多浅尝辄止,束之高阁;另一部分则“无设计不代码”,实践中不乏过度设计,甚至教条主义。前者无非继续堆砌平庸的代码,不求有功,但求无过。后者则把代码写得高深莫测,花拳绣腿,故弄玄虚。

须知,软件工程自20世纪60年代诞生,至今已走过半个多世纪,设计模式也已经提出将近30年,编程早已不是一门新兴的学问。当然,前提是在发达国家。

显然,我国规模化的信息工程教育起步较晚,家用电脑的普及也是在新世纪之后。总体来看,我国软件工程师的专业能力和编程素养与发达国家平均水平仍保持一定的差距

有感于设计模式在国内IT及互联网公司的普及度仍然很低,也有感于介绍设计模式的国内技术博客虽汗牛充栋,却珠玉难觅,故决定自己编写一系列关于设计模式的文章。

一方面作为笔者从业多年的所学所思所做的工作随笔,另一方面作为运用辩证唯物主义世界观对设计模式进行一次彻底“祛魅”的实践。如能为国内面向对象程序设计理论传播做出一点微小的贡献,那便是极好的。

本系列计划将每种设计模式单独成篇,力保一章篇幅将其说清讲透。讲解顺序也并非严格按照GoF设计模式所列,而是总体按照掌握程度先易后难、使用频率先高后低的原则进行编写。

同时,虽则本系列力求完整介绍每种设计模式,但仍会穿插大量进阶内容进行讨论,故期望读者具备基本的设计模式理论储备,以备不时之需。

而作为本系列开篇的,则是一段设计模式史话

外行的演讲

1996年10月,美国加州圣何塞市McEnery会议中心,数千名前来参加OOPSLA'96(Object-Oriented Programming, Systems, Languages, and Applications)大会的软件工程师和计算机科学家正翘首以盼,等待从即将演讲的嘉宾那里领略无尽的哲思,汲取充沛的养分。

有趣的是,在这一面向对象编程领域年度研究盛会上,马上要登台布道的嘉宾,既非James Gosling(詹姆斯·高斯林)这样的编程语言大师,亦非Richard Stallman(理查德·斯托曼)这样的自由软件领袖。

他既不懂什么计算科学,也不懂编程,甚至在受邀演讲时不清楚应该谈些什么。照他的话讲,大约两三年前,他听说硅谷有一群人愿意花3000美元请他吃饭,他才第一次知道自己的研究与计算机学界建立了联系。

这位演讲嘉宾叫Christopher Alexander(克里斯托弗·亚历山大),是加州大学伯克利分校的一名建筑学教授,也是一名建筑师。

尽管Alexander几乎全程都在讲他几十年来在建筑界做了什么工作,并不断强调,他其实并不太懂这些工作是否对计算机界有所启发或帮助。但这,丝毫不影响台下观众以朝圣一般的虔诚认真聆听演讲者的教诲。

乃至最后,当Alexander深切控诉建筑同行的短视以及开发商的贪婪,并振臂一呼,号召全体计算机界同仁帮助他,接过本应由建筑师扛起的改变世界的大旗,使世界环境成为一个生命结构的宏愿时,情至深处,不乏观众热泪盈眶,为之动容。

这股理想主义的暗流涌动,在彼时正在缓慢拉开互联网泡沫破裂序幕的美国,显得尤其难得。

诚如本届OOPSLA大会执行主席James Coplien邀请Christopher Alexander时对他所言:“……(你)想说什么说什么。因为是你讲,而你就是这种模式问题的历史,人们一定会认为它很有趣[1]。”

显然,正在经历第二次软件危机的人们,并不觉得听一位建筑学教授侃侃而谈一个多小时的建筑理论是多么的枯燥乏味。相反,软件工程学者从几年前甚至更早便注意到Alexander对建筑的研究,并意外地发现,其模式理论同样可以用于指导软件的设计与开发。

相较于积累千年的人类建筑经典案例,仅有不到30年历史的软件工程学却鲜有优秀系统或经典理论可供参考,软件行业亟需“摸着建筑行业过河”

这大概就是OOPSLA'96大会邀请Alexander为软件行业从业者进行这场讲座的初衷。与他久负盛名的模式理论相比,人们更不愿意放过这一理论的过去、现在和未来。

1977年,Alexander与加州大学伯克利分校环境结构中心的五位同事,共同撰写出版了鸿篇巨著《建筑模式语言》(A Pattern Language),书中描述了城镇、邻里、住宅、花园和房间等共253个模式。两年后,他们又出版了另一本书《建筑的永恒之道》(The Timeless Way of Building)

前者描述各种详尽的模式,后者解释原理并指导实践。两书出版后立刻成为长销不衰的经典建筑理论著作。

但Alexander定然不会料到,十几年后,这些想法竟意外地在不涉及木材和砖瓦,甚至无法感知重量的软件行业生根发芽,并取得一席之地。Alexander更不会料到,他一个建筑学教授,怎么就成计算机学界公认的模式语言运动之父了呢?

一次跨界实验

最先将Alexander的研究应用到软件行业里的,恐怕要算Kent Beck和Ward Cunningham了。

1987年,两位年轻的工程师正在泰克公司(Tektronix)为面向对象编程寻找新的合适的方法论。

他们已然意识到,面向对象编程是如此特殊,以至于过往的编程经验完全无法释放其巨大的潜力。当时,Kent和Ward正在为基于Smalltalk语言开发的用户界面设计问题头疼,两人期待一场彻底的变革。

很快,他们就在Alexander的工作中看到了希望。

Alexander建议,住宅和办公室应该由最终居住者设计和建造,因为这些人最清楚他们的要求。

Kent和Ward认为,这个论点同样适用于计算机程序,即计算机用户应该编写自己的程序。但考虑到软件开发的复杂性以及专业性,这个想法看起来难以成行,然而Alexander的“模式语言”概念似乎提供了这种可能性。

按照Alexander的说法,模式是上下文中问题的解决方案(A pattern is a solution to a problem in a context),是能重复使用且不限定领域的实用指南,是将专业知识传递给他人的主要机制[2]

仿照Alexander的模式语言,Kent和Ward设计了一种非常轻量的用于设计Smalltalk窗口的模式语言,其中包含五个模式。他们向另外一组工程师介绍了这些模式,然后发现,在没有详细了解Smalltalk的任何接口机制的情况下,这组工程师能够在一天的实践后指定非常合理的接口。

Kent和Ward将这次实践写成论文,题为《在面向对象程序中使用模式语言》(Using Pattern Languages for Object-Oriented Programs),并提交给了当年的OOPSLA'87大会。

他们不无兴奋地写道:“我们已经完成了大约十个模式,还草拟出20到30个,预计最终的模式语言将包含大约100到150个模式。我们初步成功地使用模式语言对用户界面进行设计,使我们对计算机用户设计和编写自己的应用程序的可能性充满了热情。”

OOPSLA'87大会的一场专题讨论会,给软件行业送来了Alexander的模式理论。

尽管,人们最终也没能够看到这种包含100多个模式的完整版的“面向对象程序设计”的模式语言问世,Kent和Ward的尝试似乎也偃旗息鼓。

但是,如果你知道——Kent在多年以后开创了极限编程方法学,成为测试驱动开发的创始人,Ward则搭建了世界上第一个Wiki网站,是“技术债务”概念的提出者,两位还同是敏捷宣言签署人——的话,或许可以理解,这次粗浅的跨界探索,对Kent和Ward两位行业泰斗来说,也许仅是一次玩票性质的先锋实验,但对刚刚迎来面向对象程序设计的软件行业来说,却是一场荡涤思想的启蒙运动。

Alexander的模式理论火种在软件行业被逐渐点燃。

独辟蹊径

在OOPSLA'90大会的一场关于“设计可复用设计”(Designing Reusable Designs)的专题讨论会上,一群具有丰富设计经验的面向对象框架专家齐聚一堂:

C++用户界面框架InterViews的核心开发人员,图形编辑器框架Unidraw的作者,来自IBM沃森研究中心的John Vlissides;Smalltalk绘图编辑器框架HotDraw的开发者,来自泰克公司的Ward Cunningham;操作系统研究计划Choices的面向对象专家,来自伊利诺伊大学厄巴纳-香槟分校的Ralph Johnson……

作为优秀的框架设计者,彼时的他们,正致力于消除开发者对于使用框架而不是从头构建程序的疑虑,也正沉浸在框架带给软件工程师巨大复用红利的无限遐想之中。

但用不了多久,他们便会意识到,推销框架无非是授人以鱼,而真正授人以渔的方法,恰恰蕴藏在自己写就的框架源代码中,那里有远比使用框架更玄妙高深的复用之道。

Coplien是这方面的先行者。

1991年,AT&T贝尔实验室的Coplien出版了高阶编程书籍《Advanced C++》(Advanced C++ programming styles and idioms)。在这本书中,Coplien试图将C++语言专家们所获得的编程经验传授给读者,围绕他所谓“习惯用法”(idiom)的形式来组织表达。

他认为,程序设计同自然语言一样,重要的习惯用法,或者说好的习惯用法可以大大减轻程序员的工作量,就好像在任何一种语言中习惯用法丰富了相互之间的交流一样。

当时,Coplien已经意识到,习惯用法是可复用程序设计的“表述”,将大大提高对问题的洞察力,却很少是程序设计的核心,因为,习惯用法引入了某种复杂性。可习惯用法一旦构造成功,就可以到处运行,程序设计语言的习惯用法便蕴含在约定和技巧之中。

Coplien在书中列举了大量风格化的代码范例:

如通过引入表示共享和引用计数的机制来改善类的性能和特殊类的内存使用,把已有的类转换成使用引用计数;又如通过处理/主体类(Handle/Body)的习惯用法在多个对象间共享同一行为,通过信封/信件类(Envelope/Letter)的习惯用法增强前者的灵活性以及封装性;再如通过功能元件(functor)的习惯用法利用虚拟函数的继承来代替对象的函数……

从某种角度来看,Coplien所谓的习惯用法,这种在特定编程语言上下文中具体的解决方案,就是某种通过观察捕捉到的模式。但《Advanced C++》毕竟是一本描述如何提高C++编程技巧的书,而非讲解模式的书。与Alexander动辄上百种的建筑模式相比,这些习惯用法单薄、特殊且不成体系。

不过,Coplien显然蹚对了路。

而在大西洋彼端的欧洲,那里的软件行业似乎同时进行着一场关于模式理论的平行演化,让我们把时间往回拨一下。

大洋彼岸的独立演化

1984年,瑞士苏黎世大学计算机科学研究所启动了一个项目,旨在高效开发具有现代用户界面的计算机辅助软件。

研究小组很快发现,只有使用可复用的软件组件才能合理地实现这一需求。为此,他们开发了一套基于C语言的工具包,叫做ET(Editor Toolkit),并成功应用于多个项目。

但没过几年,当面向对象编程思想正以王者之势席卷整个软件行业的时候,他们认识到ET这一基于面向过程语言的应用框架开始显得力不从心了。于是,在1987年早些时候,他们便启动了基于C++语言的面向对象的应用框架开发工作,并称之为ET++(ET + C++ = ET++)

随着ET++的不断发展,尤其是在瑞士联合银行信息学实验室(UBILAB)成功将其应用于金融领域之后,到1992年ET++ 3.0版本发布,ET++已经从当初的学校实验项目,成长为一个成熟的可移植的面向对象类库。

同年,研究小组的一名成员,以他一年前的博士论文为基础,出版了德文技术书籍《基于ET++的面向对象软件开发》(Objektorientierte Software-Entwicklung am Beispiel von ET++)

同几乎所有介绍开发框架的技术文献内容一致,作者讲解了ET++的数据结构、组件类库、应用示例等等特性,除此之外,他还用了接近一半的篇幅介绍了一种在ET++应用的支持面向对象设计的方法,并称之为“设计模式”(德文:Design-Muster,英文:Design Pattern)

作者为何对设计模式颇费笔墨?

原来,这位研究员在ET++的开发过程中,发现有一些设计结构是反复出现的,而这些结构通常可以使代码设计变得更加优雅,更具灵活性和可重用性。

为此,研究员做了一件有益的工作,他仔细观察这些经常出现的设计结构,将其共性进行高度抽象,并用“设计模式”这一概念来描述该设计结构的名字、意图和组织形式。如此一来,在设计新系统或改进现有系统时,就可以复用这些设计模式了。

他在论文中写道:“通过抽象ET++中使用的设计结构,确定了所谓的设计模式。设计模式是某些抽象的类结构,已被证明对ET++很有用,也可用于设计新的面向对象的应用程序和类库。设计模式的概念允许重用现有的设计结构和相关经验,从而支持开发人员设计面向对象的软件体系结构。设计模式是对众所周知的面向对象设计方法的重要且必要的补充。”

顺便提一句,这篇论文的作者叫做Erich Gamma。

Erich在以后的软件行业里可谓如雷贯耳,他的职业生涯也实属高光不断:IBM杰出工程师;“Eclipse之父”;JUnit框架作者;Visual Studio Code项目负责人……

可能连Erich自己也很难想到,自己几十年前做的一点微小的工作,竟逐渐演变为强大的编程理论武器,并持续不断地指导着一代又一代的程序员精进他们的编程技巧。

Erich在那篇论文中一共列举了包括组成(Composer)、包装(Wrapper)、桥接(Bridges)、代理人(Forwarder)、中介者(Mediator)、行为(Behaviours)、策略(Policies)等在内的不下九种设计模式。

这大概是软件行业里第一篇大规模且系统地将面向对象编程方法论以设计模式的形式展现给人们的技术文献了,但他当时似乎并未意识到自己所做的观察、抽象、描述工作与Alexander模式语言之间的联系,也并未意识到寥寥不足十种的设计模式会给软件行业带来震动。

诚然,彼时的设计模式还略显生涩而不成体系。想要改变软件行业,Erich还缺少一个契机。

巨擘的相会

在OOPSLA'92大会的一份关于《走向架构手册》(Towards an Architecture Handbook)的研讨会报告中,我们找到了早已埋好的伏笔。

在这份报告中,发起人Bruce Anderson介绍了这场始于OOPSLA'91的研讨会的背景及进展。当时,研讨会成员正致力于为软件架构师编写一本架构手册。

在他列举的一份立场文件清单中,Kent Beck(Patterns and Idioms: Proto-patterns for the Smalltalk Collection Classes)、Erich Gamma(The ET++ Look Subsystem)、Ralph Johnson(Constraints)、Richard Helm和John Vlissides(An Object-Oriented Architecture for Constraint-Based Graphical Editing)等人的文章赫然在列。

尔后,在OOPSLA'93大会上,Bruce Anderson又公布了已收录的模式清单[3],除了Erich Gamma的抽象工厂(Abstract Factory)、Richard Helm和John Vlissides的工厂方法(Factory Method)和装饰器(Decorator)以及Ralph Johnson的访问者(Visitor)之外,还收录了Java并发编程大师Doug Lea的前端/后端层次(Front-end/Back-end Hierarchies)以及Ward Cunningham的缓存数据库记录(Caching Database Records)等等。

不难发现,Bruce Anderson的这份模式清单,是一种更广义的软件模式,其中既有Erich Gamma这种面向对象程序设计的模式,也有Ward Cunningham这种针对通用软件架构设计的模式。

但正是这次肇始于OOPSLA'91的研讨会,让Erich Gamma陆续结识了Richard Helm、John Vlissides以及Ralph Johnson这三位编程专家,他们意识到,他们在编写可重用的面向对象软件背后的关键思想有着惊人的相似。

在那次会面之后,四个人加强了对设计模式的讨论,并不断受到Alexander的模式语言的启发。

在1993年7月的ECOOP'93(European Conference on Object-Oriented Programming)大会上,他们联名发表了题为《设计模式:面向对象设计的抽象与复用》(Design Patterns: Abstraction and Reuse of Object-Oriented Design)的摘要文章

在这份草稿形式的摘要中,被收录的设计模式已经丰富到23种。

一年后,Erich、Richard、John和Ralph出版了第一本关于设计模式的书,书名叫做《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Software)

《设计模式》赶上了OOPSLA'94大会的召开,仅在大会上便狂卖750本,比Addison-Wesley出版社在一次会议上售出的技术书籍最高销量的七倍还多[4]

因为这本书的作者有四个人,随后他们被业界戏称为“四人组”(Gangs of Four),他们所总结的设计模式,也被称为“GoF设计模式”,成为众多程序员顶礼膜拜的编程圣经。

《设计模式》一书,成功将模式概念推向更广泛的受众。

有趣的是,在软件这样一个飞速迭代的行业中,绝大多数技术书籍在二三十年之后都将面临过时淘汰的命运,但《设计模式》是个绝对的例外。这本书在出版将近三十年后仍在畅销,从未再版,这足以证明该书的权威与经典,真可谓一战封神。

生生不息

读到这里,人们往往心满意足地离开。

难得有这么一次,一个好的想法可以超越其原有的领域限制,并在另一个学科中得到长足的进步和发展。似乎,睿智的思想真的有放之四海而皆准般的纯粹。如果说,GoF设计模式在软件行业的发扬光大是一部堪比智人走出非洲的恢宏史诗,那么从这一刻开始,才应该真正擘画一幅由蛮荒步入文明的雄伟蓝图。

人们或许会问,模式语言在软件行业的演进就到此为止了吗?

严格来讲,GoF设计模式并非Alexander的模式语言在软件行业里的正统继承者。甚至可以说,GoF设计模式只是模式语言在软件行业里演化出的一个亲缘较远却广为人知的旁系分支。

GoF设计模式之于模式语言,就好像Windows之于操作系统。

GoF设计模式的发展虽则受到了模式语言的启发,但二者之间还是有很大差别的。就连四人组本身都在书中表示:“我们的工作在许多方面和Alexander的类似……不过我们的工作也在许多方面不同于Alexander的模式语言……设计模式仅仅是一个更大的软件模式语言的一部分”。

换句话说,在软件行业接过Alexander模式语言衣钵的,另有其人

所以,你真的以为Kent和Ward在1987年的那次先锋实验之后,便按甲休兵了吗?

1993年8月,也就是在四人组发表23种设计模式摘要差不多一个月之后,Kent Cunningham和Grady Booch(IBM软件工程首席科学家、统一建模语言UML创始人之一,还为四人组的《设计模式》撰写过序言)在科罗拉多州赞助了一次山地静修活动

当然,参加那次静修的还有Ward、Ralph、Coplien等一批模式语言拥趸。

在静修会上,模式爱好者们将自己的经验与Alexander的思想进行了激烈的交锋与碰撞,以求建立一种对象和模式的结合。

最后,他们达成了一致,成员们准备在四人组研究设计模式工作的基础之上再接再厉,以“生成”(generative)的方式继续探索模式的使用之道,就像Alexander在城市规划和建造建筑中使用模式的方法一样

Alexander曾解释说,生成模式是最有用的模式。“它们有力量。它们具有生成性。它们告诉我们该做什么[5](They have force. They are generative. They tell us what to do)

生成模式告诉人们如何创建一些东西,非生成模式则描述重复的现象。人们应该努力记录生成模式,因为它们不仅向我们展示了好系统的特征,还教会我们如何构建它们。

Alexander希望模式,尤其是模式语言,能够生成完整的、有生命的结构。

着迷于创造“活”的建筑的愿景,部分在于模仿生物进化和不断适应变化的独特能力。同样,在软件中,好的软件架构也应持续面对变化的挑战。因此,生成性的另一个方面是努力创建能够动态适应不断变化的“活”的架构。

这次静修活动,后来被认为是Hillside Group成立的标志。次年8月,大约80名模式爱好者齐聚伊利诺伊州蒙蒂塞洛的阿勒顿公园庄园,参加了由Ward和Ralph分别担任执行主席和会议主席的第一届PLoP(Pattern Languages of Programs)大会

此后,PLoP会议每年举办一届,逐渐成为模式作者和爱好者聚集、讨论和了解更多关于模式、设计、软件开发和构建世界的重要活动。

现在,PLoP会议的主题还扩展到讨论构建世界的各个方面——任何人为设计和制造的东西,包括组织、文化和个人实践。此外,除了模式和模式语言,PLoP会议还欢迎关于Alexander工作为主题的论文和随笔

至此,Alexander的模式理论思想,终于在软件行业得到了继承和发扬。

后记

在阅读这些软件行业先驱几十年前写就的文章和书籍时,笔者屡有驰思,不禁遐想:编程又何尝不是一件美好而纯粹的事情?

一代代的软件工程师在虚拟的赛博空间里,逢山开道,遇水架桥,字节为砖,逻辑为瓦,才建起今天雄伟的软件大厦。作为其中的一员,又岂敢乱涂乱画,信笔涂鸦?

Hillside Group曾认为,一些软件开发公司已经成为20世纪的血汗工厂:长时间、艰苦的工作,让程序员成为一端接受规范,另一端生成代码的机器。他们希望程序员能重拾尊严,因此,重视普通人的贡献,就像重视专家的贡献一样[6]

四人组曾悲观地写道:“实际上,我们认为永远也不会有一个完备的软件模式语言[7]”,“这可能是因为面向对象设计仍然是一项年轻的技术,我们可能没有足够的经验来提取涵盖设计过程中所有阶段的设计模式[8]”。

阅罢模式语言的发展历程,当知模式理论在软件行业的发展仍是方兴未艾。我们有理由相信,软件行业终将迎来属于自己的模式语言,但前提是,我们要崇尚设计,敬畏代码。

2005年11月24日,《设计模式》作者之一,John英年早逝,年仅44岁。

2022年3月17日,模式理论的开创者,Alexander去世,享年86岁。

如今斯人已去,唯愿思想长存!

参考资料:

[1]:克里斯托弗·亚历山大:建筑模式语言,全球知识雷锋

[2]:Patterns,Peter Coad和Mark Mayfield

[3]:Patterns: Building Blocks for Object-Oriented Architectures,Bruce Anderson

[4]:History Of Patterns,http://wiki.c2.com/?HistoryOfPatterns

[5]:Patterns and Software: Essential Concepts and Terminology,Brad Appleton

[6]:The Culture of Patterns,James Coplien

[7]:设计模式:可复用面向对象软件的基础,Erich Gamma,Richard Helm,Ralph Johnson和John Vlissides

[8]:Design Patterns: Abstraction and Reuse of Object-Oriented Design,Erich Gamma,Richard Helm,Ralph Johnson和John Vlissides

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值