领域驱动设计与框架——框架的支持与框架依赖的矛盾

领域驱动设计的核心是领域模型,领域模型处于软件架构的中心位置,使用接口隔离持久化等技术的具体实现,从而达到将业务复杂性与技术复杂性分离的目的。理想状态下领域模型是POJO(或者.Net下的POCO),不依赖于具体的框架。然而,实际情况是,如果没有合适的框架支持,将领域模型进行持久化在实际项目中几乎是不可能完成的任务:我们不可能在应付用户需求的同时进行复杂软件框架的研究和实现。实际项目中需要选择成熟、可靠、易于学习的技术框架在有限的时间和预算范围内完成用户需求,这是第一位的,不可能为了在项目中使用某种先进的理念而花费时间和精力。当某种理念缺乏技术支持时,就不可能在项目中使用。只有当先进理念的使用可以为项目带来其它方法不可替代的好处的时候,才有可能使用它。在领域驱动设计刚刚问世的时候,技术框架特别是持久化框架大都还只支持表模式或者Activate Recorder,如果使用领域驱动设计,必须自行开发相应的技术框架,这也就是为什么起初领域驱动设计只有在复杂项目中才会应用的原因。

随着技术的发展,越来越多的框架开始支持领域驱动设计,比如,Java生态中的Spring Data,JPA等和.Net生态中的EF Core都采用了存储库模式,支持实体在关系数据库和/或非关系数据库的持久化。

框架的支持使领域驱动设计的应用变得广泛,不仅仅限于复杂软件的开发,但同时,框架的支持也带来模型对框架的依赖。很多框架使用标记(Annotation)对实体和属性进行标注,这使得领域模型需要依赖特定的框架,与框架无感知和存储无感知的本意产生矛盾,很多标记甚至带有数据库表的设计因素,这更带来与数据库结构的实际耦合。这种情况下,随着项目的深入,领域模型会逐渐蜕变为数据模型和数据库的定义,逐渐远离初衷。

领域模型在实现中无法脱离框架,受到框架的约束,因此,常常需要与实现框架进行妥协。在项目中,妥协是可以接受的,但必须明确妥协的目的和带来的负面结果,还需要明确哪些方面是不可以妥协的。解决框架依赖是领域驱动设计落地的主要技术难点。

更多内容参见《领域驱动设计.Net实践》