反映業務規則的代碼是整個軟件的核心,可是它通常只佔很小的一部分,在傳統的基於貧血模型的分層軟件架構中,業務規則可能分散到各個層、各個代碼段,從而使得經過代碼來還原業務規則或者保證代碼與業務規則一致將變得很是困難。DDD分層架構的核心思想就是將全部業務規則的代碼抽取到領域層,保證領域層的編碼與領域模型是徹底一致的。數據庫
下圖是DDD的分層架構。
緩存
必定要牢記:DDD分層架構一個核心任務,就是將軟件最重要的資產——業務規則分離出來,抽象在領域層,並確保這些代碼是領域模型的正確實現。關於領域模型的實現,在下一篇文章介紹。 架構
接下來,我將經過代碼來演示這個新的分層架構。app
1 應用層分佈式
應用層在這裏很是的簡單清晰,它僅僅是將基礎設施層、領域層提供的功能裝配起來完成任務,這一層的代碼邏輯很是簡單。ide
下面是建立設計師訂單的裝配任務。ui
1 @Service 2 @Transactional(rollbackFor = Exception.class) 3 public class DesignerOrderServiceImpl implements DesignerOrderService { 4 @Autowired 5 private DesignerOrderRepository designerOrderRepository; 6 @Autowired 7 private RefundOrderRepository refundOrderRepository; 8 9 @Override 10 public DesignerOrder createOrder(int customerId, int designerId) { 11 DesignerOrder order = DesignerOrderFactory.createOrder(customerId, designerId); 12 13 designerOrderRepository.create(order); 14 15 return designerOrderRepository.selectByKey(order.getId()); 16 } 17 18 @Override 19 public void pay(int orderId, float amount) { 20 DesignerOrder order = designerOrderRepository.selectByKey(orderId); 21 if (order == null) { 22 AppException.throwAppException(AppExceptionMessage.DESIGNER_ORDER_NOT_EXIST_CODE, AppExceptionMessage.DESIGNER_ORDER_NOT_EXIST, orderId); 23 } 24 25 order.pay(amount); 26 designerOrderRepository.update(order); 27 } 28 29 @Override 30 public RefundOrder refund(int orderId, String cause) { 31 DesignerOrder order = designerOrderRepository.selectByKey(orderId); 32 if (order == null) { 33 AppException.throwAppException(AppExceptionMessage.DESIGNER_ORDER_NOT_EXIST_CODE, AppExceptionMessage.DESIGNER_ORDER_NOT_EXIST, orderId); 34 } 35 36 RefundOrder refundOrder = order.refund(cause); 37 38 designerOrderRepository.update(order); 39 40 refundOrderRepository.create(refundOrder); 41 42 return refundOrderRepository.selectByKey(refundOrder.getId()); 43 } 44 }
這裏例舉了建立訂單、付款、退款的應用層代碼。this
這裏,訂單建立有2個步驟:編碼
(1)使用Factory建立新的業務對象;spa
(2)使用Repository將業務對象持久化到數據庫。
付款3個步驟:
(1)使用Repository加載訂單業務對象到內存;
(2)調用訂單業務對象的付款方法更改業務對象狀態;
(3)使用Repository將業務對象持久化到數據庫。
退款有3個步驟:
(1)使用Repository加載訂單業務對象到內存;
(2)調用設計師訂單業務對象的退款方法改變業務對象的狀態,而後生成一個退款訂單業務對象;
(3)使用Repository持久化設計師訂單和退款訂單業務對象。
此外,應用層還額外處理了數據持久化的事務。
2 領域層
領域層是實現全部業務規則的領域對象,它是整個軟件的核心,而且與領域模型保持一致。
1 @Data 2 @EqualsAndHashCode(of = {"id"}) 3 public class DesignerOrder implements Entity<DesignerOrder> { 4 private int id; 5 private DesignerOrderState state; 6 private int customerId; 7 private int designerId; 8 private float area; 9 10 private float expectedAmount; 11 private int estimatedDays; 12 private DesigningProgressReport progressReport; 13 14 private String abortCause; 15 16 private float actualPaidAmount; 17 18 private int feedbackStar; 19 private String feedbackDescription; 20 21 private Date createdTime; 22 private Date updatedTime; 23 24 public void pay(float amount) { 25 Assert.isTrue(amount > 0, "The amount must be bigger than 0."); 26 27 if (!DesignerOrderWorkflowService.canChangeState(state, DesignerOrderState.PAID)) { 28 DomainException.throwDomainException(DomainExceptionMessage.PAYMENT_NOT_IN_READY_STATE_CODE, DomainExceptionMessage.PAYMENT_NOT_IN_READY_STATE, this.id, this.state); 29 } 30 31 if (Math.abs(amount - this.expectedAmount) > 0.01) { 32 DomainException.throwDomainException(DomainExceptionMessage.PAYMENT_NOT_MATCHED_CODE, DomainExceptionMessage.PAYMENT_NOT_MATCHED, this.id, this.expectedAmount, amount); 33 } 34 35 this.state = DesignerOrderWorkflowService.changeState(this.id, state, DesignerOrderState.PAID); 36 this.actualPaidAmount = amount; 37 38 // 付款完成後,自動啓動進度跟蹤 39 this.progressReport.startup(); 40 } 41 42 public RefundOrder refund(String cause) { 43 this.assertCanRefund(); 44 45 this.state = DesignerOrderWorkflowService.changeState(this.id, state, DesignerOrderState.REFUND); 46 47 return RefundOrderFactory.newRefundOrder(this, cause); 48 } 49 50 private void assertCanRefund() { 51 DesigningProgressNode constructionDrawingDesignNode = this.progressReport.getNode(DesigningProgressNodeType.CONSTRUCTION_DRAWING_DESIGN); 52 if (constructionDrawingDesignNode.getState() == DesigningProgressNodeState.REQUEST_COMPLETION || 53 constructionDrawingDesignNode.getState() == DesigningProgressNodeState.CONFIRM_COMPLETION) { 54 DomainException.throwDomainException(DomainExceptionMessage.FAILED_TO_REFUND_FOR_PROGRESS_CODE, DomainExceptionMessage.FAILED_TO_REFUND_FOR_PROGRESS, this.id); 55 } 56 } 57 58 @Override 59 public boolean sameIdentityAs(DesignerOrder other) { 60 return this.equals(other); 61 } 62 }
你能夠發現業務對象的代碼有:
關於領域層的編碼模式,在下文會詳細介紹。
3 基礎設施層
基礎設施層爲上層提供通用的技術能力,包括消息傳遞、緩存、遠程調用、分佈式事務、持久化、UI繪製等。如下是持久化實現的一段代碼。它以整個實體做爲存儲單元(注意:準確的說,是以聚合根爲存儲單元,後續詳細介紹)。
1 @Repository 2 public class DesignerOrderRepositoryImpl implements DesignerOrderRepository { 3 private static final String DESIGNER_ORDER_TABLE = "designer_order"; 4 5 @Autowired 6 private DesignerOrderMapper designerOrderMapper; 7 8 @Override 9 public void create(DesignerOrder order) { 10 if (designerOrderMapper.create(order) == 0) { 11 TableException.throwTableException(DESIGNER_ORDER_TABLE, TableOperation.CREATE); 12 } 13 } 14 15 @Override 16 public DesignerOrder selectByKey(int id) { 17 DesignerOrder order = designerOrderMapper.selectByKey(id); 18 buildConnection(order); 19 return order; 20 } 21 22 @Override 23 public DesignerOrder selectOneBySpecification(DesignerOrder example) { 24 DesignerOrder designerOrder = designerOrderMapper.selectOneBySpecification(example); 25 buildConnection(designerOrder); 26 return designerOrder; 27 } 28 29 @Override 30 public List<DesignerOrder> selectBySpecification(DesignerOrder example) { 31 List<DesignerOrder> designerOrders = designerOrderMapper.selectBySpecification(example); 32 buildConnection(designerOrders); 33 return designerOrders; 34 } 35 36 @Override 37 public void update(DesignerOrder order) { 38 if (designerOrderMapper.update(order) == 0) { 39 TableException.throwTableException(DESIGNER_ORDER_TABLE, TableOperation.UPDATE); 40 } 41 } 42 }
4 結論
必定要牢記:DDD分層架構一個核心任務,就是將軟件最重要的資產——業務規則分離出來,抽象在領域層,確保這些代碼是領域模型的正確實現。
經過以上的分層示例,咱們能夠總結出來領域驅動設計的代碼基本模式: