banq
2012-12-14 15:26

带来的思维改变,我们考虑聚合根不再聚焦在字段属性上,而是职责 方法和行为上。

对于聚合根中的字段,我们只需要那些能够改变业务方法行为的字段(banq注:状态,只有状态字段能改变业务行为),其他数据都被归纳入事件对象中。

在Match类中,是否结束这种状态对业务行为影响大,因此,代码改变最后如下:


banq
2012-12-14 15:38

最后,我们和传统编程思路对比一下:

传统思路第一步是考虑数据,将数据从行为中分离,然后将数据建模成数据库表结构Schema,这实际是企业的Turbo Pascal。

所以,问题关键是:首先考虑什么?

首先考虑的应该是语言language,也就是统一语言,将统一语言用在代码中,考虑我们的模型能够做什么?然后开始暴露其行为,行为才联系到数据,有行为才有数据(banq注:而不是从数据倒退行为)。

我们总是问自己:

为什么?它做什么?它的职责应该干什么?

这样,我们自然有了分离关注,有了CQRS。

对于CQRS的写操作:我们考虑的是,这样功能函数能够改变系统的哪些状态呢?

对于CQRS的读操作:我们考虑的是:我们在什么地方展示给用户什么数据视图?

那么,自然地事件将被引入:

领域中发生了什么事件;

什么状态被改变;

事件也可以用作持久机制。

可以还原整个历史。

最后强调:考虑业务过程而不是数据。

业务过程看上去是什么?怎么取名,有哪些行为参与改变了。

这样我们才站在冰山之顶:(全文完)


mistbow
2012-12-14 17:52

这篇文章太宝贵了

加上代码,对概念的理解更加深入了

感谢banq老师的分享

[该贴被mistbow于2013-09-18 12:48修改过]

[该贴被mistbow于2015-09-15 16:37修改过]

rejoady
2012-12-15 01:38

看完以后是觉得思路清晰了,不过还是有几点疑问:

1、按照DCI,这里比赛是否应该是一个场景,而球队是领域对象。

2、如果队伍设计成值对象,那就是不可变的,假如系统那天新增一个需求,客户需要知道整场比赛的队员情况,那球队这个对象的状态就会改变了,这里扩展需求是否会成为一个问题?

3、关于分数,分数应该是由进球这个事件产生的,而进球这个事件应该由谁来触发呢?

flyzb
2012-12-16 23:29

2012-12-15 01:38 "@rejoady"的内容
按照DCI,这里比赛是否应该是一个场景,而球队是领域对象。 ...

同意rejoady的看法,因为这个案例讲的比赛。那么试想一个场景,如果一个球队请你去帮他们设计一个管理软件,主要是解决“训练和比赛”的业务管理。如果按照上文的思路,球队的业务行为可能会被分割在“训练”和“比赛”中,那从DDD的角度看,又该如何设计呢?希望banq可以讨论一下思路。

猜你喜欢