写这篇文章主要是之前三篇对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的好处会显得很兴奋,想用在具体项目上,我想建议还是缓一缓吧,虽然它是一把瑞士军刀或者中国军队的军用铲,但是用好它还是需要先了解到你能够很轻松的运用。

补充

经过一番讨论,对于IRegisterUserService是不是需要定义成接口还是希望读者能有自己的思考,还有对于IRegisterUserService的实现我考虑是在基础设施层实现,这是一个错误的方向,应该是在领域内,因为他的知识范围就在领域内,而不是在领域外,至此我自己也更加清晰了。

学习DDD之路--勇于纠正自己的错误的更多相关文章

  1. [转载]AxureRP学习成长之路

    [编者按]本文作者@朱军华Ronzhu , 本文借用官网的描述定义,介绍了在学习AxureRP过程当中所要经历的各个阶段,也结合了作者自身学习AxureRP使用的经验,讲一下在各个阶段中的一些学习方法 ...

  2. 3 学习UML图 学习DDD的基本概念

    今天在学习DDD的过程中看到了大神 圣杰的博文 个人觉得非常经典 强烈推荐  在此提供url链接: UML类图10分钟快速入门 关于聚合 的理解 :一类没有紧密相关的东西聚在一起 ,分开了也可以独立存 ...

  3. 学习WCF之路,长期更新

    我学习WCF之路:创建一个简单的WCF程序   为了使读者对基于WCF的编程模型有一个直观的映像,我将带领读者一步一步地创建一个完整的WCF应用.本应用功能虽然简单,但它涵盖了一个完整WCF应用的基本 ...

  4. 学习 Webpack5 之路(优化篇)

    一.前言 从 0 到 1 学习的朋友可参考前置学习文章: 学习 Webpack5 之路(基础篇) 学习 Webpack5 之路(实践篇) 前置文章 学习 Webpack5 之路(基础篇) 对 webp ...

  5. 学习 DDD 之消化知识!

    接触到DDD到现在已经有8个月份了,目前所维护的项目也是基于DDD的思想开发的,从一开始的无从下手,到现在游刃有余,学到不少东西,但是都是一些关键字和零散的知识,同时我也感受到了是因为我对项目越来越熟 ...

  6. 守护石谈学习Java之路

    ​这次在CSDN Blink发表了几篇关于Java编程学习的小作文,讲述了Java工程师的成长路线.Java学习的技能树和入门工作要关注的核心问题,我继续做一次文章的整合与延展,以文章的形式发表出来, ...

  7. 小白学习Python之路---开发环境的搭建

    本节内容 1.Python的介绍 2.发展史 3.安装Python 4.搭建开发环境 5.Hello World程序 一.Python的介绍 Python的创始人为荷兰人吉多·范罗苏姆(Guido v ...

  8. 学习 DDD - 通用语言的模式

    大家好,我是霸戈,这周学习了一些关于领域驱动设计的知识 ,对比较深刻的地方做了不少笔记,分享给大家. 在日常需求讨论的时候,经常会碰到一个需求会议开了一个多小时还没有达成共识.作为业务方(领域专家)明 ...

  9. 开通博客-学习java之路

    已被西南交通大学录取,毕设也已经进入末期.开始狂神说的Java学习之路,纪念一下!!!

随机推荐

  1. AC自动机解题记录

    1.HDU 2222 Keywords Search 模板题 #include <bits/stdc++.h> #define fir first #define sec second # ...

  2. 复用微信小程序源码包后仍然有原小程序的版本管理怎么处理

    前言: 复用微信小程序源码包后,重新创建项目导入源码包,会发现开发者工具版本管理中仍然有原来小程序的版本,这样就不太好了.毕竟是一个新的小程序,需要有新的版本控制的.那么这个问题怎么处理呢? 解决方案 ...

  3. spring用注解配置,不用XML

    //首先装载一个配置类AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyCon ...

  4. AX_InventCounting

    static void Job649(Args _args)  {      ItemId                  ItemId          = "000XA00612R1& ...

  5. ABP框架系列之十三:(Authorization-授权)

    Introduction Almost all enterprise applications use authorization in some level. Authorization is us ...

  6. 位图法bitmap

    1.概念 1)所谓bitmap,就是用每一位(bit)来标记某个元素对应的value, 而key即是该元素,通常bitmap是一个int数组,用每一个int数的每一个bit来映射某个数据 2)由于采用 ...

  7. USART of STM32

    /*************************************************************************** * 文件名:USART.h * * 编写人:离 ...

  8. ReSharper 10.0.0.2 Ultimate 破解

    文件下载地址:http://pan.baidu.com/s/1gf7l8cF 1.安装ReSharper 10.0.0.2 Ultimate 2.修改Products.json文件的FilePath, ...

  9. ESP32作为接入点AP

    作为接入点的第一个任务是使用esp_wifi_set_mode()函数设置ESP32 函数并传递请求,作为接入点,可以把ESP32设置为AP或者APSTA,即 esp_wifi_set_mode(WI ...

  10. PMP:7.项目成本管理

    内容中包含 base64string 图片造成字符过多,拒绝显示