原文:Reclaiming Design Patterns (20 Years Later)
嫌太长就看这段:
20年前,“Gang of Four”出版了设计模式的书。用了当时的主流语言(C++ 和 Smalltalk),当时的设计思想(比如强调继承),尽管如此它仍然在业内引发了巨大的“运动”。然而,正如我们所知的历史规律,这也是它要灭亡的标志:所有在行业内成为“运动”的最终都会破灭。当它不能兑现它言过其实的承诺(实际上从来也没有做到)就会成为众矢之的。现在是时候让我们回去用新的眼光重新审视23种设计模式,让它和已经经过20年成长的语言对比,看看有什么变化(剧透:初始的23种模式都很不错,而且里面有很多细微之处在我们第一次接触的时候我们忽略了)。
模式:到底是什么?
在早期模式“运动”中,当时模式还是一个新概念,我们没有花什么时间去真正的讨论它。他们就是出现了。我们读着设计模式的书频频点头,感觉就像是之前一直处在代码世界的荒山野岭里,然后我们一如往常的写着代码。接着我们觉得可以在一些地方可以用上设计模式,就像是世界打开了一扇新的大门。我们感觉。。真是Cool。
Gof似乎在一开始也觉得这是一门微妙的(subtle)艺术/科学。在书的最后一章(不幸的是基本没人读到这里),他们说到:
也许有人会觉得这本书没什么了不起。毕竟它没有展现任何一种新的算法或者编程技术。它没有为设计系统给出一套严格的方法,也没有发明一种新的设计理论--它只是记录了一些已经存在的设计。你可以总结说它是不错的教程,也行,但是它显然不能为一个有着成熟面向对象经验的设计者提供太多东西。而且事实上:它就是没什么大不了。一个我认识的朋友说:设计模式:“使用指针的23种方式”。这也没什么大不了的。
同样的,如果一个经理/高级团队leader/架构师给一个新手丢过去这本书,希望他们在读完这本书之后突然“升级”,他们会大失所望。
好处,似乎就更小了:
我们希望你用不同的方式思考。一份设计模式的目录是重要的。它让我们使用的一些技术有了通用的名字。如果我们不学习软件里的设计模式,我们就不能改进它们,如果出现新的模式我们解决起来就会更难。
显然,设计模式催生了一场运动,并且模式运动诞生在原始的23中GOF设计模式上。但是,事情慢慢变得更抽象并且高端了。模式变成了“模式语言”,然后变成了“元-模式”(meta-patterns)。接着人们开始记录它的负面影响,称作“反模式”(anti-patterns)。
当人们察觉到这可以赚钱,于是相关的书就开始烂大街。
很多出版社开始出版“模式”概念的书,但是离GOF最初的模型相差甚远。模式的书成为“可复用的代码”的同义词(不再是“reusable elements of design”)。IDE产商开始寻找方式集成模式:以代码生成器的方式。不知为什么模式也成为了UML和其他设计的注解,某个目标是在UML想出怎样创建出与之对应模式的可复用的设计模板(the goal at one point was to figure out how to create reusable design templates in UML that corresponded to patterns.)。
就像上面提到这些事,模式开始变得流行并且吸引那些不知道模式是什么的人。他们怎么可能满足这些人的期望呢?
在2000年左右,模式开始成为一个不好的词,发言人开始大范围“清理”模式,说模式是人造的“烂语言”、“原始的思考方式”,应该“归入好的语言”。(an artifact of “bad languages” and “primitive thnking” and “subsumed into good languages”.)
模式显然是没用的。
可是...他们依然持续出现。我们一直使用他们的术语(terms and lingo)。为什么?GOF把它称作回到1995(在书后面的同一章):
“设计模式为设计者提供了一套通用的词汇表来交流,记录文档或者探索设计。设计模式用一个更高的抽象创造了一个更简单系统相比用编程语言描述一个设计思路。设计模式提高了你的设计和同事讨论设计的高度。”(p389)
还有:
“理解这本书里的设计模式可以让你更容易的理解现有的系统。学习面向对象编程的人常抱怨他们使用了继承的系统在流的控制上难以理解。很大的原因是因为他们没有理解系统里的设计模式。学习这些设计模式可以帮助你理解现有的面向对象系统。”(p389)
还有:
“设计模式提供了一种能更多的说明“为什么”这么设计而不只是记录你决定的结果。一个设计模式的Applicability, Consequences, 和Implementation帮助指导你应该做出什么样的选择。”
还有:
“开发可复用软件的一个问题是它常需要重新组织或者重构。设计模式帮助你决定怎么重新组织设计,可以减少今后你需要重构的次数。”
(是的。在重构流行很久以前他们就在讨论重构了。)
最重要的是,他们准确的预言了模式会作为一个整体衰败的原因:
“最简单的对待模式就是把它当做一种解决方案,作为一项可以被适用、重用的技术。难的是发现它什么时候合适--最佳的解决面对的问题和所处的上下文的方案。通常看出某个人做了什么比为什么这么做容易,为什么这么做对于一个模式就是它要解决的问题。知道一个模式的目的也非常重要,因为它是我们选择这个模式的原因。它也帮助我们理解这个系统的设计。一个模式的作者必须查明和刻画出这个模式解决的问题,即使在你已经发现了这个解决方案后。” (p393)
太多短视的人看到了“解决方案”,他们急着发现可以重用的代码,他们忘记了去思考“为什么”,结果就是他们会犯下一些非常愚蠢的错误。
一个模式是什么?
关于这点的讨论已经有很多年了,但是我会用下面这句话终结这个问题:
一个模式是一个解决方案:一个在特定上下文里并且有着可预见的影响变化的问题的解决方案。(A pattern is a solution to a problem within a certain context that has a set of predictable consequences.)
就这么多。没有什么神奇的、神秘的或者非常学院派的描述。如果你能描述这四个部分(问题、上下文、可预见的影响变化、解决方案),你就有了一个模式。把它写下来,然后发表到某个地方。当我们遇见一些相似的问题,我们可以开始找出其中的共性,然后取一个好听的名字,然后它就可以加入“词汇表”了。
GOF发布了其中的23个。在这此外存在着更多的模式。大部分都非常有用。尤其是最初的23个,因为它从一大堆不同的语言里提炼出来(之后出现的很多模式和某种特定语言绑定在一起)。
为什么我们再次讨论?
上一句,引出了另外一个重要的地方:太多的模式社区花了太多时间争论它们,给出的这个是不是一个模式,或者某段代码是这个模式还是那个模式,或者...
可以从三点考虑这些问题:
围绕一个模式的构成的辩论对于模式所提供的好处是重要的。这就是为什么模式的社区总是说“除非被发现了三次它才是一个模式”或者“一个模式除非在模式会议上研讨过否则就不是一个真正的模式”。这样做不是为了增加神秘感,或者让社区里的人能够知道。这样的目的是为了通过在思维上的辩论提炼这个模式的本质,保证它的高品质。 一旦人们开始说“Pfffft”已经避免了这些受争议的步骤,就会突然间什么都成为了一个模式。如果突然我们开始管本地变量叫做一个模式,我们所有的关于设计高度抽象的工具箱和术语就失去了意义。如果任何人都可以称任何东西是一个“模式”,那么我们就会这么做,在交谈中模式就失去了它原本的语义。如果模式只是在本地团队里产生的,那就无法和团队外的人交流它。科学需要严谨,这就是模式社区希望带来的东西。
这个地方使用的是什么模式就是一场哲学的辩论。很多人会沉溺在和其他团队成员讨论某些代码是什么模式。我都想不出更无聊的活动了,除非这个讨论能在这个模式上引出新的洞见。在这个问题上讨论会消耗很多人与人之间的善意。
一个好的设计不需要全是模式。 你可以有一个好的设计而不是任何一个已知的模式。
是时候把它们拿回来了
20过去了,我觉得是时候了重新开始讨论了。我不会想象通过我自己重建整个运动,但是至少,我可以这些老东西的灰尘擦干净,希望把它带进21世纪里我们使用的语言。
作者最后大概说会重新把最初的23种模式整理成适合现代语言的样子。也就是第一段中提到和经过20年发展里的语言的对比。
欢迎关注我的微博:@没故事的卓同学