DDD:订单管理 之 如何组织代码

前端之家收集整理的这篇文章主要介绍了DDD:订单管理 之 如何组织代码前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

背景

系统开发最难的是职责的合理分配,或者叫:“如何合理的组织代码”,今天说一个关于这方面问题的示例,希望大家多批评。

示例背景

参考数据字典

需求

  1. OrderCode必须唯一。
  2. Total = Sum(Subtotal)。
  3. 订单有三种状态:【未提交】、【待审核】和【已审核】,合理的状态迁移有:【未提交】----》【待审核】和【待审核】----》【已审核】,只有处于【未提交】状态的订单能修改
  4. 订单和订单项中的状态必须合法,规则自己定义。

示例实现

项目结构

  • Application:应用层,负责领域逻辑的封装。主要角色:ApplicationService、CommandHandler。
  • Boostrap:启动管理层,负责启动过程管理,如:注册Ioc、初始化配置。主要角色:BootstrapListener。
  • Commands:命令层,是一个契约层。主要角色:Comamnd、DTO。
  • Controllers:控制器层,边界层。主要角色:Controller。
  • Domain:领域层,负责领域逻辑的组织。主要角色:Aggregate、Entity、ValueObject、Factory、DomainService、IRepository、IUnitOfWork。
  • Events:事件层,是一个契约层,跨聚合流程可以采用。主要角色:Event。
  • EventSubscribers:事件监听层。主要角色:EventSubscriber。
  • Infrastructure:基础设施层。主要角色:Repository、QueryService、UnitOfWork。
  • Query:查询层,为UI的查询提供服务,主要角色:QueryService。

项目整体采用简单的CQRS架构,Command端采用DDD组织,Query直接从数据库返回dynamic类型。Event可以用来处理跨聚合通信,也可以用来处理长事务或离线事务。

重点介绍的领域层

采用状态模式处理状态迁移。

  1. 1 using System;
  2. 2 using System.Collections.Generic;
  3. 3 using System.Linq;
  4. 4 using System.Text;
  5. 5 using System.Threading.Tasks;
  6. 6
  7. 7 namespace Happy.Example.Domain.TestOrders
  8. 8 {
  9. 9 public interface ITestOrderState
  10. 10 {
  11. 11 void AddTestOrderDetail(TestOrderDetail testOrderDetail);
  12. 12
  13. 13 void UpdateTestOrderDetail(Guid testOrderDetailId,decimal subtotal);
  14. 14
  15. 15 void RemoveTestOrderDetail(Guid testOrderDetailId);
  16. 16
  17. 17 void Commit();
  18. 18
  19. 19 void Verify();
  20. 20
  21. 21 string Status { get; }
  22. 22
  23. 23 TestOrder TestOrder { set; }
  24. 24 }
  25. 25 }
  1. 1 using System;
  2. 2 using System.Collections.Generic;
  3. 3 using System.Linq;
  4. 4 using System.Text;
  5. 5 using System.Threading.Tasks;
  6. 6
  7. 7 namespace Happy.Example.Domain.TestOrders
  8. 8 {
  9. 9 public partial class TestOrder
  10. 10 {
  11. 11 private abstract class TestOrderState : ITestOrderState
  12. 12 {
  13. 13 public virtual void AddTestOrderDetail(TestOrderDetail testOrderDetail)
  14. 14 {
  15. 15 this.ThrowInvalidOperationException();
  16. 16 }
  17. 17
  18. 18 public virtual void UpdateTestOrderDetail(Guid testOrderDetailId,decimal subtotal)
  19. 19 {
  20. 20 this.ThrowInvalidOperationException();
  21. 21 }
  22. 22
  23. 23 public virtual void RemoveTestOrderDetail(Guid testOrderDetailId)
  24. 24 {
  25. 25 this.ThrowInvalidOperationException();
  26. 26 }
  27. 27
  28. 28 public virtual void Commit()
  29. 29 {
  30. 30 this.ThrowInvalidOperationException();
  31. 31 }
  32. 32
  33. 33 public virtual void Verify()
  34. 34 {
  35. 35 this.ThrowInvalidOperationException();
  36. 36 }
  37. 37
  38. 38 public abstract string Status { get; }
  39. 39
  40. 40 public TestOrder TestOrder { protected get; set; }
  41. 41
  42. 42 private void ThrowInvalidOperationException()
  43. 43 {
  44. 44 throw new InvalidOperationException(string.Format("处于【{0}】的订单不能执行此操作!",this.Status));
  45. 45 }
  46. 46 }
  47. 47 }
  48. 48 }
  1. 1 using System;
  2. 2 using System.Collections.Generic;
  3. 3 using System.Linq;
  4. 4 using System.Text;
  5. 5 using System.Threading.Tasks;
  6. 6
  7. 7 namespace Happy.Example.Domain.TestOrders
  8. 8 {
  9. 9 public partial class TestOrder
  10. 10 {
  11. 11 private sealed class UnCommitted : TestOrderState
  12. 12 {
  13. 13 internal static readonly string UnCommittedStatus = "未提交";
  14. 14
  15. 15 public override void AddTestOrderDetail(TestOrderDetail testOrderDetail)
  16. 16 {
  17. 17 this.TestOrder.DoAddTestOrderDetail(testOrderDetail);
  18. 18 }
  19. 19
  20. 20 public override void UpdateTestOrderDetail(Guid testOrderDetailId,decimal subtotal)
  21. 21 {
  22. 22 this.TestOrder.DoUpdateTestOrderDetail(testOrderDetailId,subtotal);
  23. 23 }
  24. 24
  25. 25 public override void RemoveTestOrderDetail(Guid testOrderDetailId)
  26. 26 {
  27. 27 this.TestOrder.DoRemoveTestOrderDetail(testOrderDetailId);
  28. 28 }
  29. 29
  30. 30 public override void Commit()
  31. 31 {
  32. 32 this.TestOrder.DoCommit();
  33. 33 }
  34. 34
  35. 35 public override string Status
  36. 36 {
  37. 37 get { return UnCommittedStatus; }
  38. 38 }
  39. 39 }
  40. 40 }
  41. 41 }

采用封装集合手法处理Total的同步问题。

  1. 1 using System;
  2. 2 using System.Collections.Generic;
  3. 3 using System.Linq;
  4. 4 using System.Text;
  5. 5 using System.Threading.Tasks;
  6. 6
  7. 7 using Happy.Domain;
  8. 8 using Happy.Domain.Tree;
  9. 9 using Happy.Infrastructure.ExtentionMethods;
  10. 10 using Happy.Example.Events.TestOrders;
  11. 11
  12. 12 namespace Happy.Example.Domain.TestOrders
  13. 13 {
  14. 14 public partial class TestOrder : AggregateRoot<Guid>
  15. 15 {
  16. 16 private ITestOrderState _orderState;
  17. 17
  18. 18 protected TestOrder() { }
  19. 19
  20. 20 public TestOrder(string orderCode,string customer)
  21. 21 {
  22. 22 orderCode.MustNotNullAndNotWhiteSpace("orderCode");
  23. 23 customer.MustNotNullAndNotWhiteSpace("customer");
  24. 24
  25. 25 this.Id = Guid.NewGuid();
  26. 26 this.OrderCode = orderCode;
  27. 27 this.Customer = customer;
  28. 28 this.OrderState = TestOrderStateFactory.CreateUnCommittedTestOrderState(this);
  29. 29 this.TestOrderDetails = new List<TestOrderDetail>();
  30. 30 }
  31. 31
  32. 32 public virtual System.String OrderCode { get; protected set; }
  33. 33 public virtual System.String Customer { get; protected set; }
  34. 34 public virtual System.Decimal Total { get; protected set; }
  35. 35 public virtual System.String Status { get; protected set; }
  36. 36 public virtual ICollection<TestOrderDetail> TestOrderDetails { get; protected set; }
  37. 37
  38. 38 private ITestOrderState OrderState
  39. 39 {
  40. 40 get
  41. 41 {
  42. 42 if (_orderState == null)
  43. 43 {
  44. 44 _orderState = TestOrderStateFactory.Create(this,this.Status);
  45. 45 }
  46. 46
  47. 47 return _orderState;
  48. 48 }
  49. 49 set
  50. 50 {
  51. 51 _orderState = value;
  52. 52 this.Status = value.Status;
  53. 53 }
  54. 54 }
  55. 55
  56. 56 public void AddTestOrderDetail(TestOrderDetail testOrderDetail)
  57. 57 {
  58. 58 this.OrderState.AddTestOrderDetail(testOrderDetail);
  59. 59 }
  60. 60
  61. 61 public void UpdateTestOrderDetail(Guid testOrderDetailId,decimal subtotal)
  62. 62 {
  63. 63 this.OrderState.UpdateTestOrderDetail(testOrderDetailId,subtotal);
  64. 64 }
  65. 65
  66. 66 public void RemoveTestOrderDetail(Guid testOrderDetailId)
  67. 67 {
  68. 68 this.OrderState.RemoveTestOrderDetail(testOrderDetailId);
  69. 69 }
  70. 70
  71. 71 public void Commit()
  72. 72 {
  73. 73 this.OrderState.Commit();
  74. 74 }
  75. 75
  76. 76 public void Verify()
  77. 77 {
  78. 78 this.OrderState.Verify();
  79. 79 }
  80. 80
  81. 81 private void DoAddTestOrderDetail(TestOrderDetail testOrderDetail)
  82. 82 {
  83. 83 this.TestOrderDetails.Add(testOrderDetail);
  84. 84
  85. 85 this.Total += testOrderDetail.Subtotal;
  86. 86 }
  87. 87
  88. 88 private void DoUpdateTestOrderDetail(Guid testOrderDetailId,decimal subtotal)
  89. 89 {
  90. 90 var testOrderDetail = this.TestOrderDetails.First(x => x.Id == testOrderDetailId);
  91. 91
  92. 92 this.Total -= testOrderDetail.Subtotal;
  93. 93 testOrderDetail.Subtotal = subtotal;
  94. 94 this.Total += testOrderDetail.Subtotal;
  95. 95 }
  96. 96
  97. 97 private void DoRemoveTestOrderDetail(Guid testOrderDetailId)
  98. 98 {
  99. 99 var testOrderDetail = this.TestOrderDetails.First(x => x.Id == testOrderDetailId);
  100. 100
  101. 101 this.TestOrderDetails.Remove(testOrderDetail);
  102. 102 this.Total -= testOrderDetail.Subtotal;
  103. 103 }
  104. 104
  105. 105 private void DoCommit()
  106. 106 {
  107. 107 this.OrderState = TestOrderStateFactory.CreatePendingVerificationTestOrderState(this);
  108. 108 }
  109. 109
  110. 110 private void DoVerify()
  111. 111 {
  112. 112 this.OrderState = TestOrderStateFactory.CreateVerifiedTestOrderState(this);
  113. 113
  114. 114 this.PublishEvent(new TestOrderVerified());
  115. 115 }
  116. 116 }
  117. 117 }

效果

背景

写这个简单的Demo过程,遇到了很多小的决策,这篇文章就看做一个开头吧,后边重点介绍每个决策点,在一篇文章中真的很难说完,喜欢看代码的朋友,先去https://happy.codeplex.com/下载。

猜你在找的设计模式相关文章