소스 검색

DDD 基本概念

master
unknown 4 년 전
부모
커밋
09aa96ca91
1개의 변경된 파일259개의 추가작업 그리고 0개의 파일을 삭제
  1. 259
    0
      实践/后端/项目/24.DDD领域驱动基本概念.md

+ 259
- 0
实践/后端/项目/24.DDD领域驱动基本概念.md 파일 보기

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

Loading…
취소
저장