演进领域驱动架构的着手点:
1 避免领域模型出现贫血模型
2 保证领域模型的纯粹性
避免贫血的领域模型
经典三层架构中
1 领域逻辑 在 业务逻辑层的service对象中
2 反映了领域概念的 领域对象 被定义为Java Bean 此 Java Bean未包含任何领域逻辑 被放在 数据访问层
3 DAO 对象仅负责与数据库的交互,并实现领域对象到数据表的 CRUD(增删改查)操作
面向对象的设计原则:
数据与行为应该封装在一起
贫血对象:
Java Bean 由于仅包含了访问私有字段的 get 和 set 方法。
贫血对象导致的问题:
不具备对象的丰富表达能力,当业务逻辑变得复杂时,在表达领域模型方面就会变得“力不从心”,无法有效应对重用与变化,且可能导致臃肿的“上帝类”。
贫血模型带来的问题在战术设计中深入解释
结论:
在面向对象设计背景下,当我们面对相对复杂的业务逻辑时,应避免设计出贫血模型
如何避免 贫血模型:
合理地将操作数据的行为分配给这些领域模型对象(Domain Model)
领域模型对象包含了领域逻辑,就需要从数据访问层转移到业务逻辑层。
DAOs 对象需要操作这些领域模型对象,使得处于数据访问层的 DAOs 对象 必须依赖 领域层的领域模型对象
避免贫血的领域模型,就不可能避免底层的数据访问层对业务逻辑层的依赖。
保证领域模型的纯粹性
加粗的两条依赖线可以清晰地看到领域层与基础设施层之间产生了“双向依赖”
两个层次的紧耦合
领域模型变得不再纯粹
根因:
高层直接依赖了低层,去掉右侧 Services 指向 DAOs 的依赖
实现逻辑是容易变化 抽象不易改变
解决:
改进设计的方式是对 DAOs 进行抽象,然后利用依赖注入对数据访问的实现逻辑进行注入
抽象层应该放在哪?
抽象的资源库接口代表了领域行为,应该放在领域层
实现资源库接口的数据库持久化,需要调用诸如 MyBatis 这样的第三方框架,属于技术实现,应该放在基础设施层
抽象的 Repositories 被搬迁至领域层,图中的领域层就不再依赖任何其他层次的组件或类,成为一个纯粹的领域模型。我们的演进正逐步迈向整洁架构!
用户展现层的变迁
前后端分离的架构思想,将用户展现层彻底分离出去,形成一个完全松耦合的前端层。
缺点:
基础设施层在这里出现了两次,但同时也充分说明了基础设施层的命名存在不足
架构也凸显了分层架构在表现力方面的缺陷。
引入应用层
领域驱动设计要求应用层“不包含业务逻辑”,但对外它却提供了一个一致的体现业务用例的接口。
取代 接口层(Controller 以及 Iface) 与封装了 Entity 与 Value Object 的 Aggregate、Services 以及抽象的 Repositories 接口协作。
基础设施层(controller Iface)的本质:
基础设施层要做的事情不正是封装对外部系统或资源的访问
对业务的支撑,提供了与业务逻辑无关的基础功能实现。