如何开始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我在学习过程中,也能从中受益。

如果我们过多的精力花在如何写代码上,可能是收集的工具类库还不强大,或者是还没有一个能够方便快捷开发的框架,当然一个好的框架带来的好处会很多。一个框架终究是有办法和技术能力去实现完成的,但是如何分析和理解业务,然后从中挖掘出便于阅读和表达业务的模型确定一件不容易的事情,他并不是通过某种技术办法就能实现的。所以我个人觉得设计模型,划分界限上下文是需要不断的积累领域业务知识才能做到的。

“领域驱动设计”和“实现领域驱动”这两本书应该是最经典的了,知识点也很多,阅读此书你会得到更多的收获!

 

转载于:https://www.cnblogs.com/younghan/p/3892598.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/273638.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git pull 报错:Untracked Fles Preventing Merge

场景 使用 git pull 命令更新报错解决 找到对应的文件删除后重新打开项目。

关于string,我今天科普的

今天下午朋友讨论组上讨论一个关于string的问题&#xff0c;问题是这样的&#xff0c;string a"aaa";string ba;a"bbb",为什么测试b的值不改变&#xff1f;之前我看过一个文章&#xff0c;知道肯定不相等&#xff0c;因为引用地址的一系列问题&#xff0c;…

git pull 报错:The following untracked working tree files would be overwritten by merge

场景 使用 git pull 命令更新报错 Updating d652d1c..fa05549 error: The following untracked working tree files would be overwritten by merge:.idea/encodings.xmlPlease move or remove them before you can merge. Aborting 解决 使用 git clean -d -fx 命令即可。

SpringBoot 配置多数据源

项目Git地址&#xff1a;SpringBoot 配置多数据源&#xff1a;Jacob-multi-data-source 准备工作 准备两个数据库(此模块中两个数据库一个为本地 一个为远程&#xff0c;本地为主&#xff0c;远程为从)。然后建表。 #本地库 CREATE TABLE username (id bigint(11) NOT NULL AUT…

HDU 2912

直线关于球的多次反射&#xff0c;求最后一次反射点 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath>using namespace std; const double inf1e10; const double eps1e-8; struct point {doub…

EMVTag系列3《持卡人基本信息数据》

9F61 持卡人证件号 L&#xff1a;2–26 R&#xff08;需求&#xff09;&#xff1a;数据应存在&#xff0c;在读应用数据过程中&#xff0c;终端不检查&#xff1b; (PBOC2.0第五部分中规定)芯片中持卡人姓名 5F20与持卡人姓名扩展9F0B只能使用一个&#xff0c;另一个必须不…

BindingException: Parameter 'XXX' not found. Available parameters are [collection, list]

应业务需求&#xff0c;需要使用到MQ进行数据上传和下发。传递格式为JSON,服务那边下发JSON数组&#xff0c;接收端将JSON数组转换成List集合&#xff0c;调用Mybatis-plus批量添加saveBatch()。提示字段未找到... org.apache.ibatis.exceptions.PersistenceException: ### Er…

JDK 8 新特性 之 default关键字

前言 Jdk1.8之前的接口中只声明方法&#xff0c;方法具体实现应在子类中进行。Jdk1.8打破了这样的用法&#xff1a;接口中可以实现具体的方法体&#xff0c;只需要加上关键字static或者default修饰即可。 default关键字 public interface UserService {//自定义方法void getUse…

headroom.js插件使用方法

1.什么是headroom.js&#xff1f; headroom是用纯Javascript写的插件&#xff0c;用来隐藏和展示页面元素&#xff0c;从而为页面留下更多空间。比如使用headroom能使导航栏当页面下滚时消失&#xff0c;当页面上滚时候又出现。&#xff08;查看效果&#xff09; 2.工作原理 通…

JDK 8 新特性 之 方法引用

概述 方法引用&#xff1a;当要传递给Lambda体的操作&#xff0c;已经有实现的方法了&#xff0c;就可以使用方法引用方法引用&#xff1a;在Lambda的基础上进一步的简化。换句话说&#xff0c;方法引用就是Lambda表达式&#xff0c;也就是函数式接口的一个实例&#xff0c;通过…

项目记录:springmvc forward redirect 问题

RequestMapping("/redirect")public String redirect(RedirectAttributes redirectAttributes){redirectAttributes.addFlashAttribute("test", "testdata"); //专供此种情况下使用。return "redirect:read";} 注意&#xff1a;此种情…

JDK 8 新特性 之 Lambda表达式

前言 Lambda 表达式&#xff0c;也可称为闭包&#xff0c;它是推动 Java 8 发布的最重要新特性。Lambda 允许把函数作为参数传递进方法中。使用 Lambda 表达式可以使代码变的更加简洁紧凑。lambda表达式的重要特征: 可选类型声明&#xff1a;不需要声明参数类型&#xff0c;编译…

开源组件DocX导出Word

1、使用Docx替换Word模板里书签里内容的一个方法 using Novacode;public class ExportWord{/// <summary>/// 导出word/// </summary>/// <param name"lBookMarks">书签数据源</param>/// <param name"sTemplatePath">导出W…

JDK 8 新特性 之 Strams简单使用

概述 Java 8 API添加了一个新的抽象称为流Stream&#xff0c;可以让你以一种声明的方式处理数据。 Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。 Stream API可以极大提供Java程序员的生产力&#xff0c;让程序员写出…

Cannot open include file: jni.h: No such file or directory解决方法

在此运行Visual Studio 2012 项目时出现 #include <stdio.h> #include <jni.h> int main() { printf("Hello World"); } But when I try to build, I get the following error - 1>c:testtest.cpp(2) : fatal error C1083: Cannot open include file:…

JDK 8 新特性 之 函数接口

函数接口 定义:接口中只有唯一的一个抽象方法&#xff0c;该接口就称之为函数接口。 //函数接口 public interface FunctionInterface1 {//1、只有一个方法的接口&#xff0c;默认称之为函数接口void get(); }//非函数接口 public interface FunctionInterface2 {void get1();v…

微服务之基础知识

什么是微服务架构 微服务是系统架构上的一种设计风格&#xff0c; 它的主旨是将一个原本独立的系统拆分成多个小型服务&#xff0c;这些小型服务都在各自独立的进程中运行&#xff0c;服务之间通过基于HTTP的RESTful API进行通信协作。 被拆分成的每一个小型服务都围绕着系统中…

LightOj 1078 Basic Math

思路&#xff1a; 设输入的两个数分别为n和a,每一次所得到的数为update&#xff1a; 开始updatea,依次update分别为update*10a,这样数据会超出范围&#xff0c;则update每次为update(update*10a)%n即可&#xff0c; 如果update0,跳出循环&#xff1b; 只需证明&#xff1a;(upd…

还是俄罗斯方块之android版

前面的&#xff0c;口水话 请直接跳过。 虽然现在不比以前了 也没多少人气了&#xff0c;放到首页 都不到几百的点击量。也许博客园整体水平也是在往水的方向发展。不谈那些了&#xff0c;哥也曾经辉煌过 有过一天上千的点击量 &#xff0c;哥也曾经有过粉丝&#xff0c;被小妹…

Integer 值判断相等

Integer 值判断相等 案例&#xff1a; public class Test {public static void main(String[] args) {Integer a 127;Integer b 127;System.out.println("a b :" (a b));System.out.println("a.equals(b):"a.equals(b));String x "127";Str…