`
javaboy2006
  • 浏览: 186308 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

基于DDD项目的设计总结

阅读更多
一、为什么要使用领域模型
• 有助于团队创建一个业务部门与IT部门都能理解的通用模型,并用该模型来沟通业务需求、数据实体、过程模型。
• 模型是模块化、可扩展、易于维护的,同时设计还反映了业务模型。
• 提高了业务领域对象的可重用性和可测性。
二、领域的分层架构
在Eric Evans《领域驱动设计--软件核心复杂性应对之道》中对领域的分层架构如下:

• 用户界面(表现层):负责给用户展示信息,并解释用户命令。
• 应用层:该层协调应用程序的活动。不包括任何业务逻辑,不保存业务对象的状态,但能保存应用程序任务过程的状态。
• 领域层:这一层包括业务领域的信息。业务对象的状态在这里保存。业务对象的持久化和它们的状态可能会委托给基础设施层。
• 基础设施层:对其它层来说,这一层是一个支持性的库。它提供层之间的信息传递,实现业务对象的持久化,包含对用户界面层的支持性库等。
三、如何创建领域模型
• 寻找概念类
• 将其绘制为UML类图中的类
• 添加关联和属性
四、领域模型的开发步骤
• 对领域进行建模
• 设计
• 开发
• 单元测试和集成测试
• 基于设计和开发来完善、重构领域模型
• 使用更新的领域模型重复上述步骤
五、实际项目设计
1、层次结构:

2、层次之间的交互
A、页面提交表单数据到Action,Action创建DTO对象并设置相应属性值为表单数据
B、Action传递DTO对象给Facade
C、Facade中套用ServiceTemplate事务模板以加入事务管理,在ServiceTemplate中根据具体业务调用Factory或Reposistory,分别create或者load出DomainModel对象
D、Facade传递DomainModel对象给Service
E、Service执行具体业务逻辑(调用DomainModel对象相应的业务方法)
F、Service调用Reposistory对状态已改变的DomainModel对象进行持久化操作(调用相应DAO)
注:
在Facade或Service中如果需要查询DomainModel对象中的属性值,调用DomainModel对象的getDataInfo()方法得到DataInfo对象,通过DataInfo对象查询所需数据,包括Service返回给Façade业务处理结果中所包含的业务数据。
3、对于DomainModel的设计
DomainModel基于贫血模型来设计。在Robbin《总结一下最近关于domain object以及相关的讨论》一文对于贫血模型领域的切分原则写到:
引用
Rod Johnson提出原则是“case by case”,可重用度高的,和domain object状态密切关联的放在Item中,可重用度低的,和domain object状态没有密切关联的放在ItemManager中。
我提出的原则是:看业务方法是否显式的依赖持久化。

在该项目中DomainModel内的业务逻辑方法没有任何对DAO接口的依赖,如果需要对DomainModel进行持久化操作全部由Service调用Reposistory的store()方法进行处理,对DomainModel的持久化操作已全部封装于Reposistory中。DomainModel只提供改变自身状态的业务处理方法。
4、对DomainModel的访问原则
A、必须从领域模型的根部操作模型的各个属性
例如一个领域模型结构如下:
public class PersonDomainModel {
    Person person;
    Bank   bank;

    public void modifyPerson(String name, String age) {
        this.person.setName(name);
        this.person.setAge(age);
    }
}

操作该领域模型的person属性只能通过modifyPerson()方法进行,而不能直接调用person对象的setter方法。
B、必须保持领域模型的完整性。最初由Factory构造一个模型的时候,就必须将其进行完整的初始化,而不是只构造一部分,然后在接下来的处理过程中逐步完善。
5、Factory和Reposistory的职责
Factory只负责领域模型对象的创建(从无到有);
Reposistory对持久化进行了封装,它操作的是已存在的领域模型对象(从数据库中读取数据or重新持久化到数据库)
6、项目待优化部分
在Service调用Reposistory的store()方法进行持久化操作时,如果某个业务仅对DomainModel的一部分属性进行了修改,在持久化到数据库中时仍然会将DomainModel的所有属性全部进行一次update操作。这样的数据库操作没有必要,只需对DomianModel中修改过的属性进行持久化操作即可。可以考虑在DomainModel上提供一个类似保存所有修改属性的列表,在Reposistory持久化时仅对该列表中的修改属性进行操作。

参考资料:
1、Eric Evans《领域驱动设计--软件核心复杂性应对之道》
2、Robbin《总结一下最近关于domain object以及相关的讨论》http://www.iteye.com/topic/11712
  • 大小: 16.3 KB
  • 大小: 29.5 KB
分享到:
评论
17 楼 javaboy2006 2009-09-24  
ORM框架里确实没配Lazy Loading。
16 楼 lonelybug 2009-09-24  
这么做有一个问题,就是,没有办法作Lazy Loading来提高性能了,因为你都依靠Repository来做跟底层DAO打交道了!

我理解的对不对?
15 楼 timshaw9791 2009-09-19  
taowen 写道
你在哪里听说的DDD不反对使用service类来处理业务逻辑了?别告诉我是Domain Service啊。。。


嘿嘿,还真有,见我附件,不但不反对,还告诉了我们判断该不该这样做的标准。我是不是很土鳖阿...这么较真。
主要是因为我这几天也在学习这方面的东西,早上泛读了下精简版DDD。

看样子本版一些人都把领域模型(Domain Model)直接理解成DDD里的Entity的集合了,当然也有可能是我误会了,估计是OO影响的,我觉得这样不妥.OO里,方法是二等公民,必须依附到一个Object,现在世道变了,方法以及方法所表现的逻辑也要当一等公民,函数式编程这不成潮流了吗,如果从这个角度看,早些年AOP的流行也潜在反映了这个诉求:我们要更多的手段来操作一些逻辑!其实回顾一下就知道,OO就是个手段,我们组织问题域信息的手段,在结构化编程后期,问题域已经复杂到我们难以搞定的程度,这时候OO逐渐流行。既然是个手段,没必要抱死不放吧。从这个意义上来说,讨论贫血模型还是充血模型好,我觉得没太大意义。大家都是反映域模型,当前条件下哪个更方便就用哪个,被必要弄出气宗剑宗看谁是正宗的戏来。

我从DDD上看到的,OO只不过是实现他的核心"Domain Model"的一种工具,这个我们一会儿用UML一会儿用草纸记录的不停交流的东西才是他的核心。

现在换一个方式说,你说新增删除在大多数情况下算不算域逻辑?如果算的话,按照你的想法,是不是person也弄几个person.create,person.delete方法?

14 楼 lonelybug 2009-09-19  
对于你所说的,修改之后的在Repository里面的更新优化问题,你可以应用DirtyMark设计模式。Hibernate, J2EE都是在内部应用了类似的东西。

这个要在Person,Bank上分别的,而不是在PersonDomainModel,按照你的设计。
13 楼 icewubin 2009-06-18  
楼主怀旧啊,头像怎么换成世嘉土星了啊?
12 楼 javaboy2006 2009-06-18  
raymond2006k 写道
领域建模,至少是 Person类,而不是多了个后缀的 PersonDomainModel 类。

之所以有PersonDomainModel是因为业务上需要将Person和Bank封装在一起。 

raymond2006k 写道
再说例子中那么多Action,Service,Facade, DataInfo类,完全还是约束于框架,根本不是在领域建模。

贴的图是描述项目设计的的总体层次结构,不完全是在描述领域建模部分。
11 楼 icewubin 2009-06-18  
taowen 写道
你在哪里听说的DDD不反对使用service类来处理业务逻辑了?别告诉我是Domain Service啊。。。

不如先把业务逻辑界定一下,不同人理解的业务逻辑都不太一样的。

我手打一下DDD中文版(Eric Evans著,陈大峰、张泽鑫译)109页的一段关于仓储(Repository)的介绍吧(也有可能我会错你的意了,看看无妨):
引用
为每种需要全局访问的对象类型创建一个对象,该对象为该类型所有对象在内存中的集合提供影像。用一个众所周知的全局接口来设计访问入口。提供增删对象的方法,把对数据存储的实际的插入和存储封装起来。提供根据某种标准筛选对象的方法,返回完整实例化了的属性值符合标准的对象或对象集合,把实际的存储和查询技术封装起来。仅为确实需要直接访问的聚合根提供仓储。让客户聚焦于模型,把所有对象存储和访问的工作委托给仓储来完成。
10 楼 icewubin 2009-06-18  
yulenice 写道
service是对行动的封装,没有主属,可以分布在application,domain层.
factory也不是必须的,在需要的情况下.
application的service处理transaction.也可以直接调用repository.
domain和repository的分离也不对.因为没有aggregate的概念.
dao在jpa等的支持下,也可以不要.

“是否有aggregate的概念”和“domain和repository是否分离”没有必然联系吧。

repository也可以为超过一个domain服务的。
9 楼 yulenice 2009-06-18  
service是对行动的封装,没有主属,可以分布在application,domain层.
factory也不是必须的,在需要的情况下.
application的service处理transaction.也可以直接调用repository.
domain和repository的分离也不对.因为没有aggregate的概念.
dao在jpa等的支持下,也可以不要.
8 楼 taowen 2009-06-18  
你在哪里听说的DDD不反对使用service类来处理业务逻辑了?别告诉我是Domain Service啊。。。
7 楼 icewubin 2009-06-17  
raymond2006k 写道
就楼主贴的图为例,我不知道是不是Eric那本书里的。 文字说的是领域建模,而例子却完全不是这么回事。

领域建模,至少是 Person类,而不是多了个后缀的 PersonDomainModel 类。

领域建模有一点要求 Data, Behavior 封装在一个类或者接口中,对使用者而言,对象是自我描述,自我行为的。create,load 可以由 repository 进行, 但update,save,delete等在调用角度上,必须由对象自己完成。

形如:

Person person = repository.load( id);
person.setAge( 23);
person.update();

再说例子中那么多Action,Service,Facade, DataInfo类,完全还是约束于框架,根本不是在领域建模。


不完全是,DDD中也不反对使用一个service类来处理业务逻辑,没有严格限定说一定要把Data和业务逻辑封装在一起吧。大家大概发现了,我这里写的是业务逻辑,而不是Behavior,我认为这两个概念还是分开说得好。一般来说有很多操作都是业务逻辑,而没有那么多的Behavior,而业务逻辑的操作的复用就是个很大的问题。

PS:我最近正好在翻这本书。
6 楼 raymond2006k 2009-06-17  
就楼主贴的图为例,我不知道是不是Eric那本书里的。 文字说的是领域建模,而例子却完全不是这么回事。

领域建模,至少是 Person类,而不是多了个后缀的 PersonDomainModel 类。

领域建模有一点要求 Data, Behavior 封装在一个类或者接口中,对使用者而言,对象是自我描述,自我行为的。create,load 可以由 repository 进行, 但update,save,delete等在调用角度上,必须由对象自己完成(或者由框架提供)。

形如:

Person person = repository.load( id);
person.setAge( 23);
person.update(); //也可以由框架来做

再说例子中那么多Action,Service,Facade, DataInfo类,完全还是约束于框架,根本不是在领域建模。

补充一下:存在 Action,Facade,Service 也许可以划归 DomainModel 外围, 但可能我比较理想化。 我认为表示层按DomainModel 可以设计为  XXXPage 类,由formBean,status等属性,onCreate,onView,onQuery 等Event构成完整的领域模型, 而不是 Action.execute 方法; Application 层也一样,再前进一把,也能抽象为本层的 Domain Model。

也许真的比较理想化。-_-
5 楼 javaboy2006 2009-05-19  
icewubin 写道
引用
6、项目待优化部分
在Service调用Reposistory的store()方法进行持久化操作时,如果某个业务仅对DomainModel的一部分属性进行了修改,在持久化到数据库中时仍然会将DomainModel的所有属性全部进行一次update操作。这样的数据库操作没有必要,只需对DomianModel中修改过的属性进行持久化操作即可。可以考虑在DomainModel上提供一个类似保存所有修改属性的列表,在Reposistory持久化时仅对该列表中的修改属性进行操作。

Hibernate中,配置一个entity的类属性为dynamic-update="true",最好顺带再加上dynamic-insert="true"。

我们目前用的是ibatis,hibernate写出来的hql dba不大好调优。
4 楼 魔力猫咪 2009-05-19  
沟通是必然的。无论是什么项目管理方法,现在都强调沟通。如果客户不重视,不沟通,那么项目失败是必然,成功才是出了问题。
不过沟通未必设计人员直接和客户沟通。可以安排专门的人员和客户沟通,编写需求列表,然后和程序员去讨论。
3 楼 icewubin 2009-05-19  
引用
6、项目待优化部分
在Service调用Reposistory的store()方法进行持久化操作时,如果某个业务仅对DomainModel的一部分属性进行了修改,在持久化到数据库中时仍然会将DomainModel的所有属性全部进行一次update操作。这样的数据库操作没有必要,只需对DomianModel中修改过的属性进行持久化操作即可。可以考虑在DomainModel上提供一个类似保存所有修改属性的列表,在Reposistory持久化时仅对该列表中的修改属性进行操作。

Hibernate中,配置一个entity的类属性为dynamic-update="true",最好顺带再加上dynamic-insert="true"。
2 楼 javaboy2006 2009-04-12  
unsid 写道
领域模型是天然的将领域驱动设计过程和实现绑定的工具,如果不能再需求时期建立DSL,如果还是按照原有的需求模式进行,而后期用领域模型来思考问题是没有意义的,因为很可能存在很多无法映射到需求的无意义的领域模型,所以沟通还是主导的\最难迈的一步.

在开发过程中来不断地完善和重构领域模型,不过开发人员比较痛苦。
1 楼 unsid 2009-04-12  
我在看领域驱动设计这书,我觉得书中的方法隐含了一个潜在的前提:客户十分配合
在官僚机构例如政府的项目中,建立一种统一中间语言和客户用来精确沟通只会把客户惹恼"我tm一天挺忙还要记住你这些东西"

领域模型是天然的将领域驱动设计过程和实现绑定的工具,如果不能再需求时期建立DSL,如果还是按照原有的需求模式进行,而后期用领域模型来思考问题是没有意义的,因为很可能存在很多无法映射到需求的无意义的领域模型,所以沟通还是主导的\最难迈的一步.

相关推荐

    ddd.rar_MFC 毕业设计_ddd359.com_ddd875.com_mfc的毕业设计_read brain

    总结来说,这个基于MFC的毕业设计展示了MFC在开发具有交互性和趣味性的桌面应用方面的强大能力。通过这个项目,开发者不仅可以掌握MFC的基本用法,还能锻炼到对用户输入的实时响应和处理,以及游戏逻辑的设计。对于...

    一个简单的DDD领域模型项目

    对于DDD项目而言,.NET Core提供了一个理想的开发环境,能够灵活地构建领域模型并与其他组件解耦。 在DDD项目中,领域模型是核心部分,它代表了业务领域的概念、规则和行为。在我们的项目“MyProject”中,我们可以...

    Laravel开发-laravel-5.1-ddd

    总结来说,“Laravel 开发 - Laravel 5.1 DDD”项目旨在展示如何结合 Laravel 框架的强大功能和 DDD 的设计原则,构建出更符合业务需求、易于维护和扩展的 web 应用。通过深入理解和实践这些概念,开发者可以提升...

    领域驱动设计(DDD)演讲

    - **ドメイン駆動設計を実践する**:基于这些“好的习惯”,在实践中理解和应用DDD的核心原则。 #### 三、实践的难点与对策 ##### 1. **アンチパターン** - **モデリングと設計の工程を分ける**:这是一种常见的...

    gencode_ddd:一个项目管理带代码生成器项目

    总结来说,"gencode_ddd"是一个集成了项目管理和代码生成的工具,旨在提升DDD项目的开发效率。通过深入理解和有效使用,开发者可以将更多的精力集中在业务逻辑上,而不是繁琐的基础架构工作,从而实现更快、更高质量...

    ddd实战中的那些坑

    首先,DDD强调的是领域建模,它基于模型驱动的原则,即通过领域专家和开发人员的紧密合作来构建领域模型。然而,在实际操作中,找到合适的领域专家并非易事,而且即使找到了,他们与开发人员之间的沟通障碍也会导致...

    基于HTML旅游网站项目的设计与实现——联途旅游网服务平台网站HTML模板HTML+CSS+JavaScript

    ### 基于HTML旅游网站项目的设计与实现 #### 一、项目背景及目标 本项目旨在通过构建一个旅游网站——“联途旅游网服务平台”来帮助学生掌握HTML、CSS和JavaScript的基础应用,并通过实际动手操作提升网页设计能力...

    DDD 领域驱动实战落地ABP.pdf

    标题《DDD 领域驱动实战落地ABP.pdf》和描述《基于C# 的DDD最佳实践落地例子》暗示本文档是一本关于如何在.NET环境,特别是基于ABP框架实现领域驱动设计(DDD)的实战指南。DDD是一种软件开发范式,它强调软件开发应...

    基于spring boot,spring cloud,axon framework的领域驱动设计的-Taroco.zip

    《基于Spring Boot、Spring Cloud与Axon Framework的领域驱动设计实践——Taroco项目解析》 在现代企业级应用开发中,Spring Boot和Spring Cloud已成为构建微服务架构的标准选择。Spring Boot简化了Spring应用的...

    基于领域分析设计的架构规范.docx

    总结来说,基于领域分析设计的架构规范着重于如何通过读写隔离优化查询操作,利用状态图揭示核心业务逻辑,并通过对比贫血模型和充血模型,强调了业务逻辑应与数据结构紧密结合,以提升软件设计的质量和效率。...

    后台产品设计系列:产品设计方式(二) .doc

    在后台产品设计中,有两种主要的设计方式:简单系统设计方式(需求驱动设计,RDD)和复杂系统设计方式(领域驱动设计,DDD)。本文将以视频产品后台为例,详细介绍这两种设计方法。 1. 简单系统设计方式 - 需求驱动...

    ddd-cqrs-cqrs-es:该演示项目介绍了如何根据DDD,CQRS,CQRS-ES模型分析和设计软件

    《基于DDD、CQRS与事件溯源的软件设计实践——ddd-cqrs-cqrs-es项目解析》 在软件开发领域,领域驱动设计(Domain-Driven Design,简称DDD)、命令查询职责分离(Command Query Responsibility Segregation,简称...

    javaEE源码报告-cargotracker-ddd:使用JavaEE的领域驱动设计

    《JavaEE源码报告——基于Cargotracker的领域驱动设计(DDD)解析》 JavaEE作为企业级应用开发的主流平台,其强大的功能和灵活性深受开发者喜爱。本报告将深入探讨一个名为"Cargotracker"的项目,该项目采用领域驱动...

    领域驱动 NET领域驱动开发框架学习培训

    这个系列的教程会和大家一起一步一步搭建一个简单实用的基于领域驱动设计(DDD)开发模式的一个项目开发框架。 通过结合实际的代码应用让大家对领域驱动开发有一个更好的理解。 章节1:基础介绍 课时1课程介绍 课时2...

    DDDKataTutoring:DDD kata为中国大陆的绘画补习学校设计班级调度系统

    《基于DDD的中国大陆绘画补习学校班级调度系统设计》 在软件开发领域,领域驱动设计(Domain-Driven Design,简称DDD)是一种强调以业务领域为中心的软件开发方法论。本项目"DDDKataTutoring"是针对中国大陆的绘画...

    scala-ddd-example:使用Akka HTTP在Scala中应用的λλ六边形架构+ DDD + CQRS

    本文将深入探讨一个名为"scala-ddd-example"的项目,该项目是基于Scala编程语言实现的一个示例应用,它结合了Akka HTTP、领域驱动设计(DDD)、命令查询职责分离(CQRS)等技术。通过这个项目,我们可以学习如何在...

    flask-ddd:该存储库用于使用flask尝试ddd

    1. **分层架构**:通常,一个DDD项目会采用分层架构,包括表现层、应用层、领域层和基础设施层。Flask可以作为表现层,处理HTTP请求和响应,而领域逻辑则在领域层实现。 2. **模型与数据库映射**:使用ORM(Object-...

    系统架构方法 系统架构设计师

    #### 3.4 基于领域的设计(Domain-Driven Design, DDD) 基于领域的设计主张从业务角度出发来设计系统架构,强调将业务规则和技术实现紧密结合在一起。DDD的核心思想是通过建立统一的语言和模型来消除业务与技术之间...

    C语言 学分管理系统的设计

    总结起来,这个项目提供了一个学习和研究C语言编程、系统设计和实施的实践平台。通过阅读源代码,可以学习到如何使用C语言进行文件操作、数据存储、用户输入输出等;通过需求文档,可以学习到系统设计的规范和方法;...

    web课程设计网页规划与设计:鲜花网站设计——基于HTML+CSS+JavaScript制作网上鲜花网页设计(5页)

    ### 一、项目概述 该项目是一项面向学生的网页设计任务,主要目标是利用HTML、CSS以及JavaScript这三种核心技术来创建一个在线鲜花网站。该网站旨在通过直观的用户界面和丰富的多媒体元素来提供良好的用户体验,...

Global site tag (gtag.js) - Google Analytics