Blog

Blog

PHODAL

模式的模式:从设计模式到元模式

最近的一两个月里,我一直在研究各类的模式:设计模式、架构模式、容器模式,以及其它一些特定领域的模式(如并行计算模式)等等。

经历了一番买书、读论文、读代码,我发现了以前对于模式的理解不够深刻。也因此呢,这篇文章就是用来记录一些缺乏的东西,诸如于模式语言、模式的模式等。

PS:为了方便阅读,本文的书名使用都是简写模式,全称在最后的相关资料中。

模式重谈

为了避免出现类似于 Datum 是最好的语言这一类的问题,在那之前,我得先阐述一下对于模式的看法:

  • 模式是对于惯用方式的总结,不限于编程,有相当多的人习惯了使用各种设计模式,但是他并不知道这是何种模式。它是一个概念字表,用于快速沟通。
  • 模式是解决方案,满足锤子定律,只有遇到特定的问题时,你才会需要它。
  • 模式是适用于特定场景的,大部分的模式对于当前所处的系统是无用的,往往只有少数的模式是适合的。
  • 模式是知识体系的展现,掌握模式的多少,更多的说明见多识广,并不一定代表真实的代码水平和能力。
  • 模式需要刻意练习,学习模式是一个漫长的过程,所以总会遇到理解解决、使用错误的情况,不要担心。
  • 模式种类繁多,计算机行业普遍认同的是:模式的起源是亚历山大的《建筑的永恒之道》。在更早的时间里,也还有对应的总结,但是这里是最体系化的技巧。

除了设计模式之外,我们所处的行业还有大量的其它模式:

  • 容器设计模式。应对于云原生应用下一系列复杂的分式场景,Google 的工程师发表了相关的论文对此进行总结,常见的有 Sidecar、Adapter、Ambassador 等。
  • 架构模式。架构模式是在给定上下文中解决软件架构中常见问题的通用,可重用的解决方案。除此,一些常见的架构风格,如微服务、事件驱动架构等,从大类上来说也被归纳到架构模式中。
  • ……

所以,你会发现这些模式只是人们对于惯用法的总结。

寻找模式

回过头来看,当我们会发现进入一个新的领域,进行相关领域的架构设计之时,我们会不断搜寻各类的资料,而后再去贴合到设计中去。实际上呢,我们是在寻找该领域的模式,有了这些模式,便可以照猫画虎的设计一个系统,而不会出现太大的问题。

运气好的情况下,我们甚至于能比在这个领域的大多数人做得更好 —— 因为我们所掌握的是解决这一类问题的模式。

这时,我们已经有一个很有优势性的套路,以帮助我们更好地进入新的领域。但是呢,作为一个新的领域的初来者,往往不知道到底应该采用哪一种模式,也不确定模式之间存在何种关系。

相关书籍:《设计模式》

模式归类:目录、集合、仓库

在一个软件系统中,模式很少独立存在,往往是多个模式相互组合,用于解决特定的问题。而其中的一种组织方式的模式就是模式集合。随后,根据不同的需求,再对进行分门别类。如《POSA 5》所介绍的几种方式:

  • 即时(ad hoc)组织。
  • 根据层次划分:根据抽象、粒度和规模的层次划分。
  • 根据领域组织:电信、金融、电子商务等。
  • 根据分区组织:归属于架构的哪一部分。如层、阶层(tier)、组件和包都是分区的例子
  • 根据意图组织:如 POSA、GoF 的 23 种设计模式、DDD
  • ……

接着,让我们来看几个分类示例。

设计模式的组织

在《设计模式》一书中,引入的概念是『设计模式空间』,在这里它们被分为了三大类:

  • 创建型模式:单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
  • 结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
  • 行为型模式:模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式

其划分的两条准分别是: 目的准则,用来完成什么工作;范围准则,指定的模式是用于类还是用于对象。

DDD 的组织

《领域驱动设计》一书其中也是一本模式合集,这就是为什么这本书不易于读懂的原因之一。另外一个原因则是,翻译这本书的人没有理解好什么是统一语言

在 《领域驱动设计》 一书以多种形式组织了模式,依次的四个部分是(PS:个人临时总结):

  1. 运用领域模型 —— 『模型知识提取的模式』
  2. 模型驱动设计的构造块 —— 『模型设计的模式』
  3. 通过重构来加深理解 —— 『模型优化的模式』
  4. 战略设计 —— 『模型边界划分的模式』

而这个顺序其实也是我们在实施 DDD 过程中的设计过程,而后再进行层次化的组织,如『战略设计』部分根据不同的意图,又分为不同的合集:

  1. 保持模型的完整性,如限界上下文、上下文地图等
  2. 精炼:核心域、通用域等
  3. 大型结构:演化秩序(Evolving Order)、系统隐喻等

所以从结构上来看,《领域驱动设计》是一本由小而大的书,阅读难度略大,需要一定的经验。

模式分类的意图

我们把『如何应用设计模式看作是一个问题域』,那么模式分类就是在这个问题域里的一种解决方案。

在计算机的不同的复杂领域里,如并行编程、架构设计等等,它们本身是包含了大量的模式。而有了对于这些模式的进一步分类,对于我们应用模式会有更大的帮助 —— 至少在应对同一个次级问题时,我们可以寻找可能的替代模式。

不过呢,多数时候,我们往往不知道的是:我们遇到的问题是什么?

角落里的模式语言

如 《POSA 5》所定义的一样:模式语言与具体领域高度相关,并且能对这一类系统提供具体而周全的引导,具体包括以下几项:

  • 要解决的主要问题有哪些?
  • 这些问题应该以什么样的先后次序解决?
  • 解决一个给定问题,有什么可用的替代解决方案?
  • 怎样处理问题之间的依赖性?
  • 在有“周边” 问题存在的情况下,怎样最有效地解决单个问题?

简单来说,模式语言针对于某个特定的问题(如并行编程)所抽象的模式,并包含了他们之间的关系等,能用于系统性地解决这一类问题。

书中还提到 了 Gerard Meszaros 的观点“模式语言可以用来指导生手创建系统”。Aha,这不就是我们想要的东西吗?作为一个进入新领域的新人,我们需要这么一个模式语言。尽管模式语言可以帮助我们解决这一类的问题,但是它也意味着它自身需要:充分覆盖进展可持续紧密集成。依照这一系列的前提,它意味着设计这个模式语言的人应该是业内专家,并且模式本身应该是不断演进的。

因此,当我们把如何实施和使用模式看作是我们的问题时,那么模式语言解决这一类问题的模式。

分布式计算的模式语言

《POSA》系列大概是在中文世界 里,我们所能找到的最好的资料。因此,这里再次以《POSA 4》作为例子,《POSA 4》全称是《面向模式的软件架构:分布式计算的模式语言》。

先来看图(图中的圈内表示的是问题域,连续表示的是他们的关系,每个问题域下包含了相关的模式):

POSA Pattern Language 举例来说开头的『From Mud to Structure』(从混沌到结构)就是一个大的问题域,对应于这个问题域则包含了一系列的模式,如:MVC、分层、PAC、微内核等。同时,针对于这个问题题来说,如果我们还要数据库访问,那么我们从数据库访问中获得对应的模式,以此来完善我们的设计。

然后,在我们进入了具体的模式/问题域之后,它还详细介绍了如何实现对应的模式。如分层:

POSA Layer

有了这系列的配合,我们便可以完善整个系统的设计。

微服务的模式语言

接着,让我们来看看《微服务架构设计模式》中关于微服务的架构模式概述:

微服务模式语言

从上图中,我们可以看到由 Chris Richardson 整理的这个微服务模式语言,对语言进行了多层的分类,并指明了它们之间的关系。颇为遗憾的是这个模式语言只包含了关系,缺少了一些相关关系的描述。

虽然如此,但是从总体上来说,它还是能在一定程度上帮助我们设计微服务。

相关书籍:《POSA 4》、《POSA 5》、《微服务架构设计模式》

模式的模式

从模式再模式归类,再到模式语言,我们已经有了整套的方案。最后,我们就剩下一些有意思的问题,诸如于如何发现新的模式?如何对现有的模式进行一些抽象。

对于『模式的模式』的理解,有助于我们更好地理解好设计模式。对于设计模式的理解之后,只需要理解其背后的模式,就不需要再去熟记每个设计模式。

所以,我们就来到了元素模式,依据的它也是来自于一本书《元素模式》。

元素模式:设计模式的模式

模式是来源于对惯用法的总结,而诸如于元素模式则是对于设计模式的提取,即模式中的模式。元素模式(Elemental Design Patterns)的核心要义是一组面向对象的基本概念。

对 OO 中的设计模式进行更细致的拆分,我们就能得到位于其背后的模式。作为其中的核心元素模式便是:创建对象、检索、继承和抽象接口。于是,如书上所说,结合这四个 EDP,我们可以创建对,并实施特定的保证,在运行时建立自此的关联,并从一种类型出发建立其他类型,以及创建出声明,并带有关于未来的、未定的类型的保证。

而我们在实施方法调用时,也被抽象了四个 EDP:递归、委托、重定向和集聚,以此构成了设计的砌块。

架构模式的模式

最后就回到了我想抽象的问题,那么架构模式其背后的模式又有什么呢?我试着进行了简单的拆解:

  • 契约。输入与输出、API 等。
  • 分割。隔离变化、明确职责等。
  • 约束。功能需求和非功能需求、性能等。
  • 封装。接口封装。
  • 协作。协作风格等
  • ……

当然了,我还需要他们进行重新命名,以构建在架构模式领域的统一语言。

其它

尽管,它有些复杂,但是依据很有意思。

相关资料

  • 《元素模式》
  • 《设计模式》 -> 《设计模式:可复用面向对象软件的基础》
  • 《POSA 4》 -> 《面向模式的软件架构,卷 4:分布式计算的模式语言》
  • 《POSA 5》 -> 《面向模式的软件架构,卷 5:模式与模式语言》
  • 《领域驱动设计》 -> 《领域驱动设计:软件核心复杂性应对之道》

或许您还需要下面的文章:

关于我

Github: @phodal     微博:@phodal     知乎:@phodal    

微信公众号(Phodal)

围观我的Github Idea墙, 也许,你会遇到心仪的项目

QQ技术交流群: 321689806
comment

Feeds

RSS / Atom

最近文章

关于作者

Phodal Huang

Developer, Consultant, Writer, Designer

ThoughtWorks 高级咨询师

工程师 / 咨询师 / 作家 / 设计学徒

开源深度爱好者

出版有《前端架构:从入门到微前端》、《自己动手设计物联网》、《全栈应用开发:精益实践》

联系我: h@phodal.com

微信公众号: 与我沟通

标签

最近的一些事

  • 最近我和我的同事们,一起在创建一个新的编程语言:Charj 。它是一个使用 Rust 编写的描述式、中间编程语言。GitHub: https://github.com/datum-lang/datum

    Nov. 14, 2020, 9:27 p.m. | China