最近,分层在为 Coco 优化分层架构之时,架构我陷入了各种决策困难之中。演化引起所以我通过不断地延迟决策,从单插件以摸清更适合现有系统的化演化现状。换个简单来说,分层在危险边缘徘徊,架构以期待能获取最大的演化引起收益。 在设计新的从单插件架构时,我们总会凭借原先的化演化经验,并结合业务现状的分层需求,并根据未来的架构需求做出我们的设计。即: 种种因素的影响之下,它注定了我们无法设计一个满足所有历史时期的系统。未来会变成现在,现在会变成过去。 原先对于 Coca 的各种设计问题,云服务器提供商以及 Golang 对于多平台的支持问题等多方面的因素。迫使 Inherd 开源小组在 Coco 在初始阶段,便考虑了为 Coco 设计插件系统。直到最近,我们实现了插件系统之后,发现了原来设计的分层架构已经不满足现今的需求。 虽然,我已经知道新的分层架构应该如何设计,但是我并不想朝那个方向过去。我走走弯路,再看看是否存在一些更有意思的设计。 在设计初期,我在 Coco 中引入了类似于 Clean Architecture 的分层架构设计(不包含 Cargo 模块): 在 domain 目录下,根据了我们的四大基本业务,进行了二次划分 : 尽管,我一直在说我采用的是类似于 Clean Architecture 的分层架构。但是实际上,并没有采用其中一些重要的设计,比如说通过依赖反转来控制流向的问题。从个人的角度来看: 作为一个单体应用,这个分层结构凑合着: 故事的开始还是蛮美好的。 为了在多个不同的系统/应用之间(即 Coco 项目的代码提供给其它应用)复用代码 ,系统中产出一些独立的模块,如 psa、framework 等等。这也是一个非常常见的模块化的场景。模块化在不同的语言里都有一定的相似之处。 譬如:在使用方式上存在本地使用和远程发布两种模式。在本地使用时,无需关注语义化版本等一系列的事项,只需关注于代码本身。一旦时机成熟,也就可以进化为可远程发布的模块。 从单体中出现模块化的一种典型形式便是,在代码库中以与源码同级的目录呈现。如下: 这里的 framework 和 psa 便是独立的模块,一旦其与其它模块的依赖关系解耦开来,那么它就可以作为独立的应用发布。 复制 over 复用 顺便提一句,对于模块化的代码复用来说,如果代码量较少,那么可以尝试复制一份代码,而不是复用做代码。这样一来,我们可以通过此来解耦依赖。 同时,为了灵活地扩展系统的功能,我们设计了插件系统。(事实上,更多地从意图上,我们只是为了减少包体积大小,这样可以方便地从 GitHub 下载) 于是乎,我们创建了独立的 plugins 目录,并在其中创建了对应的模块,如下的 coco_xxxx 即是插件。同时,我们使用了 plugin_manager 来作为插件的管理器(事实上,后面证明了,这个 manager 不应该独立作为一个模块存在): 从设计和演进的角度来看,问题并不多,也可以使用。 好了,由于经验上的不足,我们就面临了之前没考虑到的问题。 从设计思路上来看,我们本应该在原先的架构模型中,提供一个 core 模块。而在这个 core 模块里呢,则用于提供一些核心的代码给插件和应用。 所以,很快地我们就创建了一个 core_model 出来了。我的本义也就只是提供一个核心模型。我不想像一些插件化项目中,在 core 中提供大量非核心的代码。 只是呢,随着第一个模型复用需求的出现,很快地就有了第二部分、第三部分。 而插件之间除了模型的复用,还会有基础设施的复用。而这些代码,我又不想放到 core 里,所以就又需要抽取中一个 infra 的模块,用来共享基础设施的代码。那么问题来了,我们应该如何选择? 从架构设计的思想来看,我是支持双层基础设施的存在。过多的无意识地复制这些公共代码,会导致这个包大小的进一步膨胀。一个典型的例子,就是我们在一个被称为 common 包的 jar 包里,看到一个 common 子包下,还有 common 目录的存在,即 xxx-common.common.common。 故事就到这里了。哪怕一个再小的项目,它的架构模式也会随着系统的开发,不断地演化。如果不加以控制,那么系统可能会推动控制。而演进本身呢,也不会是一帆风顺的。 不过,我在思考一个新的东西,关于『分层架构适应度函数』。 无论是在 Coco 还是在 Coca 里,我们都在尝试对系统的分层进行一个评级。而这个评级的其中一个依据是通过依赖关系,来确认各个模块之间的引用关系,从而判断系统的分层架构是否是符合需求的。 通过解析模块之间的引用关系,可以帮效地帮助我们厘清系统模块之间的合理度。 本文转载自微信公众号「phodal」,可以通过以下二维码关注。转载本文请联系phodal公众号。Coco 架构设计:从过去到过去的未来
原始形态:单体架构
复用形态之模块化
插件化的架构演变
演进:未来的未来
提取核心模型
再次抉择:基础设施层的改造
小结:架构的持续演化
Yiki:分层架构适应度函数