如何開始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就會監聽並處理此事件。上面的代碼可能閱讀理解起來不是那么的直白,具體的實現起來也並非就這么簡單,只是提出一種方法。具體實現我的開源代碼里也有相關例子https://github.com/imyounghan/thinknet

 

總結

以上三篇文章我也主要是從寫代碼的角度去介紹如何DDD,強調一下我不是在教你如何寫代碼,只是為了展示用DDD如何實現,領域里的模型更應該能表達業務,他的價值更並不僅於此。而且以上的描述不一定完全正確,也不是告訴你一定要如何做,這也需要你自己的思考,如果有不對的地方歡迎你的指正,畢竟DDD我在學習過程中,也能從中受益。

如果我們過多的精力花在如何寫代碼上,可能是收集的工具類庫還不強大,或者是還沒有一個能夠方便快捷開發的框架,當然一個好的框架帶來的好處會很多。一個框架終究是有辦法和技術能力去實現完成的,但是如何分析和理解業務,然后從中挖掘出便於閱讀和表達業務的模型確定一件不容易的事情,他並不是通過某種技術辦法就能實現的。所以我個人覺得設計模型,划分界限上下文是需要不斷的積累領域業務知識才能做到的。

“領域驅動設計”和“實現領域驅動”這兩本書應該是最經典的了,知識點也很多,閱讀此書你會得到更多的收獲!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM