从三层架构迈向领域驱动设计

本文读者基本要求:从事信息管理系统开发,略懂GOF设计模式及SOLID设计原则,对三层面向过程机械编码厌倦,并且不知道出路在何方,如果还掌握代码坏味和重构手法,那是极好的。

1. 三层架构

理论介绍-->实际经验-->总结反思

1.1 简单介绍三层架构

严格分层架构模式的特点是上层只能访问相邻的下层,其他层次间的调用都不允许。三层架构就是一种严格分层模式,它把职责划分为界面展示、业务逻辑、数据访问三层,还有一个业务实体,前面三层都要依赖它,所以它并不构成一个层。结构如图1

三层架构的特点是一种面向过程的编程思想,特点如下:

a. 业务实体类中基本上只有属性没有方法。

b. 业务逻辑层的类基本上只有方法没有属性。

c. 将数据表结构映射为业务实体类是一个惯用做法,以至于有人将其称之为“传统”。这样的好处是只需要理解一套模型,能够通过自动化工具从数据表直接生成业务实体,还能够自然而然的通过自动化机制存储与检索业务实体。但对于复杂点的业务,这样做就是绝大部分问题的根源。

d. 当业务膨胀起来,需要划分模块的时候,我们有个常用的变形:提取一个服务层出来,用来组合模块间的交互,还为业务逻辑层提供了一个防腐层,可以把记录日志、验证权限、处理异常等职责分配给服务层。结构如图2

上面介绍的就是我们常说的三层架构,由于采用了严格分层模式,用户界面层是绝对不能跨过业务逻辑层调用数据访问层的,同理服务层也是不能调用数据访问层。但是图2都有四层了,那它还是三层吗?这就需要见仁见智了,一般来说还是的。其实三层架构还有个更准确的名字----分层贫血领域模型架构,这样就不管多少层都能概括了,但是这名字没有三层那么朗朗上口。前面名字中的领域模型指的是业务实体,贫血意思业务实体中没有或很少方法。

1.2 实际应用中的三层架构

1.2.1 PetShop

三层架构比较著名的例子就是PetShop,其技术内容比较丰富,MemberShipProfileProvider,各种接口,各种Factory,可替换的数据访问层,缓存机制,消息队列等技术,看起来很牛的样子。但它的领域模型却比较简单,连模块都没有划分,只能算个玩具。很多年前,见识还比较少的时候,微软就是我心中的神,只有微软提供的技术才是最正宗的,微软说的都是对的,没有用上微软提供的技术,心里就各种不对劲。后来学习设计模式,知道有个模式痴迷症(如果在编码中没有用上模式,心里就各种不对劲),才明白原来自己之前患上了微软痴迷症。在我的实际工作经历中,微软痴迷症患者不在少数。就PetShop而言,微软只是展示一下他的技术而已,初学者们不明觉厉,盲目地奉它经典,以至于固步自封,不明白软件开发的路还很长很长,每种技术都有它的适用场景,选择权永远都在自己的手上(或在团队领导的手上)。

 

1.2.2 本人实际工作经历。

参加工作的前几年,都在小公司,经历的都是一个人开发的小项目,有时有个Web前端或美工配合一下,信息系统嘛,主要功能当然就是存储、检索、展示数据,业务操作就是CRUD了,业务逻辑最多就是验证一下业务实体填写的正确性,数据表的数量也非常有限。那时的我,在三层架构的统治下,做着一个快(枯)乐(燥)的数据搬运工(从数据库搬到界面或从界面搬到数据库)。


长期重复枯燥的工作会让人感觉前途无亮,穷则思变,结果就是人员的流动。对于短期小项目来说,人员流动根本不是个事,但是对于长期项目来说,可能就没那么简单了,某些关键人物的离职,可能会引起很长期的震荡,接手的人加班、发脾气绝对是正常的(这视乎接手人员的技术水平),甚至可能使项目停滞不前。

 

终于,我顺从内心的呼唤,离开那个简单的环境,加入了一个比较复杂的长期项目。和以前一样,采用三层架构,信息系统项目嘛,CRUD就是基石,项目中绝大部分的工作就是搬运数据。不同的是,开发人员有10个以上(人生中第一个团队开发);数据表超过200个(这是以前不敢想象的)。更加不同的是,有些功能,它可能牵涉到了所有的数据表,做这样一个功能,首先要把所有关联到的数据表都找出来,理解清楚表与表之间的关系,比较痛苦的是别人写的代码你基本用不上,都要自己从头搞。对于那些平时只是埋头搞自己一块功能的人来说,简直是要命。还有更要命的,不知道什么时候需求又变更了,而处理这个功能的人离职了。开始,接手的新人两眼泪汪汪求多给点时间,而领导不理解,以前谁谁不是很快就搞定了吗?那些站着说话不腰疼的同事说,这功能简单,这个、这个、还有这个表,那个、那个、还有那个表,这样再那样就解决了。我把这种协作方式成为嘴炮协作,真正的协作应该是代码层面的。新人没法辩驳一般最后会选择默默地加班。人员继续流动,这样的情形发生多次之后,领导开始意识到,情况没那么容易了。特别是如果几个关键开发者都离职了,那境况更是难上加难。就算没有人离职,情况一样是越来越难,这我在后面的一个项目中有比较深刻的体会,但是并不是所有人都会把这种难归结于架构不对或团队开发水平还有待提升,他们会认为这是需求的问题或者其他同事的问题,还有人会认为这是正常的必然的无解的事情。如果一段时间复杂的功能变更多起来,加班就会成为常态,如果加班能够搞定,情况还不算最糟糕。“水很深,水太深,水不知道有多深”开始成为了团队的口头禅。比较幸运的是当时那个项目这样的功能不算太多。最后有人总结出一句名言:“谁遇到谁倒霉 ,忍忍就过去了”。说到这里,很多人可能会说,让所有开发人员的熟读所有数据表不就行了?实际情况是,除了关键的几个人,其他开发人员往往没有那个愿意把有限的生命浪费在阅读这些下个项目就毫无用处了的数据表上,而且表的数量可能会增长到没有任何一个人能够整体掌控的程度。而且一个牵涉多个模块的复杂功能,不能调动相关模块来协助,反而都得直接与数据库打交道,其他模块的逻辑也需要自己处理,这是单打独斗的套路,体现不了团队的协作与效率;再有就是不能复用那些久经考验的代码,导致重复代码慢慢积累,系统缺陷也比较多。而且由多人接手后,一旦有人理解出了偏差,需求变更导致致命缺陷的几率会很高。

 

虽然项目组的生活氛围不错,时不时有经费给同事们出去吃完玩乐一下,但是不能预料什么时候需求就会提出一些“险恶”的功能,对人的精神也是一种考验。为了应付随时可能出现的各种险恶情况,我学习掌握了一些重构手法,学会用了UML来分析问题,还在项目中成功地应用了两个设计模式来解决一个棘手问题。但是在三层架构的大环境下,能够发挥的余地也是非常有限,有种有技术没地方用的感觉,常有新建一个类不知道该往哪个层放的情况。


后来,我还在另外一个采用三层架构的长期项目里呆过,情况与上一个项目基本一样,除了人员比较上一个项目稳定很多。就三层架构实际遇到的问题,我咨询了一些项目经理朋友,他们的意见如下:

经理A:代码是不可能写成书上介绍那样规范好维护的。

经理B:需求是不可能稳定下来的,代码也是不可能稳定下来的。

经理C:项目到了后期代码乱?难道不都是这样吗?

1.3 三层架构的反思

Linus Torvalds Bad programmers worry about the code. Good programmers worry about data structures and their relationships. (差的程序员纠结代码怎么写,好的程序员纠结数据结构和结构间的关系。)


三层架构的最大问题在于:实际应用中人们喜欢把内存模型和数据库模型保持一致。三层架构的大部分问题都是从这里衍生出来的。

数据库模型的粒度如果很小,那么大量的表连接很快就会让数据库跑不动了。

如果数据库模型的粒度如果很大(这是大部分项目的选择),代码的质量(重用性、稳定性、扩展性)就很差。由于没有从业务的角度去仔细定义每一个对象,每个人会根据自己的需要建立各种QueryModelViewModel,慢慢地类会多到想哭。或如果不建立各种Model,强行重用DataModel的话,那么接口提供的内容往往绝大部分都不是你想要的。

内存模型与数据库模型保持一致并非天生的,这是有很多原因造成的:

它建模的简单性让初学者无法拒绝,由于经验主义,以至于多年以后已经没有勇气去摆脱了;

没有专门论述三层与建模的书籍;

ORM工具误导,与数据表结构一致内存结构方便建立映射关系;

示范代码的误导,错误把示范代码当成产品代码;

等等......

种种误导导致很多人工作很多年后依然未能找到正确的路,忽略了一个重要的核心(业务建模)环节(业务模型要与代码的数据结构保持一致),但是他却坐上了项目领导的职位,这就是更大的误导了。以至于让人产生无论你去到那个公司都是一样的错觉(在很多人的经历中,这的确是事实,包括我自己),但事实不应该是这样的。

用户界面,领域模型,数据库它们应该具有同等的重要位置,领域模型在很多公司都是被忽略的角色。

我们应该相信:优秀的软件一定是由优秀的开发者制作的,团队的协作方式应该在代码层面,代码复用可以降低缺陷和提升效率。而这些都指向你应该离开“传统”三层架构。

还有一些三层开发人员最终患上了数据库痴迷症,他坚信程序就应该做个搬运工,其他的事情都应该交给数据库来完成,业务逻辑也应该写进存储过程里面去。

2. 三层架构到DDD的转变过程

优化层次关系-->重构到面向对象设计-->使用DDD相关模式深入重构

上面讲到,三层是“分层贫血领域模型架构”,那么DDD则可称为“分层充血领域模型架构”。从名字上看,它们就有亲戚关系,有亲戚好办事,嘿!

三层到DDD的过程大体是这样的:首先推翻严格分层的理念,采用松散分层来重新定义服务层(松散分层的意思是上层可以访问下层,而不只是相邻的下层),把调用数据访问层的职责交给服务层,接着把业务逻辑层移动到与业务实体在一起,再接着融合业务逻辑与业务实体,使之成为面向对象的设计,然后利用DDD的模式进行更深入的重构。在DDD技术掌握的还不是那么扎实的时候,三层技术基本仍然能够继续使用。


2.1 重构到面向对象的设计

由于目前的服务层职责是非常轻的,甚至有很多空壳的调用,所以平衡一下职责,把调用数据访问层的职责从业务逻辑层提升到服务层,需要的数据通过参数传递给业务逻辑层。这样,对于那些简单到无业务逻辑的CRUD就不需要去访问业务层了,直接调用数据访问层。

结构如图3,我们看到业务逻辑与数据访问层已经没有依赖关系了。

然后我们就可以把业务逻辑与业务实体移到一块。

然后把属于业务实体的逻辑迁移到实体类中。

上面简单单几句话和两张图就把问题搞定了,但是实际迁移过程中,风险是非常大的,如果没有充分掌握重构知识,建议不要在正式产品代码上尝试。有些逻辑无法归类到任何一个业务实体上的,就让它留在原地,成为一个领域服务。有些逻辑连领域服务都无法归类的,就让它留在服务层,在坚持大方向的前提下,细节灵活处理,因为每次重构都能够让你对未来的路看到更清楚,很可能下一次重构后你就会为这些流浪逻辑找到合适的家了。所有的建议都只是建议,最终决定权在你的手上,受苦的人始终都是你自己。

一个事实是:掌握的编程思想越多,那么搬迁起来就越容易,倘若编程功底太差,可能根本无法搬动,不建议初学者进行这些危险的试验,因为你一定会把事情搞砸的,如果你把事情搞砸了,请自我反省一下是不是编程思想不太够用。

上面的过程并非要你一步到位,你可以把代码重构到任何一个时刻,等待后面知识跟上了,再进行下一步的重构。

到目前为止,代码还是那些代码,只是位置变了而已,所以如果严格按照重构手法进行,编译、运行应该都是没有问题的。就这样,在现有生活没有任何影响的情况下,你已经为你的职业生涯打开了另外一扇门,再也不怕编程技术拼不过那些年轻人了。

实际上,DDD只是让你重新回归到面向对象编程,没有什么更加神奇的魔法,当然DDD超越面向对象的地方在于对类的设计提出了更多的指导方法。


2.2 使用DDD相关模式进行深入重构

正式介绍一下DDD的分层架构,当然DDD的架构并不限于分层,现在还有六边形架构、CQRSEventSourcing等技术可以选用,但是不要好高骛远,先把分层架构掌握好。原版分层结构如图5,改进版结构如图4,图4基本上就是图3的各个层换了名字,并且UI可以访问基础设施层。而图4与图5的区别在于,图4是基础设施依赖领域层,图5是领域层依赖基础设施层,这两层的关系倒置了。这样的倒置会更凸显领域层的核心地位,也有人认为这样已经算是六边形架构了。


2.2.1 DDD各层次职责解析


用户界面层:

原版----负责向用户展现信息以及解释用户命令。

补充---- MVCVC都属于UI层,V展现信息,C解析用户命令UI像地图一样把各个控制器关联了起来


应用层:

原版----很薄的一层,用来协调应用的活动。它不包含业务逻辑。它不保留业务对象的状态,但它保有应用任务的进度状态。

补充----协调应用的活动这句话太抽象了,我充实一下它:从数据访问中获取领域对象,调用领域对象的方法完成任务,然后再调用数据访问代码把领域对象的改变持久化。事务、权限检查、记录日志、处理异常的职责也归它管。这点和前面三层的服务层的职责其实是一样的。


领域层:

原版----本层包含关于领域的信息。这是业务软件的核心所在。在这里保留业务对象的状态,对业务对象和它们状态的持久化被委托给了基础设施层。

补充----业务对象的持久化工作我们已经提升到应用层了,一般情况下,这层最好不要涉及资源库的调用,但是并不绝对。资源库的抽象要么在领域层中,要么提升到了“应用程序框架”,领域层是不会依赖基础设施的。


基础设施层:

原版----本层作为其他层的支撑库存在。它提供了层间的通信,实现对业务对象的持久化,包含对用户界面层的支撑库等作用。

补充----这层的职责包含了三层的数据访问,但是并不代表UI层就可以调用数据访问的代码,而且职责范围扩充了,有人可能会把它当作存放公用代码的地方,但是建议这里只存放本项目公用的东西,如果能够跨项目公用的代码应该放在一个叫做“应用程序框架”的项目来完成,每个公司都应该有自己的应用程序框架。


回顾一下三层架构DDD分层的区别:

a. UI层技术基本一样,一些比较智能的绑定可能无法进行了。

b. 服务层基本一样。

d. 业务实体+业务逻辑 = 领域层

e. 如果三层架构不采用业务实体与数据表一致的做法,这层也是一样。


2.2.2 DDD模式简单介绍

DDD的模式有:聚合,实体,值对象,工厂,资源库,模块。如果完全没有DDD经验,建议首先阅读《领域驱动设计精简版》一书,可快速掌握DDD的理念。

聚合:这是个难点,一般建议是要设计小聚合,聚合与聚合之间用ID关联,不要直接引用。聚合包含实体,值对象。表达聚合的对象叫做聚合根。聚合内部所有对象的变更必须通过聚合根。聚合根的本质是一个实体。如果聚合要传递给其他模块(系统),一般不要直接传递聚合根,新建一个粗粒度的值对象来进行传递,即DTO对象,DTO也可由接收方建立,由接收方决定需要什么数据,这样就解耦了模块间的关联,至于数据库中是否需要把这个DTO冗余存储,则看实际情况。聚合的数据表设计原则:大表小类。即数据表采用粗粒度,聚合根内部使用细粒度对象,有可能的话,尽量每一条数据表记录就是一个聚合。

实体:特点是必须要有一个ID来标识自己,可包含值对象和其他实体。

值对象:特点是个只读对象,没有ID标识。

工厂:由于聚合的创建可能是个非常麻烦的事情,用工厂来封装这个复杂麻烦的过程。

资源库:资源库就是持久化聚合的地方,就是说数据存储的最小粒度是聚合。但是数据查询的需求可能非常灵活,实践中这条规则有点僵化,一般使用是读写分离方案,就是写的时候使用聚合对象,但是读的时候可以根据业务仔细建立一些查询模型(QueryModel)进行读取。至于数据库是否需要分成读写两个模型,还是要看实际情况,在系统更复杂和需要更高性能的时候,数据库的模型也要分成两个,不过它们之间的同步就比较麻烦了。领域事件、CQRSEvent Sourcing等技术就是用来解决这个麻烦的。

领域服务:总有一些需要多个聚合进行合作才能完成的业务,它们不能简单地划归参与的其中一个聚合,要用一个领域服务来表达,注意领域服务不是应用层的服务。

模块:如何划分模块,一般有横向划分和纵向划分两种,横向划分例如:实体模块,工厂模块,资源库模块。纵向划分例如:商品模块,订单模块,支付模块,每个模块内部都会具备聚合,资源库,值对象等元素。一般的经验是横向划分对项目没有什么帮助,纵向划分可以减少系统的复杂度。模块间的交互在应用层进行。


2.2.3 重构

掌握了DDD的知识之后,剩下的工作就是按照DDD的指导进行重构了。重构有风险,掌握成熟的重构手法能最大程度规避这种风险。在团队中进行改变架构级的重构,必须先要在整个团队中取得共识,否则你认为的改进在别人看来可能是在改退。

在重构的过程中,用各种代码坏味作为切入点,DDD模式、设计模式等作为方向,利用成熟的重构手法掌控重构过程,然后用SOLID设计原则评估你的重构成果。

最好团队中有比较精通需要掌握重构和DDD的人在旁指导和加强代码走查,确保一直走在正确的道路上。如果能够形成团队学习的氛围,那么一切都不重要了,现在没有掌握的思想技术,相信很快就能拥有。

再次强调,重构,是很多人的口头禅,但是他们不一定真的懂得什么是重构,没有掌握成熟的重构手法而进行重构跟盲目自信是一个道理,特别是对整个系统架构改进的重构,是个高风险的大工程,必须在团队中取得共识,并有明确的目的地和到达目的地的安全路径。

至此,三层到DDD的转换基本完成了,我们主要完成了一个思想上的转变,从此我们的技术之路踏上了新的征程。这是三层的终结,也是DDD的开端。路,还很长。

3. DDD技术支撑

3.1 面向对象语言

DDD的核心是要建立一个通用语言。何谓通用?首先项目所有关系人(需求、开发、测试、其他管理者、客户、甚至可以写到宣传海报上)都能够用通用语言来交流,人们要大声地建模,就是说领域模型应该能够容易地用自然语言表述,然后开发人员与计算机也要用通用语言交流,就是说尽量把通用语言写进代码里面去,这就是所谓DDD的战略层面。通用意味着最接近事实,越贴近现实的结构就越稳定,而面向对象的特点就是要降低代码与现实世界的表示差异,这点和DDD是一致的,因此实现DDD的首选技术就是面向对象语言,当然Eric Evans最新研究认为用函数式编程也能够进行DDD

面向对象的继承是一个最容易被误用的特性,一般认为组合优先于继承。更进一步,我认为基本上不应该通过继承来扩展对象的结构(属性),只应该用继承来区别行为(方法),这样做是符合里氏替换原则的。

建立对象结构是个非常复杂的工程,后面章节再介绍一点本人的经验。

3.2 领域对象存储

延迟数据库实现

DDD让我们把编程的核心从如何建立信息的存储结构,转移到如何让建立信息的事实结构上来了,这样,在陌生领域里一开始往往很难把握正确的结构,通过与领域专家持续地对业务的讨论,通过单元测试的反馈,通过重构慢慢将数据结构推向事实,到了项目后期,基本上无论需求发生什么变更,结构都是稳定的。在这个过程中,对象结构的变化是相当激烈的,如果每次变化都要去修改数据表结构,也是一件非常麻烦的事情,因此如果在开发中能够把数据存储在内存中,而不需要去考虑数据库,将会大大提升开发的效率。但是要保持内存和持久化的查询接口一致是个麻烦事,每种ORM都有自己的查询语言,一旦你使用了某种ORM的查询语言,那么你就跟它绑定在一起了,如果想要换个ORM就难了,因此我们或许应该考虑实现一个自己的不依赖任何ORM框架的查询语言。


取回只读属性

面向对象的重要特点之一是封装,这样会保护对象不被乱用,但是同时为重建数据结构带来了麻烦,不过现在的ORM基本都能够通过反射来取回只读属性了,还有个方法就是通过一个特殊的构造方法来取回数据结构。


对象属性递归引用

对象属性包含对象,这样无限的递归下去的情况,该如何存储?例如存储一个树的节点。这个时候必须要制造一个DTO来隔绝这种传递关系。

3.3 规则验证

单个对象本身正确性验证

这种验证最简单,就是把三层里的验证方法搬进相关类里面就行了,但是如果客户忘记调用验证方法了,怎么办呢?我们可以给所有需要验证的对象都实现一个验证接口(IValidatable),然后在保存入口自动调用此接口。


同类对象关键属性不能重复验证

由于我们已经约定,领域对象尽量不要跟数据存储打交道,所以要验证这个逻辑得放在服务层进行,但是这样的话验证方法的业务完整性就出问题了,因此把一个Repository传进检查方法也是一个办法,当然选择权在你团队的手上。


不同类对象之间关系验证

此类验证参看上一条验证。

3.4 Repository模式的实现参考

Talk is cheap. Show me the code. [Linus Torvalds]


说了那么多,不给些代码,小伙伴们都不同意了,因此这个地址是本人的一个Repository的参考实现【仅供参考,责任自负】。

https://github.com/MurrayMol/MAF/tree/master/src/Repo

本实现的主要思想是以类型作为存储单位,用泛型减少Repository的接口,统一存储的入口方便规则验证,统一内存与持久化存储接口方便在不同的存储结构中切换。


工欲善其事,必先利其器。思想再先进,最终还得以落地为准。为了实现上面介绍的思想,在本实现中用了三个开源软件,简单介绍一下:

ORMDapper,地址:https://github.com/StackExchange/dapper-dot-net

Dapper是个ORM框架,特点是需要写Sql语句,可能很多人会不喜欢这个。上面我们提到了要推迟数据库的实现,但是不代表数据库的重要性也降低了,其实DDD强调的是提升曾经被忽略的数据结构(领域建模)的重要性,而不是贬低数据库的地位,数据库依然是第一序列的重要事物。对待如此重要的东西,我觉得还是写Sql语句才能代表我们对它的尊重,而且面对一些查询模型,写Sql语句能够提供最强灵活性和最强的效率。至于Sql语句会变得非常复杂的问题,这绝对是你的数据模型没有建好,后面章节将会介绍一些数据建模的经验。

快速反射框架:Fasterflecthttp://fasterflect.codeplex.com/

反射在框架设计是个不可缺少的东西,但是它的效率是个不得不考虑的问题,Fasterflect是个使用Emit方式进行反射调用的框架,还有缓存、委托等方式提升性能。

OOMValueInjecter http://valueinjecter.codeplex.com/

类似于AutoMapperEmitMapper等框架,不过这个框架的特点是提供了一个可容易扩展的转换接口(契约),它本身的转换类功能倒不是那么强大,不过配合Fasterflect使用将如虎添翼。

3.4 开发过程回顾


典型的三层架构开发过程:

三层架构以数据库为核心,首先根据需求建立数据模型,然后根据数据模型建立数据库,再根据数据表结构自动生成业务实体,然后可以同时进行业务逻辑及用户界面的开发。

一旦开发中业务有所变动,那么首先要修改数据库,重新生成实体,然后其他开发小朋友才能继续工作,网络连接不好、数据库挂机、数据库管理员未能及时更新数据库等等原因都会导致开发过程被打断,好处是终于可以休息一会,坏处是由于要赶进度晚上可能得加班。

经常变更数据库结构总不是一件愉快的事情,为了避免数据库结构变动,要求编码阶段之前尽量要把需求固定下来,中后期越少变动越好。由于业务逻辑与数据库绑定紧密,所以单元测试困难重重。当性能出现问题的时候,到底是代码逻辑没有写好,还是Sql语句没有写好,诊断有点困难。由于类的粒度太大,设计模式罕有用武之地,设计原则跟自己没有关系,久而久之可能会觉得编程思想都是骗人的。


DDD开发过程:

DDD以领域模型为核心,首先根据需求建立领域模型,然后根据领域模型建立代码模型,然后就可以同时开发业务逻辑和用户界面了。

我们有一个模拟数据库存储接口的内存数据库,因此这时候不需要考虑数据库,如果这时业务发生变化,直接修改对象结构是非常简单的事情。直到开发后期,所有功能都已经开发完成,业务结构也稳定下来了,我们再根据领域模型建立数据库,进行一个简单的与业务逻辑集成就完工了。

免除了开发过程中数据库经常变动的烦恼,开发过程不会被打断,随时可以进行单元测试,随意可以与用户界面集成把系统跑起来,开发逻辑的时候不考虑数据库,开发数据库的时候不考虑业务,关注点更加集中了。出现性能问题可以单独测试数据库组件和业务逻辑组件,更容易定位问题。类的粒度很小,各种重用,各种设计思想都纷纷派上用场,感觉终于跟国际接轨了。

 

4. 领域建模经验

Comming Soon....

5. 数据库设计与优化经验

Comming Soon....

6. DDD实际工作经验

Comming...

7. DDD项目实践参考案例

Comming....

你可能感兴趣的:(架构)