首先要明白组件的概念,组件是“在一个执行环境(应用程序)中的,一个干净、良好的接口背后的一系列相关功能的集合”,也就意味着组件不是一个物理的部署物,而是一系列逻辑的相关class。
根据“C4软件架构模型”,系统的静态结构有容器、组件和类。一个系统由多个容器组成(例如Web应用、移动App、数据库、文件系统),每个容器包含若干个组件,每个组件包含若干个类。一个组件可以出现在多个容器中。
按功能封装组件,组件就是一个领域的所有类的结合,只对外暴露简单的接口,隐藏实现细节,内部依然遵守高层组件与低层组件的依赖关系。如果按照这种方式划分组建了,很多问题都会迎刃而解。
1)一个应用如何拆分项目?
每个业务域抽象为一个逻辑组件,但所有业务域的代码可以放到一个项目里,也可以拆成不同的项目。这个取决于团队吧,如果不同的业务由不同的开发团队来发,那就拆开,否则就没必要拆。拆开以后的组件如何被其它组件使用呢?可以通过引用lib的方式,也可以通过微服务的方式,微服务的方式需要增加容器。
每个容器单独作为一个组件,拆分为独立项目。主要原因是容器依赖某个具体的框架,还要独立部署。
2)需要约束哪些行为? 约束对外暴露的内容。包不仅是组织代码的地方,还是封装的主要手段。尽量不要对外暴露具体的实现类,通过对外暴露构造函数(go语言的方式)或某种静态方法,用来在包外创建实例。我之前写的java类基本上都是public,这个是错误的。
约束包内部的代码行为,践行软件设计的SOLID原则。包内部无法借助编译器的支持,只能靠编码规范来约束。
3)架构的核心目标是什么? 我认为架构的核心目标是为了更好地支持系统用例,更好地实现业务流程。所以一个架构设计方案看上去必须是面向业务的,而不是面向框架的。优秀的架构不是无限接近技术上的完美,而是无限地适配业务场景。
如果一个人跟你说它的某某系统的主要架构是SpringCloud,你可以这个系统认为没有架构。
应用场景
1 如何使web controller无法直接访问数据层?
web controller是低层模块,数据层也是低层模块,低层模块依赖低层模块,适应变化的能力会很弱,所以要让他们都依赖高层模块。但如何强制实现呢?
如果按照上面提到的方式,web controller 属于web容器组建,数据层被封装在了功能组件内部,因为它与接口无关,所以不对外暴露,所以web容器组建根本就访问不到。