天天看點

NLayerAppV3--DDD之領域層

回顧:NLayerAppV3是一個使用.net 2.1實作的經典DDD的分層架構的項目。

NLayerAppV3是在NLayerAppV2的基礎上,使用.net core2.1進行重新建構的;它包含了開發人員和架構師都可以重用的DDD層。

Github位址:https://github.com/cesarcastrocuba/nlayerappv3

上一篇,介紹了NLayerAppV3項目Infrastructure(基礎設施層)的Cross-Cutting部分,文章位址:https://www.cnblogs.com/net-yuan/p/NLayerAppV3-Infrastructure_CrossCutting.html

NLayerAppV3的基礎結構層一共分為兩個部分。處理資料相關的基礎元件Data和Cross-Cutting的基礎元件。

處理資料相關的基礎元件Data主要包含UOW和倉儲的實作;

Cross-Cutting的基礎元件目前主要包含資料擴充卡、國際化、驗證;

這篇本來應該介紹Infrastructure(基礎設施層)的Data部分。

可是倉儲的具體實作是放在基礎結構層的,而倉儲的接口則是放在領域模型層的。

是以,我們就先介紹領域層Domain。

NLayerAppV3項目的Domain(領域層)分為兩個部分:Seedwork和BoundedContext

Seedwork部分定義了實體的契約、實體的基類、值對象的基類、倉儲的契約、UOW的契約、規約等。

BoundedContext部分定義了聚合相關,聚合、值對象、規約的具體實作、倉儲的契約、領域服務等。

以下描述引用自何老大的博文:

聚合包裝一組高度相關的對象,作為一個資料修改的單元。

聚合最外層的對象稱為聚合根,它是一個實體。聚合根劃分出一個清晰的邊界,聚合根外部的對象,不能直接通路聚合根内部對象,如果需要通路内部對象,必須首先通路聚合根,再導航到聚合的内部對象。

聚合代表很強的包含關系,聚合内部的對象脫離了聚合,應該是毫無意義的,或不是你真正關注的,它是聚合的一個組成部分,這與UML中的組成聚合概念相近。

有關聚合的相關知識可以檢視何老大的博文 https://www.cnblogs.com/xiadao521/p/4141904.html

以BankAccount聚合來看,BankAccount是聚合根,包含卡号BankAccountNumber這樣的值對象,BankAccountNumber由國家或者地區銀行編号、檢查位等構成;Balance金額、Locked是否鎖定、Customer使用者實體、BankAccountActivity賬戶活動的集合等等、還包含鎖定、解鎖、存款等行為。這是一個充血的模型。

BankAccountFactory是建立聚合BankAccount的工廠,它負責建立BankAccount。

BankAccountSpecifications封裝了BankAccount的查詢規約

NLayerAppV3--DDD之領域層
NLayerAppV3--DDD之領域層
public static class BankAccountSpecifications
    {
        /// <summary>
        /// Specification for bank accounts with number like to <paramref name="ibanNumber"/>
        /// </summary>
        /// <param name="ibanNumber">The bank account number</param>
        /// <returns>Associated specification</returns>
        public static ISpecification<BankAccount> BankAccountIbanNumber(string ibanNumber)
        {
            Specification<BankAccount> specification = new TrueSpecification<BankAccount>();

            if (!String.IsNullOrWhiteSpace(ibanNumber))
            {
                specification &= new DirectSpecification<BankAccount>((b) => b.Iban
                                                                              .ToLower()
                                                                              .Contains(ibanNumber.ToLower()));
            }

            return specification;
        }
    }      

View Code

 IBankAccountRepository提供了BankAccount的倉儲契約

IBankTransferService提供了轉賬的領域服務契約,有一個轉賬方法

void PerformTransfer(decimal amount, BankAccount originAccount, BankAccount destinationAccount);
      

BankTransferService實作了IBankTransferService

實作了轉賬領域服務的邏輯。

NLayerAppV3--DDD之領域層
NLayerAppV3--DDD之領域層
public void PerformTransfer(decimal amount, BankAccount originAccount, BankAccount destinationAccount)
        {
            if (originAccount != null && destinationAccount != null)
            {
                var messages = LocalizationFactory.CreateLocalResources();

                if (originAccount.BankAccountNumber == destinationAccount.BankAccountNumber) // if transfer in same bank account
                    throw new InvalidOperationException(messages.GetStringResource(LocalizationKeys.Domain.exception_CannotTransferMoneyWhenFromIsTheSameAsTo));

                // Check if customer has required credit and if the BankAccount is not locked
                if (originAccount.CanBeWithdrawed(amount))
                {
                    //Domain Logic
                    //Process: Perform transfer operations to in-memory Domain-Model objects        
                    // 1.- Charge money to origin acc
                    // 2.- Credit money to destination acc

                    //Charge money
                    originAccount.WithdrawMoney(amount, string.Format(messages.GetStringResource(LocalizationKeys.Domain.messages_TransactionFromMessage), destinationAccount.Id));

                    //Credit money
                    destinationAccount.DepositMoney(amount, string.Format(messages.GetStringResource(LocalizationKeys.Domain.messages_TransactionToMessage), originAccount.Id));
                }
                else
                    throw new InvalidOperationException(messages.GetStringResource(LocalizationKeys.Domain.exception_BankAccountCannotWithdraw));
            }
        }      

View Code

參考: dax.net https://www.cnblogs.com/daxnet/archive/2011/06/07/2074451.html

            何鎮汐 https://www.cnblogs.com/xiadao521/p/4141904.html