在架构设计中,我们会有一些难啃的骨头。其中最为典型的,就是全局性功能

全局性功能特征:

很难被独立分成模块

读盘 / 存盘功能

Office 软件作为例子

  • 读盘 / 存盘:每增加一个功能,都需要考虑这个功能的数据如何存储到磁盘,如何从磁盘中恢复。
  • Undo/Redo:每增加一个功能,都需要考虑这个功能如何回滚 / 重做,很难剥离。
  • 宏录制:每增加一个功能,都需要考虑这个功能执行的结果如何用 API 表达,并且得支持将界面操作翻译成 API 语句。

需求交织在一起,全局性功能往往难以彻底进行正交分解。但对于架构师来说,难不代表应该轻易就放弃对正交分解的追求。

引入 IO DOM 来进行正交分解
关键点:

  1. “读盘 / 存盘” 本身需求是发散的,因为要支持的文档格式只会越来越多。所以我们必须把它独立成一个子系统,比如叫它 IO 子系统。
  2. 要独立子系统,就需要抽象出它对核心系统的稳定依赖.为什么这个稳定依赖最后设计为 IO DOM,是因为 DOM 是核心系统的常规界面

因为读盘存盘是全局功能,我们没法消除这种全局性,但是可以尽可能削弱到最低。
因为 IO DOM 名称上虽然带了 IO,但是它只是一个归类,实际上这些接口都是核心系统的常规接口,并非为 IO 子系统定制。这样一来,读盘与存盘带来的全局性影响就近乎被消除

IO DOM 则是反其道而行之,通过抽象核心系统的接口,让全局性功能反向依赖这些接口来完成。这不容易,但是这样做核心系统受到的伤害值最低。

Undo/Redo 功能

在设计模式中有一个模式叫 Command 模式,专门用于解决 Undo/Redo 这个功能场景的。它的基本思路是,每个用户操作都实现为一个 Command,每个 Command 需要实现反操作,以便做到 Undo 的能力

但实际上框架只节省了 1% 的工作量。其余 99% 的工作量在实现一个个 Command 身上,框架使用方的心智负担不是一点点的大。

快速存盘

存盘的时候并不是把完整的文档写到磁盘文件中,而是将上一次存盘到这一次存盘的增量部分,追加到文档的尾部。这样一个 Word 文件就有多个版本的文档,每次读盘的时候只需要读出一个最新版本即可。

要想避免系统无法响应用户编辑的另一个思路是异步存盘

只要支持了多版本,就有了镜像能力,也有了Undo/Redo 能力。

数据层(DataLayer)

可以把它类比为服务端的数据库。它是一个存储中间件,负责托管所有的数据

随着今天软件服务化(SaaS)大行其道,基于某种存储中间件来写业务逻辑,越来越多人意识到它已经是一种必然的趋势。

宏录制功能

什么是宏(Macro)?

所谓宏(Macro),是指二次开发的代码。微软几乎所有的产品都有二次开发接口,也就是 API 层,典型代表是 OfficeVisual Studio

有了二次开发接口,就可以有生态,有围绕着 Office 和 Visual Studio 的生态厂商,来争强产品的能力,也可以让 Office 和 Visual Studio 更容易地融入到企业的业务流中。可以说,支持宏是微软做得最牛的地方。

什么是 “宏录制”?

就是把用户的界面操作用 API 调用的方式记录下来,把它变成一段二次开发代码。

好处:

  1. 被录制下来的 “宏”,可以被反复重放,如果某件事情经常发生,它就可以改善我们的工作效率。
  2. 被录制下来的 “宏”,可以进行修改迭代,进行功能的增强。这有助于二次开发的新手学习 OfficeVisual StudioAPI 接口,大幅降低二次开发的入门难度

怎么支持 “宏录制”?

宏录制也像日志一样,会去记录一段文本。我们想象一下,如果我们的 Model 层 DOM API 也基于 RESTful API 接口,那么我们就可以在 API 入口的地方去实现 “宏录制”。
“宏录制” 需要考虑 API 嵌套,我们实现某个 API 可能会调用另外某个 API,但是录制的时候,肯定只能录最外层的 API,而不是所有 API 调用都被录制下来。

架构师的信仰

任何功能都是可以正交分解的,即使我目前还没有找到方法,那也是因为我还没有透彻理解需求

怎么做业务分解?

核心系统一定要最小化,要稳定。坚持不要往核心系统中增加新功能,这样你的业务架构就不可能有臭味。

记住最重要的一点:

保持核心系统的纯洁性比什么都重要

标签: 架构, 模块, 系统, 核心, 功能, dom, 子系统, api, 分解

知识共享许可协议
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。

发送一条友善的评论

  • 目录