写这篇文章主要是之前三篇对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. POJ-1797.HeavyTransportation(最长路中的最小权值)

    本题思路:最短路变形,改变松弛方式即可,dist存的是源结点到当前结点的最长路的最小权值. 参考代码: #include <cstdio> #include <cstring> ...

  2. 使用 Composer 安装Laravel扩展包的几种方法

    使用 Composer 安装Laravel扩展包的几种方法 以下的三种方法都是需要你在项目的根目录运行 第一种:composer install 如有 composer.lock 文件,直接安装,否则 ...

  3. 100-days: thirteen

     Title: “The Godfather turns 50” <教父>50周年 turn 达到某个年龄 Mario Puzo's(马里奥·普佐) "The Godfather ...

  4. [剑指Offer]36-二叉搜索树与双向链表

    链接 https://www.nowcoder.com/practice/947f6eb80d944a84850b0538bf0ec3a5?tpId=13&tqId=11179&tPa ...

  5. 【.Net】 大文件可使用的文本分组统计工具(附带源码,原创)

    本工具可实现的效果: 1.读取大文件(大于1GB) 2.根据分隔符分割后的列分组 3.速度快. 4.处理过程中,可以随时停止处理,操作不卡死. 5.有对当前内存的实时监测,避免过多占用内存,影响系统运 ...

  6. Apache beam中的便携式有状态大数据处理

    Apache beam中的便携式有状态大数据处理 目标: 什么是 apache beam? 状态 计时器 例子&小demo 一.什么是 apache beam? 上面两个图片一个是正面切图,一 ...

  7. java29

    1.封装小练习--长方形 创建长方形类 使用getset方法 利用返回值方法计算长方形的面积,周长. 保证长方形的长宽为整数 2.继承小练习--猫狗 当父类中有构造器时,子类也要有构造器,并且要求设置 ...

  8. Servlet执行流程和生命周期

    Servlet执行流程 Get方式请求HelloServlet ---> <a href="servlet/HelloServlet"> ↓ 服务器在配置文档中查 ...

  9. ABP框架系列之一:(Entity-实体)

    Entities are one of the core concepts of DDD (Domain Driven Design). Eric Evans describe it as " ...

  10. s31 zabbix监控企业级监控

    zabbix 简介与监控 zabbix安装部署 zabbix配置主机监控 zabbix 自定义监控 zabbix 配置报警方式 网站服务全面监控 zabbix 自动发现与snmp监控