DDD:订单管理 之 如何组织代码
发布时间:2020-12-13 19:45:03 所属栏目:百科 来源:网络整理
导读:背景 系统开发最难的是职责的合理分配,或者叫:“如何合理的组织代码”,今天说一个关于这方面问题的示例,希望大家多批评。 示例背景 参考数据字典 需求 OrderCode必须唯一。 Total = Sum(Subtotal)。 订单有三种状态:【未提交】、【待审核】和【已审核
背景系统开发最难的是职责的合理分配,或者叫:“如何合理的组织代码”,今天说一个关于这方面问题的示例,希望大家多批评。 示例背景参考数据字典需求
示例实现项目结构
项目整体采用简单的CQRS架构,Command端采用DDD组织,Query直接从数据库返回dynamic类型。Event可以用来处理跨聚合通信,也可以用来处理长事务或离线事务。 重点介绍的领域层采用状态模式处理状态迁移。 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Happy.Example.Domain.TestOrders 8 { 9 public interface ITestOrderState 10 { 11 void AddTestOrderDetail(TestOrderDetail testOrderDetail); 12 13 void UpdateTestOrderDetail(Guid testOrderDetailId,decimal subtotal); 14 15 void RemoveTestOrderDetail(Guid testOrderDetailId); 16 17 void Commit(); 18 19 void Verify(); 20 21 string Status { get; } 22 23 TestOrder TestOrder { set; } 24 } 25 } 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Happy.Example.Domain.TestOrders 8 { 9 public partial class TestOrder 10 { 11 private abstract class TestOrderState : ITestOrderState 12 { 13 public virtual void AddTestOrderDetail(TestOrderDetail testOrderDetail) 14 { 15 this.ThrowInvalidOperationException(); 16 } 17 18 public virtual void UpdateTestOrderDetail(Guid testOrderDetailId,decimal subtotal) 19 { 20 this.ThrowInvalidOperationException(); 21 } 22 23 public virtual void RemoveTestOrderDetail(Guid testOrderDetailId) 24 { 25 this.ThrowInvalidOperationException(); 26 } 27 28 public virtual void Commit() 29 { 30 this.ThrowInvalidOperationException(); 31 } 32 33 public virtual void Verify() 34 { 35 this.ThrowInvalidOperationException(); 36 } 37 38 public abstract string Status { get; } 39 40 public TestOrder TestOrder { protected get; set; } 41 42 private void ThrowInvalidOperationException() 43 { 44 throw new InvalidOperationException(string.Format("处于【{0}】的订单不能执行此操作!",this.Status)); 45 } 46 } 47 } 48 } 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Happy.Example.Domain.TestOrders 8 { 9 public partial class TestOrder 10 { 11 private sealed class UnCommitted : TestOrderState 12 { 13 internal static readonly string UnCommittedStatus = "未提交"; 14 15 public override void AddTestOrderDetail(TestOrderDetail testOrderDetail) 16 { 17 this.TestOrder.DoAddTestOrderDetail(testOrderDetail); 18 } 19 20 public override void UpdateTestOrderDetail(Guid testOrderDetailId,decimal subtotal) 21 { 22 this.TestOrder.DoUpdateTestOrderDetail(testOrderDetailId,subtotal); 23 } 24 25 public override void RemoveTestOrderDetail(Guid testOrderDetailId) 26 { 27 this.TestOrder.DoRemoveTestOrderDetail(testOrderDetailId); 28 } 29 30 public override void Commit() 31 { 32 this.TestOrder.DoCommit(); 33 } 34 35 public override string Status 36 { 37 get { return UnCommittedStatus; } 38 } 39 } 40 } 41 } 采用封装集合手法处理Total的同步问题。 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 using Happy.Domain; 8 using Happy.Domain.Tree; 9 using Happy.Infrastructure.ExtentionMethods; 10 using Happy.Example.Events.TestOrders; 11 12 namespace Happy.Example.Domain.TestOrders 13 { 14 public partial class TestOrder : AggregateRoot<Guid> 15 { 16 private ITestOrderState _orderState; 17 18 protected TestOrder() { } 19 20 public TestOrder(string orderCode,string customer) 21 { 22 orderCode.MustNotNullAndNotWhiteSpace("orderCode"); 23 customer.MustNotNullAndNotWhiteSpace("customer"); 24 25 this.Id = Guid.NewGuid(); 26 this.OrderCode = orderCode; 27 this.Customer = customer; 28 this.OrderState = TestOrderStateFactory.CreateUnCommittedTestOrderState(this); 29 this.TestOrderDetails = new List<TestOrderDetail>(); 30 } 31 32 public virtual System.String OrderCode { get; protected set; } 33 public virtual System.String Customer { get; protected set; } 34 public virtual System.Decimal Total { get; protected set; } 35 public virtual System.String Status { get; protected set; } 36 public virtual ICollection<TestOrderDetail> TestOrderDetails { get; protected set; } 37 38 private ITestOrderState OrderState 39 { 40 get 41 { 42 if (_orderState == null) 43 { 44 _orderState = TestOrderStateFactory.Create(this,this.Status); 45 } 46 47 return _orderState; 48 } 49 set 50 { 51 _orderState = value; 52 this.Status = value.Status; 53 } 54 } 55 56 public void AddTestOrderDetail(TestOrderDetail testOrderDetail) 57 { 58 this.OrderState.AddTestOrderDetail(testOrderDetail); 59 } 60 61 public void UpdateTestOrderDetail(Guid testOrderDetailId,decimal subtotal) 62 { 63 this.OrderState.UpdateTestOrderDetail(testOrderDetailId,subtotal); 64 } 65 66 public void RemoveTestOrderDetail(Guid testOrderDetailId) 67 { 68 this.OrderState.RemoveTestOrderDetail(testOrderDetailId); 69 } 70 71 public void Commit() 72 { 73 this.OrderState.Commit(); 74 } 75 76 public void Verify() 77 { 78 this.OrderState.Verify(); 79 } 80 81 private void DoAddTestOrderDetail(TestOrderDetail testOrderDetail) 82 { 83 this.TestOrderDetails.Add(testOrderDetail); 84 85 this.Total += testOrderDetail.Subtotal; 86 } 87 88 private void DoUpdateTestOrderDetail(Guid testOrderDetailId,decimal subtotal) 89 { 90 var testOrderDetail = this.TestOrderDetails.First(x => x.Id == testOrderDetailId); 91 92 this.Total -= testOrderDetail.Subtotal; 93 testOrderDetail.Subtotal = subtotal; 94 this.Total += testOrderDetail.Subtotal; 95 } 96 97 private void DoRemoveTestOrderDetail(Guid testOrderDetailId) 98 { 99 var testOrderDetail = this.TestOrderDetails.First(x => x.Id == testOrderDetailId); 100 101 this.TestOrderDetails.Remove(testOrderDetail); 102 this.Total -= testOrderDetail.Subtotal; 103 } 104 105 private void DoCommit() 106 { 107 this.OrderState = TestOrderStateFactory.CreatePendingVerificationTestOrderState(this); 108 } 109 110 private void DoVerify() 111 { 112 this.OrderState = TestOrderStateFactory.CreateVerifiedTestOrderState(this); 113 114 this.PublishEvent(new TestOrderVerified()); 115 } 116 } 117 } 效果图背景写这个简单的Demo过程,遇到了很多小的决策,这篇文章就看做一个开头吧,后边重点介绍每个决策点,在一篇文章中真的很难说完,喜欢看代码的朋友,先去https://happy.codeplex.com/下载。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |