• 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的查询规约

    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

    实现了转账领域服务的逻辑。

    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

  • 相关阅读:
    【luogu3768】简单的数学题【杜教筛】【欧拉函数】
    【bzoj3589】动态树【树链剖分】【线段树】
    【bzoj4386】[POI2015]Wycieczki【矩阵快速幂】【倍增】
    【bzoj2186】[Sdoi2008]沙拉公主的困惑 【线性筛】【容斥原理】
    【bzoj3884】上帝与集合的正确用法 【欧拉函数】
    【bzoj4417】[Shoi2013]超级跳马 【矩阵快速幂】
    【bzoj3435】【uoj#55】[WC2014]紫荆花之恋 【动态树分治】【平衡树】
    【bzoj3681】Arietta 【网络流】【主席树】【启发式合并】
    【bzoj1532】[POI2005]Kos-Dicing 【网络流】【二分】
    【bzoj1565】[NOI2009]植物大战僵尸 【网络流】【最大权闭合子图】
  • 原文地址:https://www.cnblogs.com/net-yuan/p/NLayerAppV3-Domain.html
Copyright © 2020-2023  润新知