首先感谢@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 是的