一次关于DDD的讨论 从中看我对DDD的疑惑 (再次请banq解惑)

首先感谢@banq上次的回复和具体实例 但是我不得不说。。 理论性太强了落实到代码层面 还是不知道如何去做。 这几天也在看书 和 讨论 以下的讨论也恰是我对DDD所有的疑问 ,请banq 和 各位有 DDD实践的同行 帮忙看一下。 因为我觉得思维进入了死胡同了, 估计不仅是我,一定很多人有这些问题 =================================================== 回答者 16:22:24 你目前重构的项目是:java的吗? 提问者 16:22:47 是啊! 提问者 16:22:51 急切啊! 回答者 16:23:30 一张表、一个实体类,一个DAO 回答者 16:23:43 目前是这种模式吗? 提问者 16:24:33 对啊!差不多 提问者 16:24:56 目前就是贫血那种 一个模块 一个service 一个DAO 提问者 16:25:00 可能多个表 提问者 16:25:05 一个或两个 回答者 16:25:09 问题不大! 提问者 16:25:18 使用hibernate DAO会每张表一个实体类 回答者 16:25:27 UI层的展示用的啥模型 提问者 16:26:01 UI就是这样 , struts Action 控制器里面 会调用service代码 提问者 16:26:16 调用完业务方法就跳转 回答者 16:26:38 渲染界面,返回的是实体类吗? 回答者 16:26:45 还是DTO 提问者 16:27:44 界面采用的是绑定技术 就是在action控制器里面定义model类, service为model类赋值的话, JSP标签会自动显示表单数据 提问者 16:28:05 如果不采用绑定的话, 应该需要拼DTO 或者VO类 提问者 16:28:14 就是一个数据对象 提问者 16:28:19 或者数据对象的List 提问者 16:28:26 现在是这样的。。 回答者 16:28:37 这样也挺好的,只要能满足要求。 回答者 16:29:11 一个思路: 1、确定目前项目的分层。 2、确定目前每个层的元素及其职责与实现技术。 3、确定目前层与层之间的交互方式(传入和传出的都是啥)。 回答者 16:29:47 下一步是: 1、确定目标项目的分层。 2、确定目标每个层的元素及其职责与实现技术。 3、确定目标层与层之间的交互方式(传入和传出的都是啥)。 回答者 16:30:44 横切面都是通过AOP实现的吧? 回答者 16:31:40 有用spring吗? 提问者 16:32:46 有啊 提问者 16:32:52 AOPspring 都有 提问者 16:33:06 就是一般贫血哪些东西 都有 提问者 16:33:32 我有个重构思路 说来你看看属于不属于DDD的思维啊 回答者 16:33:43 好,一起聊聊!

提问者 16:34:30 因为不同模块已经定了, 所以针对不同模块进行重构, 基本上这样 , 一个模块一个模块来重构 提问者 16:35:21 现在每个模块结构都一样 action service dao model 提问者 16:35:26 还有表 提问者 16:35:38 这个是老的 回答者 16:35:39 1、如何处理跨模块通信(API和SPI的问题)? 回答者 16:35:47 您接着说 回答者 16:36:01 我先把我的问题提出来,后面再找答案! 提问者 16:36:03 好 提问者 16:36:16 然后 谈一下重构 提问者 16:36:31 先把当前重构的模块 抽取出 它的领域模型 提问者 16:36:40 模型包含 业务属性和业务方法 提问者 16:36:56 建一个领域层 提问者 16:37:16 说白了就是加一个domain包, 把领域层对象放进去 回答者 16:37:45 2、如何组织领域模型(领域模型需要丰富的对象关系(对象图))? 3、是否还有原来的贫血模型? 提问者 16:38:49 我先说一下我的 新结构的思路, 然后 再找答案哈 回答者 16:38:54 好的! 提问者 16:38:56 嗯 回答者 16:39:04 我也是先写下来! 回答者 16:39:09 您尽管说 提问者 16:39:08 嗯 提问者 16:39:58 然后领域层有了 接下来在action里面 把 包含领域层业务的 老的service 剔除掉, 替换成领域对象的业务方法 提问者 16:40:48 如果一个领域模型的业务方法不能满足业务需要多个的话,建一个service 在service里面 调用 领域模型方法 提问者 16:41:19 action调用的service 方法 也都是多个领域模型方法的集合 提问者 16:41:39 里面涉及到数据库的增删改查, 因为是采用hibernate 提问者 16:42:20 老的model类 是hibernate的必需品, 针对的是表, 一张表 一个model类, 类似于数据对象 提问者 16:43:14 如果是查询 可以在DAO 查询后 , 对领域模型进行赋值, 如果是修改删除操作 也直接把领域对象传给DAO 让hibernate处理数据库操作 提问者 16:43:55 这个是我的思路, 其实 说白了 就是 把service的业务方法, 换成了 领域模型的方法。。 回答者 16:44:11 我来总结一下,您看对不对? 提问者 16:44:29 好的 回答者 16:46:05 领域层:领域模型、领域服务、仓储接口。 持久层:数据模型、仓储实现、DAO(Hibernate实现) 回答者 16:46:37 这两个层准备组织成这种模式吗? 提问者 16:46:46 有一点点差别 提问者 16:47:16 我的思路里 只有一个DAO 访问数据库

仓储接口和仓储实现 是没有的 提问者 16:47:30 因为我不大清楚 仓储接口和实现 的作用是? 回答者 16:48:33 或者我问个问题? 提问者 16:48:54 嗯 好 回答者 16:48:57 如何创建领域模型? 提问者 16:49:06 我的想法就是 直接new 了。。。 回答者 16:49:24 1、第一此创建 2、从数据库创建 回答者 16:49:41 引入仓储就是应对第2个场景。 提问者 16:49:53 比如 class UserAction { doXXX(){ UserDomain u = new UserDomain();

}

} 提问者 16:50:01 我的想法停留在这里。。。。 回答者 16:50:02 领域模型可能包含的层次比较多。 回答者 16:50:09 是一个大的对象图 回答者 16:50:22 这个职责需要统一在一个地方。 提问者 16:50:55 这个还是难以理解 提问者 16:51:11 比如 要统一在哪里创建领域对象吗 回答者 16:51:23 是的 回答者 16:51:27 1、第一此创建(工厂) 2、从数据库创建、保存(仓储) 提问者 16:51:37 比如 传统的编程语言 是无法躲开 new 实例对象的啊 回答者 16:51:45 我的建议是引入:工厂和仓储。 回答者 16:51:53 如果简单的对象可以new 回答者 16:52:10 考虑这样一个场景,我这边是有这样的例子的。 提问者 16:52:15 嗯! 回答者 16:53:08 考核方案 --评分规则列表 --系数规则列表 --周期规则表列 回答者 16:53:37 完成考核方案的启动,需要同时加载(创建)这些对象。 回答者 16:54:10 如果不引入仓储统一这种组装过程,每个开发人员都要重复这种组装过程。 回答者 16:54:41 class 考核方案仓储 { 考核方案 GetById(方案Id) } 回答者 16:55:08 为“根”领域对象引入仓储。 回答者 16:55:38 评分规则这些根对象之下的实体是不需要引入仓储的。

提问者 16:56:10 我理解一下 回答者 16:57:06 系统有三部分逻辑: 读取:渲染UI CUD:组装领域模型的过程 计算:执行和使用领域模型的过程 回答者 16:57:37 我的建议是将这三种职责分开,定义不同分层策略和组织方式。 提问者 16:58:16 针对这个业务 回答者 16:59:02 针对你目前的情况: 回答者 16:59:25 先为读取逻辑定义一个分层策略和组织方式。 提问者 17:00:08 我说说对考核这个业务的理解吧 回答者 17:00:11 你目前的数据模型之间有导航属性吗? 回答者 17:00:24 好的 提问者 17:00:33 考核方案 --评分规则列表 --系数规则列表 --周期规则表列 完成考核方案的启动,需要同时加载(创建)这些对象。

我的理解是 考核方案就是三个列表的显示吧 提问者 17:00:56 就是查询 评分规则、 系数规则、 周期规则 这三项 提问者 17:00:57 对吧 回答者 17:01:17 对 提问者 17:01:43 那么领域模型 会存在 评分、 系数 、 周期 三者 提问者 17:02:09 还有考核方案 这个是领域模型的根 回答者 17:02:13 考核方案有一个"计算逻辑",计算考核分数,内部计算使用 评分、 系数 提问者 17:03:09 就是 在 考核领域对象里面 计算 评分和系数 把最终的数据返回? 回答者 17:03:17 对 回答者 17:03:49 计算逻辑:需要创建一个考核方案,考核方案的计算过程需要:评分和系数 提问者 17:04:20 那评分和系数 算不算领域模型呢? 回答者 17:04:39 算 回答者 17:04:45 不是聚合根 回答者 17:04:47 你目前的数据模型之间有导航属性吗? 提问者 17:04:57 啥是导航性啊 回答者 17:05:11 User { Roles } 提问者 17:05:18 就是关联关系吗 回答者 17:05:22 对 提问者 17:05:25 一对多 多对多 提问者 17:05:26 有啊 提问者 17:06:11 然后继续哈 提问者 17:06:35 我拿考核系数 说我的思路吧 先从最小的说 回答者 17:06:38 这样你就有领域模型了 提问者 17:06:49 你看看我这个思路对不 回答者 17:07:18 你先说 提问者 17:08:42 考核方案,考核方案的计算过程需要:评分和系数 建立领域模型 class 考核方案{ 评分 p; 系数 x;

public int 计算考核方案(){ int result = 0 ; result += x.计算(); result += p.计算(); return result; } } 提问者 17:08:49 是这个意思吗 回答者 17:08:58 对 提问者 17:09:29 class 考核方案{ 评分 p; 系数 x;

public int 计算考核方案(){ int result = 0 ; p = new 评分; x = new 系数; result += x.计算(); result += p.计算(); return result; } } 提问者 17:09:46 p = new 评分; x = new 系数; 在方法体里面new出来领域对象的实例 回答者 17:10:35 这种不行吧!评分需要从数据库中加载的。 回答者 17:10:54 领域层:领域模型、IDAO、IRepository 。 持久层:DAOImp,RepositoryImp 回答者 17:11:00 新的思路 提问者 17:11:24 好的 问题出现了 我改进一下 你帮我看一下对不啊~ 回答者 17:11:35 好的 提问者 17:13:39 建立 评分DAO{ public 评分 读取评分(){ select * 。。。。 }

}

然后 在计算考核方案方法体里

class 考核方案{ 评分 p; 系数 x; 评分DAO dao; 系数DAO dao;

public int 计算考核方案(){ int result = 0 ; p = new 评分; x = new 系数; p = 评分DAO .查询评分(); x= 系数DAO .查询系数();

result += x.计算(); result += p.计算(); return result; } } 提问者 17:13:55 我目前的思路。。。 提问者 17:14:06 但是我觉得我这个思路不对。。 回答者 17:14:08 这个是服务,不是领域模型。 提问者 17:14:18 是啊 , 问题就在这里。。。。 提问者 17:14:22 不知道咋整了 回答者 17:14:26 CRUD的入口为IDAO 领域计算逻辑时需要加载领域对象,计算完需要持久化,这两种职责交给:IRepository 回答者 17:14:31 这样行不? 回答者 17:14:59 比如:如果系统不需要计算逻辑,只有CRUD,我没必要用DDD的。 回答者 17:15:33 如果除了CRDU之外,需要其它的“按钮”,我才引入DDD。 回答者 17:16:02 用户的逻辑很复杂,但是其创建过程就是CRUD。 回答者 17:16:24 至于其权限验证、等于认证,都是等CRUD完了,才能起作用的。 回答者 17:17:15 因此我觉得:CRUD和DDD同时使用才是信息系统开发的一种可行方式。 提问者 17:18:02 加载领域对象 的 含义 是指 从数据库查询数据并对领域对象赋值吧 回答者 17:18:19 因为你的数据对象已经有关系了 回答者 17:18:37 所以:你只需要按聚合来设计仓储即可。

回答者 17:18:52 比如: 回答者 17:19:18 User { Roles IsInRole(string roleName); } 提问者 17:19:50 我想想。。 回答者 17:20:09 需要的就是:划分聚合、识别聚合根、一个聚合设计一个仓储。 提问者 17:20:26 那 user 这个例子 user 是聚合跟吗 回答者 17:20:44 是的,这个例子很明显! 提问者 17:20:57 聚合跟的作用是啥? 回答者 17:21:17 拿那个考核方案为例: 提问者 17:21:20 嗯 回答者 17:21:42 评分规则必须隶属一个考核方案,单独加载出来没有意义。 回答者 17:22:03 划分聚合和划分模块一样 提问者 17:22:32 我想想 我应该如何改造刚才的代码 提问者 17:22:38 按照聚合的思路 回答者 17:22:49 一个聚合专注与完成一些功能内聚的任务。 回答者 17:23:04 还拿考核方案为例吗? 提问者 17:23:09 是啊 提问者 17:23:12 这个例子好! 回答者 17:23:25 我先写吧! 提问者 17:23:27 好! 提问者 17:23:46 似乎有点感觉了 回答者 17:23:59 首先是领域模型 考核方案 { 评分规则列表 系数规则列表 } 提问者 17:23:59 这个有一点像 对现实世界的抽象 回答者 17:24:16 这个模型Hibernate应该支持 提问者 17:24:31 嗯 典型的 一对多 回答者 17:24:57 I考核方案DAO I评分规则DAO I系数规则DAO 回答者 17:25:05 定义三个DAO,可以用泛型。 回答者 17:25:51 先不考虑计算之类的逻辑,有这些类,是不是足以完成CRUD之类的界面了? 提问者 17:26:50 是啊 这些 hibernate就完成了 回答者 17:27:15 现在有一个要求:开发一个“计算”按钮 回答者 17:27:48 为此:引入 I考核方案Repository 回答者 17:28:20 修改考核模型: 考核方案 { 评分规则列表 系数规则列表 计算(); } 回答者 17:28:34 只为聚合根引入仓储 提问者 17:29:05 嗯 考核方案就是 聚合根吗 回答者 17:29:10 是的

回答者 17:29:21 仓储也是有CRUD逻辑的 提问者 17:29:35 也就是说 在一个聚合里面 谁 被其他领域模型依赖 谁就是聚合的根? 回答者 17:30:21 可以这样理解,一个侧面。 回答者 17:30:35 我也是每个阶段的理解都不一样! 提问者 17:30:56 那 计算方法 的内容是如何编写的呢 回答者 17:31:24 评分规则列表 系数规则列表 这两个属性都已经被Hibernate加载在内存了,直接计算即可。 提问者 17:31:52 肯定是需要调什么东西来实例化 这两个列表的 回答者 17:32:05 Hibernate应该支持的 提问者 17:32:15 一般是这样 回答者 17:33:40 ORM都支持延时加载或立即加载! 回答者 17:33:50 有一个问题需要考虑 提问者 17:33:52 但是也需要使用API调用的 回答者 17:34:17 .net 平台不需要这样的。 提问者 17:34:21 比如 系数规则列表 是需要在DAO 中写一个queryList方法 ,在里面调用hibernate的API来查询的 回答者 17:34:43 Hibernate是不是可以开启代理模式 回答者 17:35:00 由代理自动完成延时加载 提问者 17:34:59 hibernate本身就是代理来做延迟加载的 回答者 17:35:32 只要能加载 提问者 17:35:46 虽然是延迟加载, 但是在加载考核方案以后, 手动调用get系数列表 才能加载的啊 回答者 17:35:47 这种加载逻辑:要写在RepositoryIml中。 回答者 17:36:11 IRepository定义在领域层。 提问者 17:36:19 延迟加载, 必须要先load出来考核方案, 才能延迟的得到系数列表 提问者 17:36:40 数据库查询的逻辑 ,需要写在RepositoryIml吗 回答者 17:36:42 可以定义两个保护的get 提问者 17:37:27 但是 这样会把 领域对象 和 hibernate绑定了。。。 回答者 17:37:46 职责分开是最重要的

提问者 17:37:56 因为要想让 考核方案类, 延迟加载 系数列表, 就必须配置在hibernate, 把其当成hibernate的model类。。。。 提问者 17:38:22 但是hibernate的model类 不是领域模型 那是表的映射啊 回答者 17:38:28 那,你就在RepositoryIml写加载逻辑。 回答者 17:38:42 领域模型是POJO 提问者 17:38:57 但是 我需要在 计算()方法体里面 new RepositoryIml 来调用 query方法啊 回答者 17:38:59 RepositoryHibernateIml 回答者 17:39:06 不用啊 回答者 17:39:27 我来写一下伪代码? 提问者 17:41:18 比如 我要加载系数列表 class RepositoryIml { public 系数列表 query系数列表(){ hibernateTemplate .load (系数列表); return 系数列表 } } 回答者 17:42:00 考核方案 { private 评分规则列别 评分规则列别 private 系数规则列别 系数规则列别

计算()//先省略 }

I考核方案仓储 { GetById(方案标识); }

考核方案仓储Hibernate实现 { GetById(方案标识) { //Hibernate实现 } } 提问者 17:42:16 考核方案 { 评分规则列表 系数规则列表 计算(){ RepositoryIml rrepositoryIml = new RepositoryIml(); 系数规则列表 = rrepositoryIml.query系数列表(); } } 回答者 17:42:40 Hibernate如何加载关联属性 回答者 17:43:15 有include之类的函数吧 回答者 17:43:19 忘记了 提问者 17:43:46 hibernate没, 不需要, 直接调用get方法就可以加载 回答者 17:44:05 仓储的实现,必须保证 加载的领域模型是一颗对象树。 回答者 17:44:17 关联关系都已经加载了 回答者 17:44:29 考核方案 { 评分规则列表 系数规则列表 计算(){ RepositoryIml rrepositoryIml = new RepositoryIml(); 系数规则列表 = rrepositoryIml.query系数列表(); } } 回答者 17:44:39 因此,你的这种写法是不需要的。 提问者 17:44:54 那应该怎么写啊 提问者 17:45:05 这么看来 仓储 好像就是 DAO啊 提问者 17:45:13 把DAO换了个名字。。 回答者 17:45:38 是这样的,仓储只面向聚合根,和引入了工作单元。 提问者 17:45:45 因为 写DAO的查询方法, 也一样会加载对象的值 回答者 17:45:49 我是这么理解的。 提问者 17:46:06 不过 好处是什么。。 提问者 17:46:14 那计算方法应该怎么写 提问者 17:46:42 因为 考核方案 的仓储 已经编写好了, 在哪里调用它呢RepositoryIml 提问者 17:46:57 刚才编写了一个RepositoryIml 提问者 17:47:02 这个东西的作用是 ? 回答者 17:47:03 计算(){ this. 评分规则列表.遍历 this.系数规则列表.遍历 } 提问者 17:47:20 但是RepositoryIml这个东西还是没用到啊 回答者 17:47:45 领域服务或应用层服务或控制器使用IRepository 回答者 17:47:56 RepositoryIml通过IOC注入 回答者 17:48:06 编译时不能依赖于:RepositoryIml 回答者 17:48:17 运行时注入:RepositoryIml 提问者 17:48:20 这个知道DAO 也这样 提问者 17:48:38 RepositoryIml 这个东西 跟DAO的区别是啥 有了RepositoryIml 还需要DAO做啥呢 回答者 17:49:02 DAO主要面线CRUD 回答者 17:49:21 Repository面向领域模型的使用场景 回答者 17:49:32 DAO面向领域模型的创建场景 回答者 17:49:44 我这边还考虑将Read给分离出来 提问者 17:49:52 但是CRUD不仅仅是创建 还包括删除修改和查询 提问者 17:50:04 领域模型的使用场景 的含义是? 提问者 17:50:25 领域模型的使用场景 具体到代码编写 是指什么? 回答者 17:50:54 比如判断某个用户是否拥有某个权限 回答者 17:51:04 这个是用户这个领域模型的使用场景 回答者 17:51:14 CURD中你不需要考虑的 提问者 17:51:18 也就是具体的业务? 回答者 17:51:19 引入认证服务 回答者 17:51:25 对 提问者 17:51:29 除了增删改查以外的业务? 回答者 17:51:39 我是这样定义的! 回答者 17:51:50 否则DDD很难实施的! 回答者 17:51:57 成本太大 提问者 17:52:01 但是除了增删改查的具体业务 是在领域模型里面体现的 提问者 17:52:12 为什么要在仓储里实现? 回答者 17:52:20 仓储是加载逻辑 回答者 17:52:31 实现还是在领域模型中啊 回答者 17:52:52 仓储也是CRUD,支持面向的是聚合根。

提问者 17:52:56 仓储是加载逻辑 意思是 仓储只负责查询? 回答者 17:53:16 计算逻辑和业务逻辑下载领域模型或领域服务中。 回答者 17:53:37 计算逻辑和业务逻辑写在领域模型或领域服务中。 提问者 17:53:47 也就是说 领域模型的业务方法 中 需要操作数据库的方法 需要调用 仓储? 提问者 17:54:46 比如所 这个例子 回答者 17:54:49 如果是聚合内可以直接引用的关联模型,不需要仓储了, 回答者 17:54:56 否则通过函数的方法注入 提问者 17:55:06 通过函数的方法注入的意思是? 提问者 17:55:20 在写代码的角度 什么是通过函数方法注入 回答者 17:55:22 计算(仓储接口) 提问者 17:55:30 作为参数传进去? 回答者 17:55:39 是的 回答者 17:55:48 或者引入服务类 提问者 17:56:02 那 传入的仓储接口 肯定是实例化了的 提问者 17:56:04 对吧 提问者 17:56:17 否则不会被调用 回答者 17:56:21 外围服务类包装一下 回答者 17:56:23 对 提问者 17:56:29 那是在哪里实例化的? 回答者 17:56:35 外围服务类 提问者 17:56:36 肯定有一个地方new出来的 提问者 17:56:42 外围的意思是 提问者 17:57:30 我觉得刚才那个考核方案的例子不错 提问者 17:57:39 我来实现一下完整的代码 回答者 17:57:52 计算服务 { 计算服务(根仓储接口,依赖的仓储接口); 计算(标识) { 根仓储接口.get(标识).计算(依赖的仓储接口) } } 回答者 17:57:54 好的 提问者 17:57:53 完整的流程 回答者 17:58:35 最终都交给IOC去实例 提问者 17:59:48 考核方案 { 评分规则列表 系数规则列表 计算(RepositoryIml rrepositoryIml){ 系数规则列表 = rrepositoryIml).query系数列表(); /// } } 提问者 17:59:51

考核方案service{ public 考核方案 计算(){ RepositoryIml rrepositoryIml = new RepositoryIml(); 考核方案领域模型 k = new 考核方案领域模型(); return k.计算(rrepositoryIml); }

} 回答者 18:00:40 你用IOC容器,项目中没使用接口吗? 提问者 18:00:47 好的 我调整一下 提问者 18:01:17 考核方案service{ IRepository rrepository; public 考核方案 计算(){ 考核方案领域模型 k = new 考核方案领域模型(); return k.计算(rrepository); }

} 回答者 18:01:32 考核方案领域模型 k = new 考核方案领域模型(); 提问者 18:01:49 领域模型 需要使用IOC 注入到 service里面? 回答者 18:01:53 这个应当时通过“考核方案领仓储”获取的吧 提问者 18:02:13 我再改一下 提问者 18:02:48 考核方案service{ IRepository rrepository; public 考核方案 计算(){ 考核方案领域模型 k = rrepository. 获得考核方案(); return k.计算(rrepository); }

} 提问者 18:02:51 这个对骂 提问者 18:02:56 对吗。。 回答者 18:03:09 对 回答者 18:03:11 有一个问题 提问者 18:03:13 嗯 回答者 18:03:46 考核方案领域模型 既然通过 仓储 获取了,其关联的导航属性就应该已经有值了。 提问者 18:04:28 仓储 不仅仅能获取到 领域模型 还要获取他关联的值吗 提问者 18:04:40 比如 我不用hibernate 回答者 18:04:44 对 回答者 18:04:58 仓储面向的是一个聚合 提问者 18:04:58 但是 领域模型 并不一定要用hibernate实现啊 回答者 18:05:15 自己实现JDO也要这样做的。 提问者 18:05:23 如果不是ORM框架? 提问者 18:05:30 或者仅仅使用基本查询语句? 提问者 18:05:32 JDBC? 提问者 18:05:40 这个东西跟框架无关吧 回答者 18:06:17 也在仓储实现中实现加载逻辑 提问者 18:06:18

根仓储接口.get(标识) 一般来说 只能查询到某个对象 回答者 18:06:49 除了根对象之外的实体,不能有仓储实现。 提问者 18:07:01 为什么? 提问者 18:07:09 仓储实现实体? 回答者 18:07:12 1、DDD是这样定义的。

提问者 18:07:25 仓储实现实体 的含义是? 回答者 18:08:11 DDD有三个概念:实体、仓储、聚合根 回答者 18:08:23 还有一个:聚合 提问者 18:08:29 比如说 考核方案 { 评分规则列表 系数规则列表 } 提问者 18:08:38 我只能有一个考核方案仓储? 回答者 18:08:46 对 提问者 18:09:09 然后我要查询考核方案对象时, 需要把评分规则和系数 都给查出来?? 回答者 18:09:22 是的,因为计算逻辑需要他们。 回答者 18:09:35 单独查询评分规则也没有意义。 回答者 18:09:47 否则评分规则就可以作为独立的聚合 提问者 18:10:26 那 query考核方案() 方法就应该写成

query考核方案(String id){ 1 查询考核方案 2 查询系数 3 查询评分 4 组装考核方案 } 回答者 18:10:51 对,不过很少见使用DDD,不用ORM的。 回答者 18:11:03 cqrs例外 回答者 18:11:35 那个架构下有三个数据库:eventstore、快照store、readstore 提问者 18:11:34 那 我感觉 领域模型 倒真 十分类似于 hibernate的 数据库表映射类了!! 提问者 18:11:52 只不过多了几个业务方法。。 回答者 18:12:09 我目前的认识水平也是如此! 回答者 18:12:25 职责更分离了,内聚性好一些。 提问者 18:12:42 而且 刚才 service 这个 , 如果没有service怎么办 回答者 18:12:43 纯DDD是没有DAO的。 提问者 18:12:49 如果不需要service 怎么办? 提问者 18:13:16 比如 比如 直接在action中 调用 领域模型的业务方法。。。 提问者 18:13:37 原来是action 注入service

现在一些业务被领域模型实现了 提问者 18:13:50 action 难道要注入 领域模型类吗 回答者 18:13:51 service还是需要的 回答者 18:14:10 领域模型是组织业务逻辑 回答者 18:14:22 service封装业务逻辑 回答者 18:14:27 事务也可以在此控制 提问者 18:14:35 组织业务 跟封装业务 的区别是? 提问者 18:14:51 代码层面上面 什么叫组织 ? 回答者 18:15:07 pojo in action 这本书是这么说的 回答者 18:15:40 组织是业务逻辑真正执行的地方,粒度较细。 回答者 18:16:09 组织:面向用例进行设计,粗粒度、发布事件、发送邮件、处理事务。 回答者 18:17:23 这个层:可以采用事务脚本或者命令模式 提问者 18:17:28 可是 这么一来 架构上面 仅仅是 把hibernate的mdel 加上业务方法 然后 加个 repository层 处理一部分数据库操作

实际上还是包的改变而已啊 回答者 18:18:05 主要看看:职责是不是更明确了,维护性是不是更好了。 回答者 18:18:23 如果DDD不能带来以上好处,还是不用为好! 提问者 18:18:36 架构上面 仅仅是 把hibernate的mdel 加上业务方法 然后 加个 repository层 处理一部分数据库操作

这个是DDD吗 回答者 18:18:39 我使用DDD,会按照上面咱们讨论的执行。 回答者 18:18:50 加上read分离 回答者 18:19:01 是DDD了 提问者 18:19:03 但是 我看到的 大部分都是概念化的东西 回答者 18:19:16 如果引入:工作单元、规约 提问者 18:19:17 我们讨论 落到代码层面实处的 不多吧 提问者 18:19:36 其实 那些概念层面的 我都不关心 提问者 18:19:48 到底 体现在代码上 跟贫血模式的区别 回答者 18:19:50 DDD:实体、根对象、工厂、仓储、规约、服务 回答者 18:19:53 就这些东 提问者 18:20:00 这些还都是概念化的。。。 提问者 18:20:17 但是这些东西落到代码层面怎么写? 提问者 18:20:21 伪代码 回答者 18:20:35 职责更清晰了,DDD重在减少了设计和开发的鸿沟。 提问者 18:20:38 不是。。。 提问者 18:20:46 这些好处 怎么说都可以 提问者 18:20:52 但是我们最终是要编写代码的 提问者 18:20:58 落到代码 落实 回答者 18:21:01 要吃饭了,明天接着聊。 提问者 18:21:03 好的。。 回答者 18:21:09 明天咱们落实代码 提问者 18:21:13 好 [该贴被zouruixin于2012-12-18 18:39修改过]

承蒙厚爱,我大概看了一下你们的对话,太多,没有看完。

我直接和你这样说:

如果你还是使用传统JavaEE或Spring + Hibernate这样的框架,是无法实现DDD原始意图的,这个DDD创始人Eric Vans已经说过,可在本站查询到。

要实现DDD原始意图,必须CQRS+Event Sourcing。

提供基于Jdonframework实现的CQRS 源码,ES部分稍微拓展一下即可:Robot.rar,文章见DDD DCI和领域事件

或者选用新的编程语言Scala,文章:Scala的event-sourced和CQRS案例代码

2012-12-18 19:10 "@banq"的内容
提供基于Jdonframework实现的CQRS 源码,ES部分稍微拓展一下即可:Robot.rar ...

代码下来了 可是在领域层有一个@model注解, 这样领域层代码貌似就依赖于jdonframework了吧 领域层不是可以移植到任意系统的吗

2012-12-18 19:53 "@zouruixin"的内容
领域层有一个@model注解, 这样领域层代码貌似就依赖于Jdonframework了吧 领域层不是可以移植到任意系统的吗 ...

完整案例下载见这里

用注解是目前所有依赖中最松耦合的方式,比extend AggragateRoot或Scala中继承一个Actor要对代码侵入性小。

你也可以看看:Axon框架的AxonTrader案例。不过我个人认为复杂性不低。

建议你还是先使用Spring+Hibernate做新项目吧,不要贸然采取超前技术,特别是你没有把握的情况下。

其实 infoQ 有一篇翻译文章 专门描述了一个老外用 spring hibernate 进行DDD的例子 ,不过例子不太全 。 在这边 又是另一种概念 所以现在比较迷糊

2012-12-20 09:57 "@zouruixin"的内容
不过例子不太全 ...

关键就在这里啊,他一全下来就漏丑了,INFOQ之类媒体显式网站和Jdon这样隐式网站区别你应该是知道的。

显式的媒体,隐式有1分,他能叫成10分啊。千万别当真,当成IT娱乐看看。 [该贴被banq于2012-12-20 11:45修改过]

软件这东西不需要赶潮流,也不需要特别创新。这里讨论了一些新的甚至是边缘的思想,但是实践过程中要量力而行。 写一个能动的软件即使再不好看也是能动,写一个不能动的软件即使再有思想再精致也是不能动。 尤其在商业开发中推荐边实践边探索,彻底想明白了再做,切忌一哄而上。

2012-12-25 15:08 "@IceQi"的内容
软件这东西不需要赶潮流,也不需要特别创新。这里讨论了一些新的甚至是边缘的思想,但是实践过程中要量力而行。 写一个能动的软件即使再不好看也是能动,写一个不能动的软件即使再有思想再精致也是不能动。 尤其在商业开发中推荐边实践边探索,彻底想明白了 ...

很不幸的是,只要跟金钱扯上关系,任何技术都失去研究价值,因为研究是一种无回报的投资,有规模的公司才有机会,一般向的就别想了。

所以,想研究学习新东西,停下金钱思想,问自己兴趣,感兴趣就学,不感就放弃。商业开发中边实践边探索是一种奢求。

软件、技术最好跟潮流(从很多方面说都应该,为什么?思考一下潮流是怎样形成的),可以的话走走创新路。但商业开发的不是软件或技术,而是商品,不能成为商品的软件,能动都没用。

脱离了金钱,不能动的软件也有价值——失败只是另一种成功。正因为这样,jdon上讨论的技术(或者说学术)才能够摆脱“卖不出有屁用”的魔咒。