連續寫了兩篇文章,這一篇我想是序的完結篇了。結合用戶注冊的例子再將他簡單豐富一下。在這里只添加一個簡單需求,就是用戶注冊成功后給用戶發一封郵件。補充一下之前的代碼
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就會監聽并處理此事件。上面的代碼可能閱讀理解起來不是那么的直白,具體的實現起來也并非就這么簡單,只是提出一種方法。具體實現我的開源代碼里也有相關例子https://github.com/imyounghan/thinknet
?
總結
以上三篇文章我也主要是從寫代碼的角度去介紹如何DDD,強調一下我不是在教你如何寫代碼,只是為了展示用DDD如何實現,領域里的模型更應該能表達業務,他的價值更并不僅于此。而且以上的描述不一定完全正確,也不是告訴你一定要如何做,這也需要你自己的思考,如果有不對的地方歡迎你的指正,畢竟DDD我在學習過程中,也能從中受益。
如果我們過多的精力花在如何寫代碼上,可能是收集的工具類庫還不強大,或者是還沒有一個能夠方便快捷開發的框架,當然一個好的框架帶來的好處會很多。一個框架終究是有辦法和技術能力去實現完成的,但是如何分析和理解業務,然后從中挖掘出便于閱讀和表達業務的模型確定一件不容易的事情,他并不是通過某種技術辦法就能實現的。所以我個人覺得設計模型,劃分界限上下文是需要不斷的積累領域業務知識才能做到的。
“領域驅動設計”和“實現領域驅動”這兩本書應該是最經典的了,知識點也很多,閱讀此書你會得到更多的收獲!
?