首页 > 代码库 > 学习DDD之路--勇于纠正自己的错误

学习DDD之路--勇于纠正自己的错误

写这篇文章主要是之前三篇对DDD的介绍算是自己学习的一次试水,也希望能够有更多的人能帮我发现其中的问题。昨天继续阅读了DDD书,发现了自己之前的例子存在了一些问题,早上也和园友进行了一些讨论。最后整理出此文,还记得第一篇用户注册是怎么做的吗?再次回顾一下,但也有一点变化,为了更好的符合DDD, 这次将应用代码写在了Application层中。

先贴上领域内的核心代码

public class User{    public User(string name, string password)    {        this.Name = name;        this.Password = password;        this.Id = Guid.NewGuid().ToString();    }    public string Id { get; private set; }    public string Name { get; private set; }    public string Password { get; private set; }}public interface IUserRepository{    void Add(User user);}public interface IEncryptionService{    string Encrypt(string password);}public class UserFactory{    private readonly IEncryptionService _encryptionService;    public UserFactory(IEncryptionService encryptionService)    {        this._encryptionService = encryptionService;    }    public User Create(string loginId, string password)    {        return new User(loginId, _encryptionService.Encrypt(password));    }}public interface IRegisterUserService{    User RegisterNewUser(string name, string password);}

再贴上Application的代码

public class UserService{    private readonly IRegisterUserService _registerUserService;    private readonly IUserRepository _userRepository;    public void Register(string name, string password)    {        User user = _registerUserService.RegisterNewUser(name, password);        _userRepository.Add(user);    }}

你有没有看到现在与之前的变化,是不是有点看不懂了?是的,这次我完全抛弃了domain service技术实现,这也是我昨天看原著和今天早上讨论出的结果,为什么会是这样?首先我个人的理解是domain service和repository一样,强调他们能做的是什么,而不是我怎么做的,之前我也有过把精力集中放在repository的技术实现上,最后发现它对于我思考领域没有什么太大帮助,当然不是说不重要,而是忽略了DDD的重点,同理domain service也一样,它也是强调能为我们做什么,只要定义的接口能够表达业务目的就可以了。所以用户注册这个例子,业务规则是要求注册的过程用户名必须唯一,domain service能够很好的反应这个过程,这个过程不一定要你就立即去解决它。刚刚我还想到由domain service提供一个接口来检查用户名是否唯一(如ValidateService.CheckUserNameIsUnique(user)),然后由application层先创建一个user,然后再检查用户名,看起来似乎蛮合理的,在领域内做了一些封装,但是这样却将领域知识暴露给了应用层或UI,很显然方向错了。

所以我会考虑将domain service和repository的实现放在基础设施层中,那么在基础设施层中domain service如果需要用到repository也是可以的。这样就不会有之前蟋蟀兄的疑惑了

对IRegisterUserService作一个简单的实现演示

class RegisterUserService : IRegisterUserService{    private readonly UserFactory _userFactory;    private readonly UserRepository _userRepository;    public User RegisterNewUser(string name, string password)    {        if (_userRepository.IsNameExist(name)) {            throw new Exception("用户名已存在");        }        return _userFactory.Create(name, password);    }}

也有人提出创建出来的用户是否合法也可以由工厂来保证,这里我想说也是可以的,但是我个人不推荐,这样工厂可能还需要其他一些知识,尽管在领域内部,这是可控的,但是我觉得他已经不纯洁了,工厂就是创建复杂对象用的,不需要掺杂着其他东西,而且它也不能表达用户注册这个过程。

 

总结

在学习DDD的过程中你会发现实现一个功能方式可能会更多,但是什么是合理的,可能一时并不能找到答案,甚至也迷糊。如果你在尝试DDD过程中也出现了错误,但这都没有关系,从错到对都会有一个过程,我们勇于承认并纠正自己的错误,没什么大不了的。如果你体会到DDD的好处会显得很兴奋,想用在具体项目上,我想建议还是缓一缓吧,虽然它是一把瑞士军刀或者中国军队的军用铲,但是用好它还是需要先了解到你能够很轻松的运用。