鼎鼎知识库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

24.DDD领域驱动基本概念.md 9.8KB

преди 4 години
преди 4 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. > 领域驱动设计
  2. - 思想体系
  3. - DDD 是一种开发思想体系,旨在管理为复杂问题域编写的软件的创建和维护工作。
  4. - 专注领域要高于其他一切需求。
  5. - DDD是模式、原则和实践的集合,可以被用到软件设计以管理
  6. - 模式类型
  7. - 战略模式:对任何应用程序都有用 重点提炼问题域(核心子域)->塑造应用程序架构
  8. - 战术模式:用于实现富领域模型(只当模型在领域逻辑做够丰富时才有用)
  9. - 实践原则
  10. - 专注于核心领域 强调在核心子域付出最多努力的需要
  11. - 通过协作学习 开发团队与业务专家的协作
  12. - 通过探索和实验来创建模型
  13. - 通信 公共语言(UL)
  14. - 理解模型的活用性 语言边界,避免歧义
  15. - 让模型持续发展 持续致力与知识提炼
  16. > 通用语言
  17. - 抛开DDD 想到通用语言首先想到英语 特点:1)简单易学 2)使用效率高 3)国际通用
  18. - 概念:通过团队交流达成共识的能够准确传递业务规则的简单的语言
  19. - 价值 解决了交流障碍问题,使领域专家和开发人员协同合作
  20. > 领域(重在范围的界限)
  21. - 本质 :可以理解为 就是一个问题域,只要是同一个领域,那问题域就相同。所以,只要我们确定了系统所属的领域,那这个系统的核心业务,既要解决的关键问题、问题的范围边界就基本确定了。
  22. - 与传统开发过程的区别在于 DDD注重领域建模
  23. - 领域拆分: 子域、核心域、通用子域、支撑子域
  24. - 举个例子(比如创建个电商网站 需要涉及的业务。商品、用户、订单、报价、支付、物流、保修相关业务)
  25. - 大致拆分:商品子域、用户子域、销售子域、订单子域、支付子域、物流子域、维修子域
  26. - 确定核心域:开发电商网站的目的是为了寻求推广和销售利润的最大化。所以核心域就是销售子域。
  27. - 通用子域:服务服务于整个业务领域。-》日志子域 可以为该网站提供一个日志系统,来记录一些日志。我们可以设计一个日志子域来供其他子域使用。
  28. - 支撑子域:作用于业务系统的某些重要业务而非核心业务,它关注于业务的某一方面,来支撑完善业务系统。
  29. - 我们划分的子域中除了销售子域,其他都可以说是支撑子域。
  30. - 比如物流子域,就是专注于物流相关业务,支撑着订单发货以及物流跟踪的重要流程。
  31. > 界限上下文
  32. - 可拆分为两个词,界限和上下文。 界限是指一个界限,具体的某一个范围。 上下文可理解为语境。
  33. - 例子 还是上述(电子商务)例子
  34. - 在销售子域和商品子域中就是商品
  35. - 在物流子域中特质货物,只关注部分属性
  36. - 命名 领域名+上下文 销售上下文 物流上下文
  37. > 领域模型
  38. - 概念:描述正在解决的问题及提出的解决方案
  39. - 特征:
  40. - 综合了系统分析和设计
  41. - 语言、模型、代码 三者紧密绑定
  42. - 可以通过UML类图来展示
  43. - 例子 在线商城案例
  44. ```
  45. Customer
  46. public class Customer
  47. {
  48. public int Id{get;set;}
  49. public string Name{get;set;}
  50. public string BillingAddress{get;set;}
  51. public string DeliveryAddress{get;set;}
  52. Public string LoginName{get;set;}
  53. public string LoginPassword{get;set;}
  54. public string DayOfBirth{get;set;}
  55. }
  56. order
  57. public class Order
  58. {
  59. public int Id{get;set;}
  60. public string CreatedDate{get;set;}
  61. public string CreatBy{get;set;}
  62. }
  63. OrderLine
  64. public class OrderLine
  65. {
  66. public int Id{get;set;}
  67. public string Quantity{get;set;}
  68. public string Discount{get;set;}
  69. }
  70. Category
  71. public class Category
  72. {
  73. public int Id{get;set;}
  74. public string Name{get;set;}
  75. public string Description{get;set;}
  76. }
  77. CreditCard
  78. public class CreditCart
  79. {
  80. public int Id{get;set;}
  81. public string Number{get;set;}
  82. public string HolderName{get;set;}
  83. public string ExpirationDate{get;set;}
  84. }
  85. Item
  86. public class Item
  87. {
  88. public int Id{get;set;}
  89. public string Name{get;set;}
  90. public string Description{get;set;}
  91. public string PurchasePrice{get;set;}
  92. public string SalesPrice{get;set;}
  93. }
  94. ```
  95. > 实体 (Entity)
  96. - 概念: 唯一身份标识+可变性[状态(属性)+行为(方法或领域事件或领域服务)]
  97. - 唯一标识: 针对上述例子 抽象出User实体 要定义其唯一标识。
  98. - 性格、外貌、昵称、身份证号都可以是User的属性,但为了确保标识的稳定性,智能用身份证号设为唯一身份标识。
  99. - 唯一标识的类型
  100. - 一个简单的应用程序里,一个int类型的自增Id就可以作为唯一标识。优点就是占用空间小,查询速度快。
  101. - 而在一些业务当中,要求唯一标识有意义,通过唯一标识就能识别出一些基本信息,比如支付宝的交易号,其中就包含了日期和用户ID。这种就属于字符串类型的标识,这就对唯一标识的生成提出了挑战。
  102. - 唯一标识的生成时机
  103. - 即时生成,即在持久化实体之前,先申请唯一标识,再更新到数据库。
  104. - 延迟生成,即在持久化实体之后。
  105. - 委派标识和领域标识
  106. - 基于领域实体概念分析确定的唯一身份标识,我们可以称为领域实体标识
  107. - 实现层超类型
  108. - 定义层超类型接口
  109. ```
  110. public interface IEntity
  111. {
  112. }
  113. public interface IEntity<TPrimaryKey> : IEntity
  114. {
  115. TPrimaryKey Id { get; set; }
  116. }
  117. ```
  118. - 实现层超类型
  119. ```
  120. public class Entity : Entity<int>, IEntity
  121. {
  122. }
  123. public class Entity<TPrimaryKey> : IEntity<TPrimaryKey>
  124. {
  125. public virtual TPrimaryKey Id { get; set; }
  126. public override bool Equals(object obj)
  127. {
  128. if (obj == null || !(obj is Entity<TPrimaryKey>))
  129. {
  130. return false;
  131. }
  132. if (ReferenceEquals(this, obj))
  133. {
  134. return true;
  135. }
  136. var other = (Entity<TPrimaryKey>) obj;
  137. var typeOfThis = GetType();
  138. var typeOfOther = other.GetType();
  139. if (!typeOfThis.GetTypeInfo().IsAssignableFrom(typeOfOther) && !typeOfOther.GetTypeInfo().IsAssignableFrom(typeOfThis))
  140. {
  141. return false;
  142. }
  143. return Id.Equals(other.Id);
  144. }
  145. public override int GetHashCode()
  146. {
  147. return Id.GetHashCode();
  148. }
  149. public static bool operator ==(Entity<TPrimaryKey> left, Entity<TPrimaryKey> right)
  150. {
  151. if (Equals(left, null))
  152. {
  153. return Equals(right, null);
  154. }
  155. return left.Equals(right);
  156. }
  157. public static bool operator !=(Entity<TPrimaryKey> left, Entity<TPrimaryKey> right)
  158. {
  159. return !(left == right);
  160. }
  161. }
  162. ```
  163. - 可变性
  164. - 实体的状态 eg:订单状态:未支付、正常、已发货、关闭
  165. - 实体的行为 eg:订单行为:支付、发货、关闭
  166. > 值对象
  167. - 概念:值+对象=》将一个值用对象的方式进行标书,表达一个具体的固定不变的概念
  168. - 值特征:
  169. - 表示一个具体的概念
  170. - 通过值得属性对其识别
  171. - 属性判断
  172. - 固定不变
  173. - 案例分析(购物网站都会维护客户收货地址信息来进行发货处理,一个地址信息一般主要包含省份、城市、区县、街道、邮政编码信息。)
  174. - 地址是一个值,不会随着时间而变化,它包含了地址所需要的完整属性(省份、城市、区县、街道、邮政编码)
  175. ```
  176. public class Address
  177. {
  178. /// <summary>
  179. /// 省份
  180. /// </summary>
  181. public string Province { get; private set; }
  182. /// <summary>
  183. /// 城市
  184. /// </summary>
  185. public string City { get; private set; }
  186. /// <summary>
  187. /// 区县
  188. /// </summary>
  189. public string County { get; private set; }
  190. /// <summary>
  191. /// 街道
  192. /// </summary>
  193. public string Street { get; private set; }
  194. /// <summary>
  195. /// 邮政编码
  196. /// </summary>
  197. public string Zip { get; private set; }
  198. public Address(string province, string city,
  199. string county, string street, string zip)
  200. {
  201. this.Province = province;
  202. this.City = city;
  203. this.County = county;
  204. this.Street = street;
  205. this.Zip = zip;
  206. }
  207. public override bool Equals(object obj)
  208. {
  209. bool isEqual = false;
  210. if (obj != null && this.GetType() == obj.GetType())
  211. {
  212. var that = obj as Address;
  213. isEqual = this.Province == that.Province
  214. && this.City == that.City
  215. && this.County == that.County
  216. && this.Street == that.Street
  217. && this.Zip == that.Zip;
  218. }
  219. return IsEqual;
  220. }
  221. public override int GetHashCode()
  222. {
  223. return this.ToString().GetHashCode();
  224. }
  225. public override string ToString()
  226. {
  227. string address = $"{this.Province}{this.City}" +
  228. $"{this.County}{this.Street}({this.Zip})";
  229. return address;
  230. }
  231. }
  232. ```
  233. - 作用
  234. - 符合通用语言,更简单明了的表达简单业务概念
  235. - 简化设计,减少不必要的数据库表设计
  236. - 值对象不会孤立存在,可作为所属实体的数据列
  237. - 多个值对象序可以劣化到单个列