<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          EasyDomain領(lǐng)域驅(qū)動開發(fā)實用庫

          聯(lián)合創(chuàng)作 · 2023-09-23 10:05

          EasyDomain是為領(lǐng)域驅(qū)動開發(fā)設(shè)計的基礎(chǔ)類庫,主要包括實體對象通用能力支持、基于實體的業(yè)務(wù)規(guī)則驗證支持、領(lǐng)域事件支持以及應(yīng)用服務(wù)層基于領(lǐng)域事件的發(fā)布訂閱模式支持。

          實體

          根據(jù)領(lǐng)域驅(qū)動設(shè)計中實體的定義,一個實體是一個唯一的東西,每一個實體都有一個唯一的業(yè)務(wù)身份標(biāo)識,并且實體具有生命周期,在生命周期內(nèi)實體的狀態(tài)會不斷發(fā)生變化。實體對象的每一次變化都需要使用業(yè)務(wù)規(guī)則進行驗證,以保證實體狀態(tài)的變更是合法有效的。

          實體的通用基類 EntityBase 和 ConcurrentEntityBase。

          實體對象定義

          class Order extends EntityBase<Long> {
          
              @Override
              public Boolean validate() {
                  return null;
              }
          
              @Override
              protected BrokenRuleMessage getBrokenRuleMessages() {
                  return null;
              }
          }

          具有并發(fā)能力(樂觀鎖)的實體對象定義

          class Order extends ConcurrentEntityBase<Long> {
          
              @Override
              public Boolean validate() {
                  return null;
              }
          
              public BrokenRuleMessage getBrokenRuleMessages() {
                  return null;
              }
          }
          1. 實體類型定義繼承自 EntityBase<T> 或 ConcurrentEntityBase<T>,泛型 T 表示實體類唯一業(yè)務(wù)標(biāo)識類型,可以是基礎(chǔ)類型、也可以是復(fù)雜類型
          2. 繼承EntityBase的實體類,需要實現(xiàn) validate() 和 getBrokenRuleMessages() 抽象方法,validate()方法用于對實體對象進行業(yè)務(wù)規(guī)則驗證、getBrokenRuleMessages() 方法用于定義異常業(yè)務(wù)規(guī)則描述信息
          3. ConcurrentEntityBase<T>類繼承自EntityBase<T> ,多出用于進行并發(fā)控制的版本號version和oldVersion字段,version是實體對象本次狀態(tài)變更的最新版本號,oldVersion是實體對象最后一次變更的版本號,最終實現(xiàn)并發(fā)控制還需要數(shù)據(jù)庫樂觀鎖能力一起配合。

          實體業(yè)務(wù)規(guī)則

          實體具有唯一的身份標(biāo)識,在生命周期內(nèi)實體的狀態(tài)會不斷發(fā)生變化,實體業(yè)務(wù)規(guī)則類,負責(zé)保證在實體對象狀態(tài)變化的過程中實體數(shù)據(jù)合法有效,當(dāng)有異常數(shù)據(jù)時,能夠反饋出異常數(shù)據(jù)的描述或具體異常字段信息等。

          業(yè)務(wù)規(guī)則類的基類 EntityRule

          實體業(yè)務(wù)規(guī)則類

          class OrderEntityRule extends EntityRule<Order> {
              // 1 
              public OrderEntityRule() {
                  // 2
                  this.isBlank("pin", OrderBrokenRuleMessages.PIN_IS_EMPTY, "");
          
                  // 3
                  this.addRule("totalPrice", new IRule<Order>() {
                      @Override
                      public boolean isSatisfy(Order model) {
                          return model.getTotalPrice().compareTo(BigDecimal.ZERO) > 0;
                      }
                  }, OrderBrokenRuleMessages.TOTAL_PRICE_ERROR, "");
          
                  // 4
                  this.addRule(new IRule<Order>() {
                      @Override
                      public boolean isSatisfy(Order model) {
                          // 4.1
                          return model.getOrderItemList().size() > 0 && model.getOrderItemList().size() < 100;
                      }
                  }, OrderBrokenRuleMessages.ORDER_ITEM_ERROR, "", new IActiveRuleCondition<Order>() {
                      // 4.2
                      @Override
                      public boolean isActive(Order model) {
                          return model.getStatus() == 1;
                      }
                  });
              }
          }
          
          1. 實體業(yè)務(wù)規(guī)則定義類繼承自EntityRule<T>類,實體業(yè)務(wù)規(guī)則的類名一般按 "<實體名>EntityRule" 來命名,泛型T是要驗證得實體類型。
          2. 實體業(yè)務(wù)規(guī)則初始化在類的構(gòu)造函數(shù)中完成,上面例子中的1處示例,可以根據(jù)實際情況將規(guī)則代碼拆分組織,在構(gòu)造函數(shù)中完成最終組裝。
          3. EntityRule基類提供了幾種方式實現(xiàn)業(yè)務(wù)規(guī)則驗證,基礎(chǔ)的驗證規(guī)則包含以下幾種實現(xiàn) isBlank()、email()、numberShouldGreaterThan()、numberShouldLessThan() 、dateShouldGreaterThan()、dateShouldLessThan()、booleanShouldEqual()、numberShouldEqual() 上面例子中的2處,是一個簡單的例子。
          4. EntityRule還提供了兩更具靈活性的業(yè)務(wù)規(guī)則驗證方法 addRule()、addParamRule(),上面4處示例展示了 addRule() 方法的使用。
          5. addRule的第一個參數(shù)是實現(xiàn)了IRule接口的匿名類,isSatisfy方法實現(xiàn)具體的業(yè)務(wù)規(guī)則驗證,驗證完成后返回true或false,true表示業(yè)務(wù)規(guī)則驗證通過,false表示不通過;方法入?yún)⑹菢I(yè)務(wù)實體對象,如上示例4.1。
          6. addRule最后一個參數(shù),是實現(xiàn)了IActiveRuleCondition接口匿名類,該接口用于控制業(yè)務(wù)規(guī)則參與驗證的條件,當(dāng)不滿足條件時,直接忽略該業(yè)務(wù)規(guī)則 ,isActive方法實現(xiàn)具體控制規(guī)則,返回true表示業(yè)務(wù)規(guī)則生效參與驗證、false表示不參與驗證。如果使用addRule的重載版本,不傳遞IActiveRuleCondition實現(xiàn),則默認該業(yè)務(wù)規(guī)則總是參與驗證。
          7. addParamRule()方法和addRule()功能類似,前者支持參數(shù)化異常消息處理。

          實體業(yè)務(wù)規(guī)則異常描述類

          // 5
          class OrderBrokenRuleMessages extends BrokenRuleMessage {
              // 5.1
              public static final String PIN_IS_EMPTY = "PIN_IS_EMPTY";
              public static final String TOTAL_PRICE_ERROR = "TOTAL_PRICE_ERROR";
              public static final String ORDER_ITEM_ERROR = "ORDER_ITEM_ERROR";
          
              @Override
              protected void populateMessage() {
                  // 5.2
                  this.getMessages().put(PIN_IS_EMPTY, "用戶PIN不能為空");
                  this.getMessages().put(TOTAL_PRICE_ERROR, "訂單總金額不能為0");
                  this.getMessages().put(ORDER_ITEM_ERROR, "訂單商品不能為0且商品數(shù)超過100");
          
              }
          }
          1. 實體業(yè)務(wù)規(guī)則異常描述類用于統(tǒng)一放置實體的異常規(guī)則描述,該類的命名規(guī)則一般按"<實體名>BrokenRuleMessages"。
          2. 該類統(tǒng)一繼承自抽象類 BrokenRuleMessage 并需要實現(xiàn) populateMessage() 抽象方法
          3. 以上示例中 5.1 展示了異常KEY定義的方式,5.2 展示了異常KEY對應(yīng)文字描述信息的書寫方式

          實體業(yè)務(wù)規(guī)則驗證的使用方式

          class Order extends EntityBase<Long> {
          
              // 1
              @Override
              public Boolean validate() {
                  // 1.1
                  return new OrderEntityRule().isSatisfy(this);
              }
          
              // 2
              @Override
              protected BrokenRuleMessage getBrokenRuleMessages() {
                  // 2.2
                  return new OrderBrokenRuleMessages();
              }
          }
          1. 實體業(yè)務(wù)規(guī)則驗證,需要和實體配合一塊使用,以實體為中心展開驗證,一般一個實體只對應(yīng)一個實體業(yè)務(wù)規(guī)則EntityRule

          2. 在實體類中重寫validate()方法,如以上示例中 1.1顯示,也可以自行寫一個validate()的重載,以便實現(xiàn)更加靈活的EntityRule類管理。

          3. 在實體類中,還需要重寫getBrokenRuleMessages(),直接返回實體業(yè)務(wù)規(guī)則異常描述類的一個實例,如以上的 2.2,一般情況下,實體業(yè)務(wù)規(guī)則異常描述類,是線程安全的,因此,也可以定義單例模式,在getBrokenRuleMessages()方法中返回單例對象。

          public class MainTestClass {
              @Test
              public void orderTest() {
                  // 3
                  Order order = new Order();
                  // 4
                  Boolean validate = order.validate();
          
                  if (!validate) {
                      // 5
                      order.getBrokenRules();
                      // 6
                      order.aggregateExceptionCause();
                      // 7
                      order.throwBrokeRuleAggregateException();
                      // 8
                      order.exceptionCause();
                      // 9
                      order.throwBrokenRuleException();
          
                  }
              }
          }
          
          1. 以上單元測試代碼,示例的是對Order對象進行業(yè)務(wù)規(guī)則驗證過程,3 處實例化一個Order對象,4 處調(diào)用實體對象的validate()方法.
          2. validate()方法,返回一個Boolean結(jié)果,true表示驗證通過,false表示驗證失敗
          3. 示例中5、6、7、8、9處展示了各種用于獲取異常信息的處理方式,
            • getBrokenRules() 方法獲取所有異常信息列表
            • aggregateExceptionCause()以BrokeRuleAggregateException的形式返回所有異常信息,
            • throwBrokeRuleAggregateException() 方法直接throw出BrokeRuleAggregateException
            • exceptionCause() 返回所有異常中的第一個,類型是BrokenRuleException
            • throwBrokenRuleException() 直接throw出所有異常中的第一個,類型是BrokenRuleException

          領(lǐng)域事件

          在領(lǐng)域驅(qū)動設(shè)計中,領(lǐng)域事件是對實體對象,由于某一業(yè)務(wù)操作導(dǎo)致實體對象狀態(tài)發(fā)生變化的事實的描述。例如,當(dāng)訂單實體調(diào)用支付payment() 方法后,訂單的狀態(tài)變成已支付,并產(chǎn)生訂單已支付的事件,該事件將交由應(yīng)用服務(wù)層去發(fā)布,相關(guān)業(yè)務(wù)組件將會訂閱訂單已支付事件、并對事件做出相關(guān)的響應(yīng)。

          領(lǐng)域事件定義

          @EventName(value = "OrderPayedEvent", shareTopicName = "")
          class OrderPayedEvent extends BaseDomainEvent {
          
              //還可以有其他的字段
          
              public OrderPayedEvent(long orderId) {
          
                  this.setBusinessId(String.valueOf(orderId));
              }
          
          }
          
          1. 領(lǐng)域事件統(tǒng)一繼承自BaseDomainEvent類,該類有 businessId 字段,值一般是發(fā)生事件的業(yè)務(wù)對象標(biāo)識,事件子類還可以有其他相關(guān)的字段,以便其他業(yè)務(wù)組件能夠根據(jù)事件信息做出不同的處理邏輯。
          2. 領(lǐng)域事件一般描述的是已發(fā)生業(yè)務(wù)操作的實事,所以在類命名上采用過去式的方式 "<實體名><業(yè)務(wù)操作過去式表達>Event" ,如上例中的訂單已支付事件OrderPayedEvent
          3. 領(lǐng)域事件上的注解@EventName是可選項,用于和其它發(fā)布事件的基礎(chǔ)設(shè)施進行交互。shareTopicName 可以用于基礎(chǔ)設(shè)施底層共享的事件發(fā)布通道命名 例如,Kafka中的Topic,可以被多個領(lǐng)域事件對象共享。

          領(lǐng)域事件使用

          class Order extends EntityBase<Long> {
          
              private BigDecimal totalPrice = BigDecimal.ZERO;
              private String comment = "";
              private String pin;
              private int status;
          
              private List<OrderItem> orderItemList;
          
              @Override
              public Boolean validate() {
                  return new OrderEntityRule().isSatisfy(this);
              }
          
              @Override
              protected BrokenRuleMessage getBrokenRuleMessages() {
                  return new OrderBrokenRuleMessages();
              }
          
              /**
               * 訂單支付業(yè)務(wù)操作
               *
               * @return 返回訂單已支持事件
               */
              public OrderPayedEvent payment() {
                  this.status = 3;
                  return new OrderPayedEvent(this.getId());
              }
          }
          1. 領(lǐng)域事件需要結(jié)合實體業(yè)務(wù)操作方法一起使用,實體上的業(yè)務(wù)操作方法在操作完成后,返回對應(yīng)的事件對象,如果操作失敗,返NULL,表示沒有事件發(fā)生。

          應(yīng)用服務(wù)層

          應(yīng)用服務(wù)層,在領(lǐng)域驅(qū)動設(shè)計分層架構(gòu)中的角色是用于實現(xiàn)協(xié)作、統(tǒng)籌和編排領(lǐng)域模型以及基礎(chǔ)設(shè)施層的各種業(yè)務(wù)組件類,以實現(xiàn)相關(guān)業(yè)務(wù)功能。此外,對實體對象的各種操作,都必須經(jīng)由應(yīng)用服務(wù)層處理,任何其它地方都不能私自處理。應(yīng)用服務(wù)層,也是用于保證實體對象邏輯一致性(強一致,一般指數(shù)據(jù)庫事務(wù))和發(fā)布實體對象生成的領(lǐng)域事件的地方。

          應(yīng)用服務(wù)層是極容易出現(xiàn)代碼壞味道的地方,應(yīng)用服務(wù)層是協(xié)作者,不是業(yè)務(wù)決策者。在該層出現(xiàn)業(yè)務(wù)決策類的代碼段時,需要格外注意。

          通過將業(yè)務(wù)決策代碼放回到領(lǐng)域?qū)右约巴ㄟ^發(fā)布訂閱模式將各業(yè)務(wù)組件進行解耦,可以使該層清晰職責(zé)和結(jié)構(gòu)。

          實體操作應(yīng)用服務(wù)類定義

          // 1
          class OrderApplicationService extends BaseApplication {
          
              private IOrderRepository orderRepository;
          
              // 2
              public OrderApplicationService() {
                  this.initSubscriber();
              }
          
              public void payment(long orderId) {
                  // 3
                  Order order = this.orderRepository.findByOrderId(orderId);
                  if (order != null) {
                      // 4
                      OrderPayedEvent orderPayedEvent = order.payment();
                      // 5
                      if (order.validate()) {
                          // 6
                          this.orderRepository.update(order);
                          // 7
                          this.publishEvent(orderPayedEvent);
                      } else {
                          // 8
                          throw order.exceptionCause();
                      }
                  }
              }
          }
          1. 在應(yīng)用服務(wù)層,需要有一個對實體操作的服務(wù)類(一個實體對應(yīng)一個),該類的命名規(guī)則一般使用<實體>ApplicationService,并且該類需要繼承BaseApplication。如,上例中 1處 OrderApplicationService
          2. BaseApplication內(nèi)部默認使用了一個基本線程池的發(fā)布訂閱能力實現(xiàn),ThreadPoolTaskDomainEventManager() ,也可以自行實現(xiàn)IDomainEventManager接口,替換默認實現(xiàn)。如,可以使用Kafka、RabbitMQ做為底層發(fā)布訂閱能力支持,以保證更高的可靠性。使用BaseApplication帶構(gòu)造函數(shù)版本傳入自定義實現(xiàn)。
          3. 實體操作服務(wù)類中的方法,用于實現(xiàn)業(yè)務(wù)用例,如上例中 payment()方法,是一個典型應(yīng)用服務(wù)層實現(xiàn)用例的寫法。代碼3處首先從數(shù)據(jù)倉庫中查詢出訂單實體對象,代碼4處,調(diào)用實體類payment() 實現(xiàn)實體對象的狀態(tài)變更,并返回訂單已支付的領(lǐng)域事件,代碼5處,對訂單實體對象的最終狀態(tài)進行合法性驗證,如果驗證通過,代碼6處實現(xiàn)此實體對象的持久化, 并在代碼7處,發(fā)布訂單已經(jīng)支付的領(lǐng)域事件。如果訂單驗證不通過,則在代碼8處,拋出業(yè)務(wù)規(guī)則異常。

          領(lǐng)域事件訂閱實現(xiàn)

          class OrderApplicationService extends BaseApplication {
          
              private IOrderRepository orderRepository;
              public OrderApplicationService() {
                  // 1
                  this.initSubscriber();
              }
              public void payment(long orderId) {
                  //發(fā)布OrderPayedEvent事件
              }
              
              private void initSubscriber() {
                  // 2
                  this.registerDomainEvent(OrderPayedEvent.class);
                  // 3
                  this.registerSubscriber(new IDomainEventSubscriber<OrderPayedEvent>() {
                      @Override
                      public Class<OrderPayedEvent> subscribedToEventType() {
                          return OrderPayedEvent.class;
                      }
          
                      @Override
                      public void handleEvent(OrderPayedEvent aDomainEvent) {
                          //調(diào)用發(fā)送通知用戶支付成功的消息服務(wù)
                      }
                  }, "sendSMS");
                  // 4
                  this.registerSubscriber(new IDomainEventSubscriber<OrderPayedEvent>() {
                      @Override
                      public Class<OrderPayedEvent> subscribedToEventType() {
                          return OrderPayedEvent.class;
                      }
          
                      @Override
                      public void handleEvent(OrderPayedEvent aDomainEvent) {
                          //調(diào)用通知庫房準(zhǔn)備生產(chǎn)服務(wù)領(lǐng)域事件對上的注解
                      }
                  }, "noticeWarehouse");
              }
          }
          1. 領(lǐng)域事件訂閱的定義,可以在實體操作應(yīng)用服務(wù)類里實現(xiàn),如以上的示例。為了放置該類代碼過的,也可以拆分到單獨的類里。
          2. 以上代碼是在 1處調(diào)用initSubscriber()私有方法,實現(xiàn)領(lǐng)域事件訂閱的初始化。
          3. 在代碼2處,首先需要注冊領(lǐng)域事件,如果有多個,需要注冊多次,調(diào)用registerDomainEvent()方法。
          4. 代碼3、4處,是兩個對OrderPayedEvent 事件的訂閱,分別用于不同處理邏輯。
          5. 訂閱代碼需要調(diào)用registerSubscriber()方法,該方法有兩個參數(shù),第一個參數(shù)是實現(xiàn)了IDomainEventSubscriber<T>接口的匿名類。泛型T 是要訂閱的領(lǐng)域事件類型。實現(xiàn)方法subscribedToEventType()返回具體的事件類型,handleEvent()方法用于調(diào)用對應(yīng)的響應(yīng)組件,以實現(xiàn)相應(yīng)的業(yè)務(wù)操作,如上例的 "調(diào)用發(fā)送通知用戶支付成功的消息服務(wù)",第二個參數(shù)是訂閱的唯一名字,在同一個事件下,訂閱名字不能重復(fù)。
          6. registerSubscriber()方法,還有一個三個參數(shù)的重載,第三個參數(shù)IExecuteCondition接口的實現(xiàn),這個參數(shù)用于判斷是否可以執(zhí)行,這個接口需要實現(xiàn)isExecute()方法,返回true表示訂閱可以執(zhí)行,false表示訂閱不執(zhí)行,IExecuteCondition 是個泛型接口,T 是對應(yīng)的領(lǐng)域事件類型。

          基礎(chǔ)設(shè)施層

          在領(lǐng)域驅(qū)動設(shè)計中,基礎(chǔ)設(shè)施層提供具體技術(shù)上的支撐,實體對象數(shù)據(jù)的數(shù)據(jù)庫持久化,面向查詢的數(shù)據(jù)持久化(ES)、面向緩存的數(shù)據(jù)刷新(Redis)、外部系統(tǒng)遠程接口調(diào)用以及發(fā)布供外部系統(tǒng)處理的消息等。 基礎(chǔ)設(shè)施層主要有以下幾個特點

          1. 基礎(chǔ)設(shè)施層的類都相對單純,沒有邏輯判斷代碼
          2. 類和類之間基本相互獨立,無關(guān)聯(lián)性。
          3. 基礎(chǔ)設(shè)施層的類,一般都會實現(xiàn)來自領(lǐng)域模型層或應(yīng)用服務(wù)層的接口定義(依賴倒置)
          4. 該層的代碼單元測試相對容易,單元測試覆蓋率高,可以達到90%以上。
          5. 該層的具體實現(xiàn)類可以很容易被替換,例如 sqlserver替換成mysql
          6. 該層還具有防腐層的作用,例如,遠程服務(wù)接口調(diào)用,將遠程接口返回的對象轉(zhuǎn)換成領(lǐng)域內(nèi)的對象。
          class OrderRepository implements IOrderRepository{
          
              @Override
              public Order findByOrderId(long orderId) {
                  //執(zhí)行數(shù)據(jù)庫查詢,返回領(lǐng)域模型對象
                  return null;
              }
          
              @Override
              public void update(Order order) {
                  // 1
                  // 持久化領(lǐng)域模型數(shù)據(jù)
              }
          }
          
          1. 以上代碼 OrderRepository 是基礎(chǔ)設(shè)施層持久化實體對象數(shù)據(jù)的一個示例,該類實現(xiàn)一個 IOrderRepository接口,該接口定義在領(lǐng)域模型層和對應(yīng)的實體在一個包下。
          2. 在代碼1處,在對order對象持久化時 ,不做任何業(yè)務(wù)邏輯上的判斷,直接將數(shù)據(jù)update到數(shù)據(jù)庫,業(yè)務(wù)規(guī)則屬于領(lǐng)域模型層的職責(zé)。

          分層結(jié)構(gòu)以及層之間的依賴關(guān)系

          領(lǐng)域驅(qū)動設(shè)計,將一個系統(tǒng)或微服務(wù)劃分成四層,每一層都是不同的角色,有不同的職責(zé)。

          • 領(lǐng)域模型層,是整個系統(tǒng)的核心,是對業(yè)務(wù)的建模。它決定這個系統(tǒng)『我是誰』的問題。
          • 基礎(chǔ)設(shè)施層,是整個系統(tǒng)的技術(shù)底座,該層與其它層通過接口保持聯(lián)系,可通過不同的接口實現(xiàn),來對底坐進行替換、優(yōu)化和升級。
          • 應(yīng)用服務(wù)層,通過將領(lǐng)域?qū)雍突A(chǔ)設(shè)施層的各種組件進行編排組裝以實現(xiàn)業(yè)務(wù)用例。
          • 用戶接口層,將系統(tǒng)提供的功能通過不同方式暴露出去,供最終用戶或其他系統(tǒng)使用。rest api,dubbo接口、UI等

          上下結(jié)構(gòu)分層視圖

          DDD分層結(jié)構(gòu)

          上圖藍色線體現(xiàn)了各層之間的調(diào)用關(guān)系,各層的調(diào)用并不會嚴格的經(jīng)過每一層。

          • 圖中所示一個調(diào)用從用戶接口層直接調(diào)用了基礎(chǔ)設(shè)施層,這種情況一般是,查數(shù)據(jù)給外部系統(tǒng)使用,因為不會對業(yè)務(wù)數(shù)據(jù)做變更,所以不需要經(jīng)過應(yīng)用服務(wù)層和領(lǐng)域模型層。
          • 圖中所示的另一個調(diào)用分別經(jīng)過了,應(yīng)用服務(wù)層、領(lǐng)域模型層和基礎(chǔ)設(shè)施層,這種情況一般是,一個業(yè)務(wù)操作,需要對領(lǐng)域模層的實體進行變更,應(yīng)用服務(wù)層需要裝載實體對象數(shù)據(jù)到內(nèi)存,然后調(diào)用實體對象上的業(yè)務(wù)方法,接下來執(zhí)行業(yè)務(wù)規(guī)則驗證,通過后,調(diào)用基礎(chǔ)設(shè)施層進行相關(guān)持久操作等。
          • 圖中所示的用戶接口層直接調(diào)用領(lǐng)域模型層,場景一般是需要把業(yè)務(wù)邏輯算法或規(guī)則暴露給外部使用時。

          上圖紅色線體現(xiàn)了基礎(chǔ)設(shè)施層和各層之間的依賴關(guān)系。

          • 一般來說,如果A需要使用B的提供的能力,那么A就需要依賴B,在上圖中幾乎所有層都需要依賴基礎(chǔ)設(shè)施層,但是依賴關(guān)系確實倒過來的,采用的是依賴倒置原則
          • 通過依賴倒置原則,保證了基礎(chǔ)設(shè)施層可以被進行替換、優(yōu)化和升級。
          • 采用依賴倒置的方式,一般都會在領(lǐng)域模型層、應(yīng)用服務(wù)層或用戶接口層進行接口定義,由基礎(chǔ)設(shè)施層對接口進行實現(xiàn)。
          • 接口的定義一般都和接口所管理對象放置在同一個包里。

          以領(lǐng)域模型為核心的視圖

          DDD分層結(jié)構(gòu)

          領(lǐng)域模型是整個系統(tǒng)的核心和靈魂,所有其它方面都會圍繞領(lǐng)域模型開展。當(dāng)我們需要了解一個系統(tǒng)的時候 ,一般也會從領(lǐng)域模型做為開端。

          瀏覽 13
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          編輯 分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          編輯 分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美第一视频 | 日韩精品一区二区三区四区五区六区 | 色婷婷在线无码精品秘 人口传媒 | 国内乱伦自拍 | 直播天堂久久 |