学习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的好处会显得很兴奋,想用在具体项目上,我想建议还是缓一缓吧,虽然它是一把瑞士军刀或者中国军队的军用铲,但是用好它还是需要先了解到你能够很轻松的运用。
补充
经过一番讨论,对于IRegisterUserService是不是需要定义成接口还是希望读者能有自己的思考,还有对于IRegisterUserService的实现我考虑是在基础设施层实现,这是一个错误的方向,应该是在领域内,因为他的知识范围就在领域内,而不是在领域外,至此我自己也更加清晰了。
学习DDD之路--勇于纠正自己的错误的更多相关文章
- [转载]AxureRP学习成长之路
[编者按]本文作者@朱军华Ronzhu , 本文借用官网的描述定义,介绍了在学习AxureRP过程当中所要经历的各个阶段,也结合了作者自身学习AxureRP使用的经验,讲一下在各个阶段中的一些学习方法 ...
- 3 学习UML图 学习DDD的基本概念
今天在学习DDD的过程中看到了大神 圣杰的博文 个人觉得非常经典 强烈推荐 在此提供url链接: UML类图10分钟快速入门 关于聚合 的理解 :一类没有紧密相关的东西聚在一起 ,分开了也可以独立存 ...
- 学习WCF之路,长期更新
我学习WCF之路:创建一个简单的WCF程序 为了使读者对基于WCF的编程模型有一个直观的映像,我将带领读者一步一步地创建一个完整的WCF应用.本应用功能虽然简单,但它涵盖了一个完整WCF应用的基本 ...
- 学习 Webpack5 之路(优化篇)
一.前言 从 0 到 1 学习的朋友可参考前置学习文章: 学习 Webpack5 之路(基础篇) 学习 Webpack5 之路(实践篇) 前置文章 学习 Webpack5 之路(基础篇) 对 webp ...
- 学习 DDD 之消化知识!
接触到DDD到现在已经有8个月份了,目前所维护的项目也是基于DDD的思想开发的,从一开始的无从下手,到现在游刃有余,学到不少东西,但是都是一些关键字和零散的知识,同时我也感受到了是因为我对项目越来越熟 ...
- 守护石谈学习Java之路
这次在CSDN Blink发表了几篇关于Java编程学习的小作文,讲述了Java工程师的成长路线.Java学习的技能树和入门工作要关注的核心问题,我继续做一次文章的整合与延展,以文章的形式发表出来, ...
- 小白学习Python之路---开发环境的搭建
本节内容 1.Python的介绍 2.发展史 3.安装Python 4.搭建开发环境 5.Hello World程序 一.Python的介绍 Python的创始人为荷兰人吉多·范罗苏姆(Guido v ...
- 学习 DDD - 通用语言的模式
大家好,我是霸戈,这周学习了一些关于领域驱动设计的知识 ,对比较深刻的地方做了不少笔记,分享给大家. 在日常需求讨论的时候,经常会碰到一个需求会议开了一个多小时还没有达成共识.作为业务方(领域专家)明 ...
- 开通博客-学习java之路
已被西南交通大学录取,毕设也已经进入末期.开始狂神说的Java学习之路,纪念一下!!!
随机推荐
- 十一 hashlib模块
# 1.什么叫hash:hash是一种算法(3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法),该算法接受传入的 ...
- netty(二) 创建一个netty服务端和客户端
服务端 NettyServer package com.zw.netty.config; import com.zw.netty.channel.ServerInitializer;import io ...
- Ueditor 前后端分离实现文件上传到独立服务器
关于Ueditor 前后端分离实现文件上传到独立服务器,在网上搜索确实遇到大坑,不过还好遇到了 虚若影 最终实现了,在此感谢!虚若影的原文博客网址:http://www.cnblogs.com/hpn ...
- yum提示Another app is currently holding the yum lock
使用yum grouplis列举系统中以组安装的包,结果提示: # yum grouplist Loaded plugins: fastestmirror, refresh-packagekit, s ...
- 五子棋 AI(AIpha-beta算法)
博弈树 下过五子棋的人都应该知道,越厉害的人,对棋面的预测程度越深.换句话讲,就是当你下完一步棋,我就能在我的脑海里假设把我所有可能下的地方都下一遍,然后考虑我下完之后你又会下在哪里,最后我根据每次预 ...
- 《笨方法学Python》加分题6
types_of_people = 10 x = f"There are {types_of_people} types of peoples." binary = "b ...
- 【Selenium】【BugList4】执行pip报错:Fatal error in launcher: Unable to create process using '""D:\Program Files\Python36\python.exe"" "D:\Program Files\Python36\Scripts\pip.exe" '
环境信息: python版本:V3.6.4 安装路径:D:\Program Files\python36 环境变量PATH:D:\Program Files\Python36;D:\Program F ...
- AngularJS封装webupload实现文件夹上传
百度的webupload没有开放api获取整个文件夹的信息.本文是二次开发webupload实现获取文件夹信息. 指令封装 /** * @license lx.ui.framework v1.0.0 ...
- ansible教程
相关教程: 权威指南:http://www.ansible.com.cn/ 博客教程:https://www.w3cschool.cn/automate_with_ansible/ 视频教程: htt ...
- PMP:3.项目经理角色
成员角色:整合指挥者 在团队中的职责:负终责 知识技能:综合技能&沟通 定义: 职能经理专注于对某个职能领域或业务部门的管理监督. 运营经理负责保证业务运营的高效性. 项目经理是由执行组织 ...