开始DDD

如何开始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)