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

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

3
zouruixin
2012-12-18 18:35
回答者 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

zouruixin
2012-12-18 18:38
根仓储接口.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修改过]

banq
2012-12-18 19:10
承蒙厚爱,我大概看了一下你们的对话,太多,没有看完。

我直接和你这样说:

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

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

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

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

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


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

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


完整案例下载见这里

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

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

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

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

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


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

显式的媒体,隐式有1分,他能叫成10分啊。千万别当真,当成IT娱乐看看。

[该贴被banq于2012-12-20 11:45修改过]

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

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


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

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

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

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

猜你喜欢