另外, 为了能让大家对我有一个更加具体的了解, 我也特地按照flyzb的思想设计了一个基于领域事件和DDD的架构.

该架构的核心思想是:

1. 领域模型好比是一个实心的圆球,圆球的表层就是领域服务(Domain Service),圆球内部由各个相互平等的,没有相互依赖的,通过事件消息完成相互协作的领域对象组成;
2. 领域模型应该依赖于一个中央事件处理器,该处理器负责统一协调领域模型的各种动作;具体地说就是该处理器能够智能的知道任何一个领域事件该如何处理,也就是说它知道该调用哪些事件响应者完成各自的响应;
3. 关于领域服务,应该是非常薄的一层,它的职责非常简单,就是生成领域事件,然后让事件处理器去发布领域事件,仅此而已;
4. 关于领域对象,每个领域对象主要做两件事情:一:在需要的时候生成领域事件,然后让事件处理器发布该领域事件;二:响应并处理一些它所关心并能单独处理的领域事件;
5. 领域模型应该处在正在应用的中心位置,因为它包含了整个应用的所有业务逻辑,包括流程控制逻辑和业务逻辑。任何其他的东西比如数据持久层、应用层、表现层都只是一些辅助的东西。比如数据持久层只是用来将领域模型的任何修改持久化到某种数据存储介质如数据库,应用层只是用来将领域模型做进一步封装(Facade),它提供面向用户操作的各种应用接口供表现层使用,应用层中所有接口可以分为两类:1)调用领域模型实现,一般是行为型操作(ADD、Update、Delete、或其任意组合);2)调用查询服务(该查询服务完全和领域模型无关)提供各种查询功能;也就是说在我看来我们应该应用CQRS的思想来实现应用层。最后,表现层其实和领域模型没有任何关系,它应该需要使用应用层即可。

总结:基于上面的思想,一个完整的领域模型由三个要素组成:领域服务+领域对象+领域事件。然后,为了能让这三个要素能协调工作,还需要借助一个中央事件处理器来完成统一协调的工作。另外,领域模型处于整个应用的中心,其他任何东西都只是作为辅助产品将该中心从各种角度进行扩展以满足用户需要;或者实现持久化目的,以便整个领域模型的状态可以被保存和恢复。

架构源代码为:
http://files.cnblogs.com/netfocus/EventBasedDDDExample.rar

希望能得到大家的意见和建议.

摘录

1)方向明确,就是要有自己的积累,要有自己的“东西”;
2)要有一种希望通过这种自己不断积累下来的“东西”来不断简化自己的工作的想法;
3)遇到任何问题,要努力去思考并抽象问题的实质,并用机器可以认识的语言去实现一种你认为好的解决方案;

在楼主博客中看到这段话,顶下,呵呵!

那就再引用一段我以前写的话分享给大家, 呵呵:

我觉得很多知识,如C#、OO、设计模式、DI、IOC、DDD、EDA、AOP等,都很重要,但不见得你这些东西都懂了就会写出很好的“东西”了。这只能说明你对这些东西熟悉或了解了,但并不代表你遇到问题时就能灵活运用这些知识; 所以,最重要的是要学会独立思考,要在思考中敢于用自己认为好的方式来实现自己所遇到的问题,而不要每次都借助于别人的所谓的优秀的框架,我觉得只有这样自己才能够真正提高。虽然当时你自己认为好的东西在别人看来并不那么好,并且在过段时间之后,你自己也许也会否定当初的设计,但那不正恰恰说明你进步了吗?所以,只要你坚持不懈,每次都用自己的思想来解决你所遇到的问题,那你提高的就会比别人都快。当然在这个过程中,我们也需要积极的学习别人优秀的知识,学习他们的设计思想,让你自己的思想来源可以更丰富。

这儿好凄凉啊, 发贴这么久也没有人回复. 太让人失望了.

2011年01月26日 12:04 "tangxuehua"的内容
要学会独立思考 ...

对的,这个是关键,我自己也在写“无侵入的持久模块”(只需告诉需要持久的实体),所以也感触很深。独立思考可以让我们思维系统完整、完善、精益求精,加上不断地实践,可以让自己的思考内容得以实现与验证,同时建立自信,最终良性循环。我们平时都说实践很重要,但也忽视了独立思考的重要性。完整的思维系统,呵呵,知其然,且知其所以然。

呵呵, 终于有人出现了.
那我就趁机问两个问题吧.

经典的企业应用系统会分为4层:UI层+应用层+领域层+基础层
其中领域层是存放业务逻辑的地方,我们可以用很多方式来组织业务逻辑,比如用事务脚本,也可以用DDD,等等.
假如我现在用DDD的方式,然后我可能希望用领域事件来将各个领域对象之间的依赖解偶.

那么我的问题是:
1) 创建了一个领域对象, 需要告诉别人该领域对象被创建了, 这个告诉或者说通知的职责该由谁来做? 是领域对象自己的构造函数的最后一行, 还是在应用层做? 还是在其他地方?
2) 领域对象是否应该有删除自己的职责? 比如account.Delete();account是一个领域对象. 如果没有, 那应该由谁去删除某个领域对象呢?

我的办法:

系统中有一个事件总线,领域对象的产生犹如婴儿呱呱坠地,用哭声宣布它来到了这个世界,这个声音来自对象内部,所以可在构造函数最后一行,但是我们DDD系统,大多数时候有一个工厂来创建对象的,工厂创建完向事件总线砸一个事件过去,这个事件等于婴儿的哭声。

领域对象的删除是否是基础设施层?删除是业务逻辑吗?对象有自杀和他杀两种情况,再次引入事件,他杀就直接向基础设施发指令过去,同时把内存中的模型清除,自杀的现实情况是找要害之处形成致命一击,可在对象中设置这个要害,一旦契约到达这个条件,发事件到基础设施层。

代码可见jdonmvc+jdon实现的CRUD,http://code.google.com/p/jdonmvc/downloads/list

呵呵,关于account.Delete()这个跟我说过的password思维是一样的,注意分析:在领域中存在的是用户实体,而非帐号。那么帐号到底是哪里来的呢?其实我们可以去看看网游的登录机制:输入帐号密码,创建或者选择角色,然后进入网游世界。在这里可以看出帐号和密码不是游戏角色(用户实体)的属性,而是系统级别的服务,在于唤醒实体,只有唤醒了才有一些列的业务。先撇开持久模块,实体是一直在内存中的(设想内存足够大),当用户没有登录,则是一直在被动状态(不是沉睡,可理解为在发呆),不会自己干事,别人有事要他加入时,才会做事。如论坛中,版主对某离线会员进行加分行为时。但现实是残酷的——内存不够用,所以需要持久模块,避免领域实体消失。持久化,就是让领域实体进入沉睡状态——记录当前实体状态,当唤醒时,重新进入内存中。
[该贴被SpeedVan于2011-01-26 16:39修改过]

写的挺不错的 我从你的例子中也获得了很多的启发

但是你例子中的事件驱动好像存在一些问题:

public class BankAccountService
{
private void Handle(TransferEvent evnt)
{
//触发事件通知源帐号减去转账金额, 目标帐号加上转账金额
EventProcesser.ProcessEvent(
new DecreaseAccountMoneyEvent
{
BankAccountId = evnt.FromBankAccountId,
MoneyAmount = evnt.MoneyAmount
},
new IncreaseAccountMoneyEvent
{
BankAccountId = evnt.ToBankAccountId,
MoneyAmount = evnt.MoneyAmount
});

//创建一笔转账记录
TransferHistory transferHistory = new TransferHistory(evnt.FromBankAccountId, evnt.ToBankAccountId, evnt.MoneyAmount, DateTime.Now);
Repository.Add(transferHistory);

//为源帐号关联该转账记录, 目标帐号关联该转账记录
EventProcesser.ProcessEvent(
new AddAccountTransferHistoryEvent
{
BankAccountId = evnt.FromBankAccountId,
TransferHistory = transferHistory
},
new AddAccountTransferHistoryEvent
{
BankAccountId = evnt.ToBankAccountId,
TransferHistory = transferHistory
});
}
}

以上是你例子中的 转账服务的实现 这里存在的一个问题是:service不保存历史信息(也不能保存 DDD中是这样说的) 虽然表面上你通过事件把进出账户的耦合降低了,但是实际情况是 这个操作的结果是和2个账号的操作结果紧密关联的 其中一个出错会导致整个操作的回滚 我现在把事件交由事件处理器之后 原先的操作状态信息完全丢失了 无法完成回滚(异步环境下)
[该贴被dArtist于2011-04-07 11:30修改过]