绪论:
三点:软件开发的方法论,讨论系统分层的必要性,提出构建领域模型的重要性;讨论OO技术是构建领域模型的主角;
争论:面向对象还是面向数据?一个
企业级应用的系统架构是应该面向对象还是面向数据的争论由来已久,并且从未停止过.这是一个非常尖锐且很难抉择的问题.产生这一问题的根源就在于当前企业级应用所依赖的数据库几乎无一例外的都是关系型数据库,关系型数据已经盛行了很多年,它也确实....但是后来随着面向对象技术的兴起,人们意识到面向对象技术在解决复杂业务问题上有着无可比拟的优势.这又驱使人们试图通过oo技术构建一个领域模型来处理业务逻辑.然后面向对象的领域模型和面向关系的数据模型天生存在着巨大的差异,这种差异使得企业级应用中构建领域模型变得
在基于企业级应用必须依赖于关系数据库的前提下,人们并没有放弃通过OO技术构建领域模型的尝试,随着这方面的理论不断地成熟,具有实际可操作性的设计模式被总结并加以应用,人们逐渐地总结出了一整套将对象模型映射成关系模型的理论和方法,并产生了很多优秀的ORM框架,从而在关系模型和领域模型之间构建起一座桥梁,让开发人员得以通过OO技术来解决复杂的领域问题.
客观地讲,当今的企业级应用的主流依然是以面向数据为主.
我们无意要在这里比较孰优孰略,但是一般而言,对于那些数据量巨大,性能要求较高的系统,面向数据的架构要更好一些,而对于业务逻辑复杂,需求变动频繁的系统,面向领域的架构会更加适合.当然,正所谓技高人胆大,想要做到鱼和熊掌兼得,也不是不可能的.如何权衡整体的得失做出全局性的决策,让系统的综合性能达到最高,是一名架构师安身立命的核心技能之一.
1.领域模型:重中之重
从mvc谈起,涉及CC中关于软件复杂度管理的论述.
若干处来,MVC之所以成为一种广泛应的经久不衰的架构模式,根本原因在于它对一个软件系统做了合理的划分
自...以来,人类之所以能够完成各种宏大的工程,无不在应用这样一条放之四海而皆准的原则:将复杂任务分解为多个简单的子任务!也就是"关住点分离".MVC便是这一恩想下的典型架构
2.领域模型中的重要元素:
Entities
Value Objects
Aggregates
Domain Events
2.ORM不能回避的现实问题
在构建领域模型时,ORM确实是非常非常重要的一环.而且这一环也非常复杂,包括类继承体系与数据库的映射,抓取策略和缓存管理在内的一系列问题都是非常棘手的.即使我们现在已经有了像Hibernate这样优秀成熟的ORM框架,开发人员依然必须对ORM的原理和内部机制有深入地了解才能完成这一工作.否则领域模型很可能会受到数据库关系模型的"污染"进而被"同化",或者更常见的情况是因为糟糕的映射导致系统性能严重下降.讲到这里想说句题外话.笔者认识很多从事企业级应用开发的朋友,他们中有很多学习和使用Hibernate已经有三四年了,但是自觉依然不得要领,他们在项目中总是固定使用Hibernate中的"一小部分"功能,对一些所谓的"高级"机制从为涉及过,而且也找不适用的场合.这说明他们过去参与过的项目并没有构建过直正的领域模型.如果我们从领域模型的角度出发去思考对象应该如何从数据库中重建出来,我们就会发现我们会面临很多"必须"面对的问题,当你带着这些问题去学习一个ORM框架时,你会惊奇地发现,你所想到过的这些问题框架都给出了解决方案.学习ORM框架,必须要有面向对象方面的设计思想作为背景,总是从领域模型出发思考如何映射到数据库,如何从数据库中加载出对象才能领悟ORM框架的真实用意.
阻抗失配
关于性能的考量;可选方案.
3.IOC&AOP:重要的补充
虽然人们将IOC视为一种设计模式,但由于IOC所解决的问题几乎是所有OO系统都会遇到的,也可以说是OO技术本身在对象创建方面的缺失或者说是天生不足,这才导致IOC变得如此必须.,显然,IOC有着超越一般设计模式的重要地位,
如同rod jonason所赞叹:"再怎么赞扬IOC的好处都不为过!",IOC对于OO来说,就如同
4.团队管理和工作流程
5.应用领域驱动设计的面临的巨大挑战
面向数据还是面向领域?这是个问题!
为什么有如此之多的系统是面向数据而不是面向领域的?
DDD一书中引入的独创性概念中,Aggregation是非常重要的一个.这个概念在此之前从末被提出过,它对进一步合理细分领域模型提供了非常好的理论依据.划分Aggregation是对领域模型的进一步深化,Aggregation能阐释领域模型内部对象之间的深层关联.对Aggregation的划分会直接映射到程序结构上.比如:DDD推荐按Aggregation设计model的子包.每个Aggregation配备一个Repository.Aggregation内部的非root对象是通过导航获得的.等等.
若干重要细节:
1.如何建立完整,自封闭的领域模型。举例:user.subscribe()和user.post(Message reply)
所有的外部请求到达应用层后,应用层知道如何把外部请求转换成驱动模型运转的指令,模型根据指令运转到达结果状态,外部视图选取模型中用户关心的部分呈现出来。
2.如何建模领域服务。
3.关于领域对象的依赖注入
参考:AspectJ in Action
http://www.infoq.com/news/2008/02/ddd-di-aop
Spring参考文档:6.8.1. Using AspectJ to dependency inject domain objects with Spring
4.Repository VS. DAO
Repository:位于领域层,面向Aggregation Root。
DAO:是面向数据访问的,不再需要。在领域领域驱动的项目中,去除DAO,淡化数据访问的概念,使用更加OO的Repository来替代。
5.关于领域对象和领域服务以及Repository之间的互相依赖问题。
当领域对象所需要的数据需要通过查询得到时应该怎么办?
1.通过为领域对象注入Repository来实现。
2.通过异步消息机制+Domain Event的形式来实现
考虑核心问题:领域对象可不可以依赖Repository?
一种声音:有个感觉是无论是DAO或者是Resposity,都是domain logic里的噪声。如果Domain logic也能透明的调用DAO或Respoisty,这样的domain模型会更完美,而且更关注业务。
这么说来repository只用来取root?从概念上讲不错,可是要知道往往一个root下面会有成百上千个node,这么巨大的一坨关系树我们用repository取出来然后在“关系之间游走”...是否有点滑稽?呃...或许我们能想到引入延迟加载,取出来的root下的二级node都用stub来占位;不过这又为污染我们纯洁的领域模型创造了良机...
我们常说的“领域模型”是一个分析模型,是对领域问题的整体表述,决不是编程的实现模型,一个领域概念不一定会隐射成一个类,有可能要映射很多的类。同样,我们的实现模型也有很多领域模型不设计或不关心的东西,像领域对象的crud,等。这对我们是一个启示,在从领域模型到实现模型的隐射过程中,我们要明白它们各自的本质。这对实现模型的组织结构也有一定的借鉴意义。
“领域模型”是一个针对业务逻辑抽象的模型,是一组概念的集合,和软件编程并无关系。
Repository的角色和Factory有些类似,它是一种编程层面上的Artifact,并无业务意义。对于它在架构中的位置,可能放在Model里会好些。就像是Factory总是伴随它的产品在一起一样。
架构:
1.包结构:
领域层应该按业务逻辑相关性(即aggregation)来组织。
应用层面向外部应用,不应该使用领域层的分割模式。展现层同样如此。
关于领域层的各对象:
领域对象和领域服务是领域模型的主体,地位相当,应等同对待。
Repository和Factory一样,属于设计和实现层面的衍生产物,在领域模型中没无对应概念,但是确实应该置于领域层!
DDDSample中把一些依赖具体框架的实现类划分到infrastructure包的做法,并不是一个好的做法。这分法试图突出领域层的“纯粹性”,但是,我们要明确,领域模型并不是领域层,领域层是领域模型的编程实现,既然是“实现”,那些具体类是不可避免的。它们是“实现模型”的重要组成部分!如果隔离到nfrastructure包,反而在包结构上让它与它们的实现类产生较大的距离,这种包结构好不到哪里去。