代理注册个公司一般需要多少钱,湘潭网站建设优化建站,如何用记事本做网站,网上申报系统入口最近几年#xff0c;领域驱动设计#xff08;Domain-Driven Design#xff0c;DDD#xff09;这个术语越来越多地出现在软件工程师的视野里。对DDD不熟悉的人可能会觉得它是软件领域里的一个新的概念#xff0c;但是实际上#xff0c;Eric Evans在十几年前就已经提出了这…最近几年领域驱动设计Domain-Driven DesignDDD这个术语越来越多地出现在软件工程师的视野里。对DDD不熟悉的人可能会觉得它是软件领域里的一个新的概念但是实际上Eric Evans在十几年前就已经提出了这个概念。这个“古老”的概念在之所以能够重焕新生很大程度上是因为遇上了“微服务”这个浪潮。如果把DDD里面的理念拿去和微服务架构做对比你会发现它们有着高度的相似性——DDD里的限界上下文不正是微服务架构中的微服务吗于是各大公司纷纷运用DDD的方法论来构建自己的产品架构。有些团队成功地将DDD结合到了产品架构中产生了许多优秀的实践也有些团队反映DDD太过复杂很难落地。那么DDD究竟是个什么样的理念为什么大家都争先恐后地使用它彷佛不加点DDD都不好意思说自己是微服务架构然而又为什么那么多团队说DDD难以落地本文将会结合简单的代码实现来谈谈笔者对DDD的理解。什么是领域驱动设计 软件的核心是其为用户解决领域相关的问题的能力。软件就是为了解决某一领域相关问题而存在的比如一个普通的计算器软件就是为了满足我们进行简单的加减乘除运算而存在。对于计算器这种小而简单的软件一个普通的软件工程师可能花上几天就能过设计开发出来而且基本不会出现Bug。但是对于一些大型而且复杂的系统一个团队都得花上很长的时间去设计整个架构然后经过n轮迭代才能开发出可用的版本而且后面还有各种Bug要去处理。比如证券交易系统里面就包括了用户系统、账户系统、订单系统、撮合系统等一系列的子系统而且其中的调用关系和业务都非常复杂。像这样一个庞大的系统怎样才能把它设计好呢这正是DDD要回答的问题。领域驱动设计DDD是一种软件开发的方法论旨在帮助我们设计出高质量的软件模型。在软件领域解决复杂问题的方法不外乎是“分治”和“抽象”DDD也是基于这两个理念建立起一套方法论。其中将一个系统划分成多个限界上下文限界上下文中划分出多个子域这是分治然后在分别对各个子域进行领域建模这是抽象。当你在设计一个业务复杂的系统却无从下手时尝试一下DDD说不定困难就会迎刃而解了。DDD中最核心的理念就是领域建模可以说它提供的各种方法都是为了帮助我们设计出更能准确传达业务规则的领域模型。一个好的领域模型可以让一个系统更加健壮可以让一个框架易用性更加好可以让一段代码更加好维护。那么什么样的模型才是好的领域模型下面我们通过一个例子来简单说明下。什么是领域模型 领域模型是关于某个特定业务领域的软件模型。通常领域模型通过对象模型来实现这些对象同事包含了数据和行为并且表达了准确的业务含义。日期和时间领域模型 如何设计一个日期和时间API首先需要对日期和时间的概念进行建模从直觉上我们可以将日期和时间抽象成一个对象Date。另外时间和日期经常都需要进行格式化输出因此我们还需要一个用于表示时间格式的对象DateFormat。为了更好地表示年月周日等概念再抽象出一个表示日历的Calendar对象以及表示时区的TimeZone对象。相信到这里大家都已经知道这正是JDK 1.1版本的日期时间API下面我们先回顾一下它的用法public class TestOldDate {public static void main(String[] args) {// 获取表示当前时刻的Date对象Date date1 new Date();// 通过Calendar等到指定日期时间的Date对象采用当前的系统时区Calendar calendar Calendar.getInstance(TimeZone.getDefault());calendar.set(2020, 2, 10, 0, 0, 0);Date date2 calendar.getTime();// 进行时间比较System.out.println(date1 is after date2: date1.after(date2));// 进行时间的加减法如获得昨天的这个时刻calendar.setTime(date1);calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) - 1);Date date3 calendar.getTime();// 对日期格式化输出DateFormat df new SimpleDateFormat(yyyy-MM-dd HH:mm:ss);System.out.println(date3: df.format(date3));}
}
/* Output:
date1 is after date2: false
date3: 2020-02-07 23:55:39
*/
如果你用习惯了JDK 1.1版本的日期时间API可能会觉得上述例子中的用法也没有多大的问题。但是仔细思考一下就会发现这其中的逻辑跟我们人类对时间的处理逻辑不太像比如要对时间做加法首先要将需要操作的Date对象设置到Calendar然后对Calendar做加法最后调用Calendar的接口得到结果。时间的加法难道不应该直接对Date对象加上一个时间段就行了吗相信很多小伙伴都会遇到这种情况自己写出来的代码可读性不够好。这其中原因可能是对领域的理解不够深设计出来的领域模型没能准确的表达业务逻辑如JDK 1.1的日期时间模型或者开发前根本就没有进行领域建模。这样容易导致采用了一种“机器思维”去进行开发而不是按照我们平常思考问题的思维去开发。JDK 1.8引入了全新的日期和时间API来解决老版本的API所存在的种种问题下面我们来看一下比之前更准确地表达日期和时间的领域模型JDK 1.8的日期和时间领域模型中的领域知识明显比老版本的领域模型要丰富很多而且模型更加符合人类思考日期和时间的思维。下面我们看下新的日期和时间API的用法public class TestNewDate {public static void main(String[] args) {// 获取表示当前时刻的LocalDateTime对象LocalDateTime date1 LocalDateTime.now(ZoneId.systemDefault());// 获取指定时间的LocalDateTime对象LocalDateTime date2 LocalDateTime.of(LocalDate.of(2020, 2, 10),LocalTime.of(0, 0, 0));// 进行是时间比较System.out.println(date1 is after date2: date1.isAfter(date2));// 进行时间的加减法如获得昨天的这个时刻LocalDateTime date3 date1.minus(Period.ofDays(1));// 对时间进行格式化输出DateTimeFormatter df DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss);System.out.println(date3: df.format(date3));}
}
/* Output:
date1 is after date2: false
date3: 2020-02-07 23:56:51
*/
实现同样的功能JDK 1.8版本的日期和时间API明显更加简洁而且代码的逻辑更加符合人的思维可读性更好比如使用.now()函数创建当前时刻的LocalDateTime对象代码阅读起来就跟人类的自然语言一样。由此可见设计出一个高质量的领域模型对于软件系统是多么的重要。在这个例子中JDK并没有显式地使用DDD提供的战术建模手段对日期和时间API进行设计但是从JDK 1.1到JDK 1.8版本中的变化其中就蕴含着DDD最核心的内容设计出更符合业务规则和人类思维的领域模型。从这个例子中我们也能看出DDD并没有传说中的那么神秘也未必一定要运用在复杂的系统即使是一个简单的日期和时间API其中也可以看到它的身影。如果让你对JDK 1.1的日期和时间API进行优化相信很多人都设计不出像JDK 1.8版本的这样优秀的API不管在经验还是在方法上我们都欠点火候。简单的API如此更别说设计复杂的大型系统了。这时我们需要一些具体的建模方法来指导设计。DDD的建模方法 DDD主要提出了两种建模方法来帮助我们设计出高质量的领域模型战略建模和战术建模。战略建模根据领域知识对系统进行限界上下文和子域的划分战术建模具体为每个限界上下文设计出领域模型。而这两者中又内涵很多知识点光看下面的这张DDD的概念图你可能会觉得DDD太过复杂了。确实DDD的学习曲线比较陡特别是第一次看Eric Evans所著的《领域驱动设计——软件核心复杂性应对之道》时会有种不知所云的感觉。再看Vaughn Vernon所著的《实现领域驱动设计》可能会好点了但是里面提到的各种概念还是没能很清晰地理解。所谓“实践出真知”只有通过不断地实践才能学习到DDD的精髓体会到它的魔力。下一篇文章我们将开始通过实践一个简单的业务功能着手介绍DDD的各种理论知识。http://weixin.qq.com/r/Tx2zqxDE602UrVTI90hd (二维码自动识别)