领域驱动设计(1)认识了解什么是领域驱动
领域驱动(1)认识了解什么是领域驱动
废话
领域驱动设计已经出现很早了,说实话很早以前的我很不喜欢看书、不论是pdf还是书本、买过的书籍还是有几本的,这仅有的几本书还是因为公司的业务或者某项技术遇到瓶颈需要自己和团队进行突破的时候用来填充自己的大脑用的,当然这是被动的,毕竟:生下来、活下去很重要的。这两年微服务的出现好像又推动了领域驱动设计的发展。
一、解释什么是领域驱动:
其实对于IT的行业的我们理解起来很容易,很有可能在日常生活工作中我们也都有过接触,对于领域是一个什么样的概念
举例:
比如说我们要做一个有关用户登录的功能,使用最简单的RBAC来进行设计但是在进行设计的时候我们首先需要明白的是用户(甲方)有几种级用户的级别,每种级别处于什么样的角色,又有多少权限,这个时候产品经理开始去接触软件使用方(方法),去了解他们的需求以及,期初因为产品经理不明白甲方的企业架构导致采集需求的时候工作异常难做,摩擦不断,后来渐渐的接触的多了,明白了甲方的企业架构,并且对甲方的一些专业的称呼、名词也渐渐的懂得了,在往后的沟通过程中双方之间的摩擦也渐渐的少了起来。 在这个由坏变好的过程中,是因为产品经理渐渐的融入了甲方的领域内。
然后产品把业务拿了回来,软件开发人员开始了设计开发工作,大多数开发人都把技术作为自己的能力,对领域并不去了解,导致了后来功能实现后,代码不能很好的扩展,有一天产品经理拿了一份变更的需求回来了,为了实现新的需求,迫不得已软件开发人员只有重新来过,导致了前面做的很多工作都是无用工,我相信这样的场景很多的开发人员都遇到过,也埋怨过,其实开发人员也是有错的假如我们开发人员也同样进入了对方的领域中,在真正的实现过程中,就可能会提前发现隐藏的问题,再不济也能写出可扩展的设计或代码,当真正的发生变更的时候,也不至于前面的所有的工作都成为了无用功。
其实领域驱动设计需要领域驱动专家和开发人员相互协作来完成的,在这个过程中无论是开发人员还是业务人员都积累了该领域的相关知识。
但是在开发过程中,时长会有人员流失的可能性,其实人员的流失也是相对应的领域知识的流失,有人这样说,真正的高手写出的代码是可以让菜鸟维护起来都不是很吃力的,为什么呢,其实高手在写代码的时候已经传承下了该领域的知识,等到新人来到的时候,根据代码分析学习代码中传承下的领域知识,可以做到更快的了解业务。
代码举例:利用策略模式实现一个简单的领域模型
用一个比较靠近生活的例子:一套服装的价格在不同的地区出售不同的价格
我们把地区和服装的价格联系起来
/// <summary> /// 获取衣服价格 /// </summary> /// <returns></returns> public decimal GetClothing(string ClothingNO, string AreaNo) { ClothingModel clothingModel = new ClothingModel(); SellAreaModel sellAreaModel = SellAreaModellist.Where(x => x.AreaNo == AreaNo).SingleOrDefault(); if (sellAreaModel != null) { clothingModel = ClothingModellist.Where(x => x.ClothingNo == ClothingNO&& x.AreaNo==sellAreaModel.AreaNo).SingleOrDefault(); //乘以折扣比率 return clothingModel.ClothingPrice* clothingModel.Discount; } else { return 0.00M; } }
View Code
由于季节发生了改变,衣服的价格需要根据不同的季节进行价格上的改动,这种情况被称为商品的季节性,这是商品销售领域的基本常识,然而有的技术人员对这项规则并不了解。
需求文档中增加了这样一句话:衣服根据不同的季节会发生价格上下浮动的变化。春季下调10% 冬季上调10%.
/// <summary> /// 获取衣服价格 /// </summary> /// <returns></returns> public decimal GetClothing(string ClothingNO, string AreaNo,int SeasonMark) { //根据季节规定价格浮动比例 double floatNum = SeasonMark != 0 ? 0.1 : 1.1; ClothingModel clothingModel = new ClothingModel(); SellAreaModel sellAreaModel = SellAreaModellist.Where(x => x.AreaNo == AreaNo).SingleOrDefault(); if (sellAreaModel != null) { clothingModel = ClothingModellist.Where(x => x.ClothingNo == ClothingNO && x.AreaNo == sellAreaModel.AreaNo).SingleOrDefault(); //乘以该地区的折扣比率*季节价格调动比例 return clothingModel.ClothingPrice * clothingModel.Discount* (decimal)floatNum; } else { return 0.00M; } }
View Code
这样的代码已经变得复杂了起来,当业务规则在增加的时候代码将变得更加的复杂,这个时候我想一个新人想要在代码中得到业务规则也将变得困难起来。规则越复杂情况越糟糕。
现在代码这样改动:使用策略模式
策略模式(Strategy)概念:策略模式一般指定义一组算法,将每个算法都进行封装,可以使程序可有由一个或多个可替换的策略组合成。
/// <summary> /// 获取衣服价格 /// </summary> /// <returns></returns> public decimal GetClothing(string ClothingNO, string AreaNo, int SeasonMark) { //根据季节规定价格浮动比例 double floatNum = SeasonMark != 0 ? 0.1 : 1.1; SellAreaModel sellAreaModel = SellAreaModellist.Where(x => x.AreaNo == AreaNo).SingleOrDefault(); if (sellAreaModel != null) { ClothingModel clothingModel = ClothingModellist.Where(x => x.ClothingNo == ClothingNO && x.AreaNo == sellAreaModel.AreaNo).SingleOrDefault(); return ComputedPrice(clothingModel, floatNum); } else { return 0.00M; } } /// <summary> /// 计算衣服的价格 /// </summary> /// <param name="clothingModel">服装信息</param> /// <param name="floatNum">滑动比例</param> /// <returns></returns> public decimal ComputedPrice(ClothingModel clothingModel, double floatNum) { //乘以该地区的折扣比率*季节价格调动比例 return clothingModel.ClothingPrice * clothingModel.Discount * (decimal)floatNum; }
View Code
/// <summary> /// 获取衣服价格 /// </summary> /// <returns></returns> public decimal GetClothing(string ClothingNO, string AreaNo, int SeasonMark) { //根据季节规定价格浮动比例 double floatNum = SeasonMark != 0 ? 0.1 : 1.1; SellAreaModel sellAreaModel = SellAreaModellist.Where(x => x.AreaNo == AreaNo).SingleOrDefault(); if (sellAreaModel != null) { ClothingModel clothingModel = ClothingModellist.Where(x => x.ClothingNo == ClothingNO && x.AreaNo == sellAreaModel.AreaNo).SingleOrDefault(); return ComputedPrice(clothingModel, floatNum); } else { return 0.00M; } } /// <summary> /// 计算衣服的价格 /// </summary> /// <param name="clothingModel">服装信息</param> /// <param name="floatNum">滑动比例</param> /// <returns></returns> public decimal ComputedPrice(ClothingModel clothingModel, double floatNum) { //乘以该地区的折扣比率*季节价格调动比例 return clothingModel.ClothingPrice * clothingModel.Discount * (decimal)floatNum; }
View Code
这样写的好处在于,当开发设计人员看到这段代码的时候可以明确的看到衣服不通季节有不同的价格计算策略,而不是像上面代码一样把一个重要的业务规则,写成一句不引人注意的计算问题。这样的代码读起来会开发人员更快的理解代码
深层模型:
每一个项目都会随着对领域和需求的理解,模型也会逐渐的加深,可能项目刚开始的时候对于我们来说很重要的表面元素,将变得不是那么重要,也或者那些不重要的元素,随着业务理解的深度或切换角度后变得重要起来。模型在一步步的变得庞大这也是知识消化后的产物,如果当领域专家和开发人员通过领域模型就能对业务需求有一定的认知,我想最起码沟通的过程中目的的一致性也做到了。同样会减少很多本不应该出现的需求变更的出现。
最近一两个月将持续更新领域驱动设计。有偏差的望大家指出,相互学习。
有不足之处 希望大家指出相互学习,
本文原创:转载请注明出处 谢谢!