如何开始DDD(完)

连续写了两篇文章,这一篇我想是序的完结篇了。结合用户注册的例子再将他简单丰富一下。在这里只添加一个简单需求,就是用户注册成功后给用户发一封邮件。补充一下之前的代码

public class DomainService
{
public void Register(User user)
{
if (_userRepository.IsLoginIdExist(user.LoginId)) {
throw new Exception("用户名已存在");
} _userRepository.Add(user);
MailService.Send(user.Email, "邮件内容");
}
}

上面的代码是存在一点问题的,了解DDD的人都知道,此时user并没有持久化或者持久化是否成功是不确定的,假设此时持久化user失败了,但邮件却发送出去了,这显然不是我们想要的结果。怎么办?我能想到的是两种办法。

第一种:创建一个发送邮件的model。

public class MailMessage
{
public MailMessage(string receiver, string content)
{
this.Receiver = receiver;
this.Content = content;
} public string Receiver { get; private set; }
public string Content { get; private set; }
} public class DomainService
{
public void Register(User user)
{
if (_userRepository.IsLoginIdExist(user.LoginId)) {
throw new Exception("用户名已存在");
} _userRepository.Add(user);
_mailRepository.Add(new MailMessage(user.Email, "邮件内容"));
}
}

在添加用户的时候同时添加一条邮件消息,这样他们将会在同一个事务中,要么一起成功,要么一起失败。最后再设计个计划任务,从邮件记录表中取出记录依次发送邮件,发送成功的可以标记一下,至于怎么做就不细讲了。

第二种:就是这一篇我要介绍的使用事件。

public class UserRegistered : IEvent
{
public UserRegistered(string name, string email)
{
this.Name = name;
this.Email = email;
} public string Name { get; private set; }
public string Email { get; private set; }
} public class UserRegisteredHandler : IEventHandler<UserRegistered>
{
public void Handle(UserRegistered @event)
{
//TODO.. 发送邮件
}
} public class User : IEventPublisher
{
private readonly IList<IEvent> _uncommittedEvents = new List<IEvent>();
IEnumerable<IEvent> IEventPublisher.Events
{
get { return this._uncommittedEvents; }
} public User(string name, string password, string email)
{
this.Name = name;
this.Password = password;
this.Email = email; _uncommittedEvents.Add(new UserRegistered(name, email));
} public string Name { get; private set; }
public string Password { get; private set; }
public string Email { get; private set; }
}

这样用户注册会产生一个事件。持久化成功后,会将事件发布出去,这样EventBus就会监听并处理此事件。上面的代码可能阅读理解起来不是那么的直白,具体的实现起来也并非就这么简单,只是提出一种方法。具体实现我的开源代码里也有相关例子http://thinknet.codeplex.com

总结

以上三篇文章我也主要是从写代码的角度去介绍如何DDD,强调一下我不是在教你如何写代码,只是为了展示用DDD如何实现,领域里的模型更应该能表达业务,他的价值更并不仅于此。而且以上的描述不一定完全正确,也不是告诉你一定要如何做,这也需要你自己的思考,如果有不对的地方欢迎你的指正,毕竟DDD我在学习过程中,也能从中受益。

如果我们过多的精力花在如何写代码上,可能是收集的工具类库还不强大,或者是还没有一个能够方便快捷开发的框架,当然一个好的框架带来的好处会很多。一个框架终究是有办法和技术能力去实现完成的,但是如何分析和理解业务,然后从中挖掘出便于阅读和表达业务的模型确定一件不容易的事情,他并不是通过某种技术办法就能实现的。所以我个人觉得设计模型,划分界限上下文是需要不断的积累领域业务知识才能做到的。

“领域驱动设计”和“实现领域驱动”这两本书应该是最经典的了,知识点也很多,阅读此书你会得到更多的收获!

随笔分类 - ThinkNet

一款帮助开发DDD+CQRS风格的应用框架
摘要: 连续写了两篇文章,这一篇我想是序的完结篇了。结合用户注册的例子再将他简单丰富一下。在这里只添加一个简单需求,就是用户注册成功后给用户发一封邮件。补充一下之前的代码public class DomainService{ public void Register(User user) { ...阅读全文
posted @ 2014-08-06 09:29 young.han 阅读(463) | 评论 (15) 编辑
摘要: 上一篇针对用户注册案例简单介绍了如何使用 DDD,接下来我将继续针对这个例子做一下补充。先将User模型丰富起来,因为目前看上去他和贫血模型还没有啥大的区别。首先还是由领域专家来说明业务,他提出了用户注册成功后需要完善个人信息,这些信息包括姓名、生日、手机号。还需要用户提供一些联系信息,如地址,邮编...阅读全文
posted @ 2014-08-05 11:11 young.han 阅读(630) | 评论 (11) 编辑
摘要: 在开始DDD之前,你需要了解DDD的一些基础知识,聚合(AggregateRoot)、实体(Entity)、值对象(ValueObject),工厂(Factory),仓储(Repository)和领域服务(DomainService)。在这里值对象有区别于C#的值类型,请不要将两者混淆,一开始我也范...阅读全文
posted @ 2014-08-04 14:31 young.han 阅读(214) | 评论 (4) 编辑
摘要: 经过一段时间的DDD学习,第一个开源框架终于初步完成了,我为他命名为ThinkNet。之前或许你听过ThinkPHP,没错,虽然我对php没有过多的掌握,但是借助thinkphp,我也能开发一个web应用程序。所以我也想写一个框架能够帮助快速开发基于DDD考虑的应用程序。首先要感谢园子里的dax.n...阅读全文
 
分类: ThinkNet
标签: DDD

开始DDD的更多相关文章

  1. 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑

    阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...

  2. 如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成

    阅读目录 前言 建模 实现 结语 一.前言 前面几篇已经实现了一个基本的购买+售价计算的过程,这次再让售价丰满一些,增加一个会员价的概念.会员价在现在的主流电商中,是一个不大常见的模式,其带来的问题是 ...

  3. 如何一步一步用DDD设计一个电商网站(十)—— 一个完整的购物车

     阅读目录 前言 回顾 梳理 实现 结语 一.前言 之前的文章中已经涉及到了购买商品加入购物车,购物车内购物项的金额计算等功能.本篇准备把剩下的购物车的基本概念一次处理完. 二.回顾 在动手之前我对之 ...

  4. 如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念

    一.前言     DDD(领域驱动设计)的一些介绍网上资料很多,这里就不继续描述了.自己使用领域驱动设计摸滚打爬也有2年多的时间,出于对知识的总结和分享,也是对自我理解的一个公开检验,介于博客园这个平 ...

  5. 如何一步一步用DDD设计一个电商网站(七)—— 实现售价上下文

    阅读目录 前言 明确业务细节 建模 实现 结语 一.前言 上一篇我们已经确立的购买上下文和销售上下文的交互方式,传送门在此:http://www.cnblogs.com/Zachary-Fan/p/D ...

  6. 如何一步一步用DDD设计一个电商网站(六)—— 给购物车加点料,集成售价上下文

    阅读目录 前言 如何在一个项目中实现多个上下文的业务 售价上下文与购买上下文的集成 结语 一.前言 前几篇已经实现了一个最简单的购买过程,这次开始往这个过程中增加一些东西.比如促销.会员价等,在我们的 ...

  7. 如何一步一步用DDD设计一个电商网站(五)—— 停下脚步,重新出发

    阅读目录 前言 单元测试 纠正错误,重新出发 结语 一.前言 实际编码已经写了2篇了,在这过程中非常感谢有听到观点不同的声音,借着这个契机,今天这篇就把大家提出的建议一个个的过一遍,重新整理,重新出发 ...

  8. 如何一步一步用DDD设计一个电商网站(四)—— 把商品卖给用户

    阅读目录 前言 怎么卖 领域服务的使用 回到现实 结语 一.前言 上篇中我们讲述了“把商品卖给用户”中的商品和用户的初步设计.现在把剩余的“卖”这个动作给做了.这里提醒一下,正常情况下,我们的每一步业 ...

  9. 如何一步一步用DDD设计一个电商网站(三)—— 初涉核心域

    一.前言 结合我们本次系列的第一篇博文中提到的上下文映射图(传送门:如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念),得知我们这个电商网站的核心域就是销售子域.因为电子商务是以信息网络 ...

  10. 如何一步一步用DDD设计一个电商网站(二)—— 项目架构

    阅读目录 前言 六边形架构 终于开始建项目了 DDD中的3个臭皮匠 CQRS(Command Query Responsibility Segregation) 结语 一.前言 上一篇我们讲了DDD的 ...

随机推荐

  1. IP地址解析

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.N ...

  2. ios7 JavaScriptCore.framework

    曾经想要oc调用js代码通常是通过uiwebview的stringByEvaluatingJavaScriptFromString方法,或是直接使用JavaScriptCore引擎,比如https:/ ...

  3. POJ 1113 || HDU 1348: wall(凸包问题)

    传送门: POJ:点击打开链接 HDU:点击打开链接 以下是POJ上的题: Wall Time Limit: 1000MS   Memory Limit: 10000K Total Submissio ...

  4. SPOJ 375 树链剖分

    SPOJ太慢了,SPOJ太慢了, 题意:给定n(n<=10000)个节点的树,每条边有边权,有两种操作:1.修改某条变的边权:2.查询u,v之间路径上的最大边权. 分析:树链剖分入门题,看这里: ...

  5. 一旦rhel5.8造成只读文件系统ORA-00354: corrupt redo log block header

    一旦rhel5.8造成只读文件系统ORA-00354: corrupt redo log block header Wed Jun 03 03:31:24 CST 2015 Thread 1 adva ...

  6. HDU ACM 1007 Quoit Design 分而治之的方法,最近点

    意甲冠军:给n坐标点.半一对点之间的距离所需的距离最近. 分析:分而治之的方法,最近点. #include<iostream> #include<algorithm> #inc ...

  7. 面向对象三大特征之多态——Java笔记(七)

    多态:     同一个实体同时具有多种形式     编译时的类型有声明该变量时使用的类型决定,运行时的类型有实际赋值给变量的对象决定     如果编译时类型和运行时类型不同,就出现多态 例: clas ...

  8. js 正则学习小记之NFA引擎

    原文:js 正则学习小记之NFA引擎 之前一直认为自己正则还不错,在看 次碳酸钴,Barret Lee 等大神都把正则玩的出神入化后发现我只是个战五渣.  求抱大腿,求大神调教. 之前大致有个印象,正 ...

  9. 什么时候rootViewController至tabbarController时刻,控制屏幕旋转法

    于ios6后,ios系统改变了屏幕旋转的方法,假设您想将屏幕旋转法,在需求rootvc里面制备,例如 UIViewController *viewCtrl = [[UIViewController a ...

  10. mac_Mac item2常用快捷键

    整理使用 iTerm 2 过程中得常用快捷键,Mac 原来自带的终端工具 Terminal 不好用是出了名的,虽然最近几个版本苹果稍微做了些优化,功能上,可用性方面增强不少,无奈有个更好用的 Iter ...