GoFrameGoFrame
一、什么是模块
Golangpackage

软件进行模块化设计的目的,是为了使得软件功能逻辑尽可能的解耦复用,终极目标也是为了保证软件开发维护的效率和质量。

三、模块复用原则
REP
Release/Reuse Equivalency Principle

直白地说,就是要复用一段代码就把它抽成模块。

CCP
Common Closure Principle

对大部分应用程序而言,可维护性的重要性远远大于可复用性,由同一个原因引起的代码修改,最好在同一个模块中,如果分散在多个模块中,那么开发、提交、部署的成本都会上升。

CRP
Common Reuse Principle

相信你一定有这种经历,集成了模块A,但模块A依赖了模块B、C。即使模块B、C 你完全用不到,也不得不集成进来。这是因为你只用到了模块A的部分能力,模块A中额外的能力带来了额外的依赖。如果遵循共同复用原则,你需要把A拆分,只保留你要用的部分。

复用原则竞争关系

REPCCPCRPREPCCPCRPREPCCPCRPREPCRPCCPn

图2. 模块复用原则竞争关系张力图

CCPREP
四、框架模块设计

经过前面关于模块设计原则和复用原则的介绍,我们应该对模块开发和管理这块的原则有了大概的了解,那么我们接着介绍框架的模块化设计就比较容易理解了。

单仓库包设计

REPGolangCRP


示例中的模块依赖,都是一些通用模块,大部分业务项目都会涉及到。模块地址是便于演示而写的随意地址,并不一定真实存在。

GolangGolang
  • 实现相同功能逻辑的模块较多,选择成本增加

  • 项目依赖的模块过多,项目整体的稳定性会受到影响

  • 项目依赖的模块过多,项目无从下手是否应当升级这些模块版本

  • 模块分散设计,不成体系,难以统一。具体请参考章节:统一框架设计

现身说法举例。

bug fixbug
bug
Golangbug

好的软件设计,并不是一成不变,而是能够做到快速响应变化,根据变化快速改进完善。模块的设计和管理,亦是如此。寻求能够快速改进模块逻辑、有效维护模块依赖的方案,比编写更加稳定的功能模块,更加高效和务实。

模块聚合设计

GoFrameCCPGoFrame
GoFrame
GoFrameREPCRP
  • 框架核心维护较全面的通用基础模块,降低基础模块选择成本

  • 我们只需要维护一个统一的框架版本,而不是数十个模块版本

  • 我们只需要了解一个框架的内容变化,而不是数十个模块的内容变化

  • 升级的时候只需要升级一个框架版本,而不是数十个模块版本的升级

  • 减轻开发人员的心智负担,提高模块可维护性,更容易保证各业务项目的模块版本一致性

五、常见问题解答

1、虽然每一个模块都按照低耦合设计,模块可以选择性引入,但在使用时也得全量下载完整框架代码

文件层面的源文件下载与模块之间的逻辑耦合没有直接关系。需要注意的是,编译型语言解释型语言的模块管理逻辑不太一样。

main

2、框架中任一模块的版本变更都会引起框架版本的发布,框架的发布频次是否会变高

CCP
hot fix

3、框架聚合并维护通用性的核心模块,通用性的核心模块定义是什么

首先,它们是基础模块,往往位于模块依赖链的最底层,这部分的模块变化对项目稳定性影响最大。

其次,绝大部分项目(二八定律来讲为80%以上)都会依赖的通用性基础模块,可以称作核心模块。

最后,这部分模块不包含具体业务的封装实现。例如:微信公众号/小程序、CMS/CRM、区块链等相关模块都是具体业务实现封装。


关于模块通用性的评估无法完全准确,框架为保证核心精简会尽可能持保守态度,并且会根据实际情况在未来的迭代中逐步做调整。

以下为可供参考的模块分层:

模块分层参考

业务实现模块:特定业务项目逻辑实现,这里包含业务项目进一步的代码分层。

通用业务模块:可复用的业务逻辑封装,例如微信公众号/小程序、CMS/CRM、区块链等相关业务逻辑封装模块。

通用基础模块:标准库不提供或者基于标准库封装扩展的基础模块,例如:配置、校验、缓存、ORM、I18N等等。

标准基础模块:Golang标准库。

4、框架中包含的模块多,我觉得每个模块的性能往往就不会高

哈哈。