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