一个系统的架构是它的高层级的视图,是系统的大局观,是粗线条的系统设计。架构的决策就是系统结构上的决策,这些决策影响着全部代码,决定了系统中其它部分的基础。
除了其它用处以外,架构决定了系统的:
组件
组件之间的关系
指导对组件以及及其之间关系进行设计和演进的原则
换句话说,这些设计决策在系统演进的过程中更难改变,它们是支撑特性开发的基础。
意大利面架构
我参与的有些项目结构完全是随意的,又不能体现架构也不能反映领域。如果我的问题是“这个值对象应该放在哪里?”,答案就是“随便放在 src 目录里就好了”。如果我的问题是“完成这个逻辑的服务在哪里”,答案是“用 IDE 搜索吧”。这意味着完全没有思考该如何组织代码。
这里的隐患很大,因为完全没有使用包来实现模块化,高级别的代码关系和流向完全不遵守任何逻辑结构,将导致高耦合低内聚的模块,实际上可能根本就没有模块划分,本来应该属于某个模块的代码散落在整个代码库中。这样的代码库就是所谓的意大利面代码,或者是意大利面架构!
可维护的代码库
拥有可维护的代码库意味着我们能以最小的代码修改获得最大的概念变化。换句话说,如果我们需要修改一个代码单元,其它代码单元的修改应该尽可能地少。
这带来了明显的优势:
因为影响的代码少,修改会更容易;
因为影响的代码少,修改会更快;
因为修改的代码少,出现问题的几率会降低;
封装 、低耦合和高内聚是保持代码隔离的核心原则,使可维护的代码库成为可能。
封装
封装是隐藏一个类的内部表示和实现的过程。
也就是说,实现被隐藏了,这样类的内部结构可以随意的改变,而不会影响使用这个类的其它类的实现。
低耦合
耦合涉及代码单元之间的关系。如果一个模块的修改会导致另一个模块的修改,我们就说这两个模块高度耦合。如果一个模块可以独立于其它任何模块,我们就说它是松耦合的。通过提供稳定的接口来有效地对其它模块隐藏实现,可以达成松耦合的目标。
低耦合的优点
可维护性 – 修改被限制在一个模块中
可测试性 – 单元测试涉及的模块尽可能地少
可读性 – 需要仔细分析的类尽可能地少