DDD的方式获取外部信息 [英] DDD Approach to Access External Information

查看:209
本文介绍了DDD的方式获取外部信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个现有的银行应用程序类,如下图所示。该银行帐户可以是SavingsBankAccount或FixedBankAccount的。有称为IssueLumpSumInterest的操作。为FixedBankAccount,天平需要更新只有当帐户的拥有者没有其他帐户。

这需要在FixedBankAccount对象了解账户所有人的其他账户。如何通过以下要做到这一点的固体 / DDD / GRASP /信息专家模式?

 命名空间ApplicationServiceForBank
{

公共类BankAccountService
{
    RepositoryLayer.IRepository< RepositoryLayer.BankAccount> accountRepository;
    ApplicationServiceForBank.IBankAccountFactory bankFactory;

    公共BankAccountService(RepositoryLayer.IRepository< RepositoryLayer.BankAccount>回购,IBankAccountFactory bankFact)
    {
        accountRepository =回购;
        bankFactory = bankFact;
    }

    公共无效IssueLumpSumInterest(INT acccountID)
    {
        RepositoryLayer.BankAccount oneOfRepositroyAccounts = accountRepository.FindByID(P => p.BankAccountID == acccountID);

        INT OWNERID =(INT)oneOfRepositroyAccounts.AccountOwnerID;
        IEnumerable的< RepositoryLayer.BankAccount> accountsForUser = accountRepository.FindAll(P => p.BankUser.UserID == OWNERID);

        DomainObjectsForBank.IBankAccount domainBankAccountObj = bankFactory.CreateAccount(oneOfRepositroyAccounts);

        如果(domainBankAccountObj!= NULL)
        {
            domainBankAccountObj.BankAccountID = oneOfRepositroyAccounts.BankAccountID;
            domainBankAccountObj.AddInterest();

            this.accountRepository.UpdateChangesByAttach(oneOfRepositroyAccounts);
            //oneOfRepositroyAccounts.Balance = domainBankAccountObj.Balance;
            this.accountRepository.SubmitChanges();
        }
    }
}

公共接口IBankAccountFactory
{
    DomainObjectsForBank.IBankAccount CreateAccount(RepositoryLayer.BankAccount repositroyAccount);
}

公共类MySimpleBankAccountFactory:IBankAccountFactory
{
    公共DomainObjectsForBank.IBankAccount CreateAccount(RepositoryLayer.BankAccount repositroyAccount)
    {
        DomainObjectsForBank.IBankAccount ACC = NULL;

        如果(String.Equals(repositroyAccount.AccountType,固定))
        {
            ACC =新DomainObjectsForBank.FixedBankAccount();
        }

        如果(String.Equals(repositroyAccount.AccountType,储蓄))
        {
            // ACC =新DomainObjectsForBank.SavingsBankAccount();
        }

        返回ACC;
    }
}

}

命名空间DomainObjectsForBank
{

公共接口IBankAccount
{
    INT BankAccountID {获得;组; }
    双平衡{获得;组; }
    字符串AccountStatus {获得;组; }
    无效FreezeAccount();
    无效AddInterest();
}

公共类FixedBankAccount:IBankAccount
{
    公众诠释BankAccountID {获得;组; }
    公共字符串AccountStatus {获得;组; }
    公共双平衡{获得;组; }

    公共无效FreezeAccount()
    {
        AccountStatus =冻结;
    }

    公共无效AddInterest()
    {
        //要做到:平衡需要更新仅如果这个人有没有其他帐户。
        余额=余额+(平衡* 0.1);
    }
}

}
 

阅读

  1. <一个href="http://stackoverflow.com/questions/11759120/issue-in-using-composition-for-is-a-relationship">Issue使用成分为是 - 个关系

  2. 实现业务逻辑(LINQ到SQL) http://msdn.microsoft.com/en-us/library/bb882671.aspx

  3. 架构设计的LINQ to SQL应用程序

  4. 探索N层架构使用LINQ到SQL <一href="http://randolphcabral.word$p$pss.com/2008/05/08/exploring-n-tier-architecture-with-linq-to-sql-part-3-of-n/" rel="nofollow">http://randolphcabral.word$p$pss.com/2008/05/08/exploring-n-tier-architecture-with-linq-to-sql-part-3-of-n/

  5. <一个href="http://stackoverflow.com/questions/1323070/confusion-between-dtos-linq2sql-and-class-objects">Confusion的DTO(LINQ2SQL)和类对象之间!

  6. <一个href="http://stackoverflow.com/questions/652585/domain-driven-design-linq-to-sql-how-do-you-delete-parts-of-an-aggregate">Domain驱动设计(LINQ到SQL) - 如何删除聚集的部位

解决方案

从阅读您的要求,这里是我会怎么做:

  //应用服务 - 通过UI消耗
公共类的Account:IAccountService
{
    私人只读IAccountRepository _accountRepository;
    私人只读ICustomerRepository _customerRepository;

    公共ApplicationService(IAccountRepository accountRepository,ICustomerRepository customerRepository)
    {
        _accountRepository = accountRepository;
        _customerRepository = customerRepository;
    }

    公共无效IssueLumpSumInterestToAccount(GUID帐户ID)
    {
        使用(IUnitOfWork的UnitOfWork = UnitOfWorkFactory.Create())
        {
            帐户帐户= _accountRepository.GetById(帐户ID);
            客户客户= _customerRepository.GetById(account.CustomerId);

            account.IssueLumpSumOfInterest(客户);

            _accountRepository.Save(账户);
        }
    }
}

公共类客户
{
    私人列表&LT;的Guid&GT; _accountIds;

    公开的IEnumerable&LT;的Guid&GT; AccountIds
    {
        {返回_accountIds.AsReadOnly();}
    }
}

公共抽象类账户
{
    公共抽象无效IssueLumpSumOfInterest(客户的客户);
}

公共类FixedAccount:帐户
{
    公众覆盖无效IssueLumpSumOfInterest(客户的客户)
    {
        如果(customer.AccountIds.Any(ID =&GT;!ID = this._accountId))
            抛出新的异常(包干不能发给定期账户,其中客户有其他帐户);

        // code到这里问题的关注
    }
}

公共类SavingsAccount:帐户
{
    公众覆盖无效IssueLumpSumOfInterest(客户的客户)
    {
        // code到这里问题的关注
    }
}
 

  1. IssueLumpSumOfInterest 的帐户总方法需要客户聚集,以帮助决定是否应该发出的兴趣。
  2. 在客户总包含账户ID列表 - 不会一个账户聚集的名单
  3. 在基类的帐户有一个多态的方法 - 在FixedAccount检查,客户没有任何其他账户 - 的SavingsAccount不会做这种检查

I have an existing bank application classes as shown below. The banks account can be of SavingsBankAccount or FixedBankAccount. There is an operation called IssueLumpSumInterest. For FixedBankAccount, the balance need to be updated only if the owner of the account has no other account.

This demands the FixedBankAccount object to know about other accounts of the account owner. How to do this by following SOLID/DDD/GRASP/Information Expert pattern?

namespace ApplicationServiceForBank
{

public class BankAccountService
{
    RepositoryLayer.IRepository<RepositoryLayer.BankAccount> accountRepository;
    ApplicationServiceForBank.IBankAccountFactory bankFactory;

    public BankAccountService(RepositoryLayer.IRepository<RepositoryLayer.BankAccount> repo, IBankAccountFactory bankFact)
    {
        accountRepository = repo;
        bankFactory = bankFact;
    }

    public void IssueLumpSumInterest(int acccountID)
    {
        RepositoryLayer.BankAccount oneOfRepositroyAccounts = accountRepository.FindByID(p => p.BankAccountID == acccountID);

        int ownerID = (int) oneOfRepositroyAccounts.AccountOwnerID;
        IEnumerable<RepositoryLayer.BankAccount> accountsForUser = accountRepository.FindAll(p => p.BankUser.UserID == ownerID);

        DomainObjectsForBank.IBankAccount domainBankAccountObj = bankFactory.CreateAccount(oneOfRepositroyAccounts);

        if (domainBankAccountObj != null)
        {
            domainBankAccountObj.BankAccountID = oneOfRepositroyAccounts.BankAccountID;
            domainBankAccountObj.AddInterest();

            this.accountRepository.UpdateChangesByAttach(oneOfRepositroyAccounts);
            //oneOfRepositroyAccounts.Balance = domainBankAccountObj.Balance;
            this.accountRepository.SubmitChanges();
        }
    }
}

public interface IBankAccountFactory
{
    DomainObjectsForBank.IBankAccount CreateAccount(RepositoryLayer.BankAccount repositroyAccount);
}

public class MySimpleBankAccountFactory : IBankAccountFactory
{
    public DomainObjectsForBank.IBankAccount CreateAccount(RepositoryLayer.BankAccount repositroyAccount)
    {
        DomainObjectsForBank.IBankAccount acc = null;

        if (String.Equals(repositroyAccount.AccountType, "Fixed"))
        {
            acc = new DomainObjectsForBank.FixedBankAccount();
        }

        if (String.Equals(repositroyAccount.AccountType, "Savings"))
        {
            //acc = new DomainObjectsForBank.SavingsBankAccount();
        }

        return acc;
    }
}

}

namespace DomainObjectsForBank
{

public interface IBankAccount
{
    int BankAccountID { get; set; }
    double Balance { get; set; }
    string AccountStatus { get; set; }
    void FreezeAccount();
    void AddInterest();
}

public class FixedBankAccount : IBankAccount
{
    public int BankAccountID { get; set; }
    public string AccountStatus { get; set; }
    public double Balance { get; set; }

    public void FreezeAccount()
    {
        AccountStatus = "Frozen";
    }

    public void AddInterest()
    {
        //TO DO: Balance need to be updated only if the person has no other accounts.
        Balance = Balance + (Balance * 0.1);
    }
}

}

READING

  1. Issue in using Composition for "is – a " relationship

  2. Implementing Business Logic (LINQ to SQL) http://msdn.microsoft.com/en-us/library/bb882671.aspx

  3. Architecting LINQ to SQL applications

  4. Exploring N-Tier Architecture with LINQ to SQL http://randolphcabral.wordpress.com/2008/05/08/exploring-n-tier-architecture-with-linq-to-sql-part-3-of-n/

  5. Confusion between DTOs (linq2sql) and Class objects!

  6. Domain Driven Design (Linq to SQL) - How do you delete parts of an aggregate?

解决方案

From reading your requirement, here is how I would do it:

//Application Service - consumed by UI
public class AccountService : IAccountService
{
    private readonly IAccountRepository _accountRepository;
    private readonly ICustomerRepository _customerRepository;

    public ApplicationService(IAccountRepository accountRepository, ICustomerRepository customerRepository)
    {
        _accountRepository = accountRepository;
        _customerRepository = customerRepository;
    }

    public void IssueLumpSumInterestToAccount(Guid accountId)
    {
        using (IUnitOfWork unitOfWork = UnitOfWorkFactory.Create())
        {
            Account account = _accountRepository.GetById(accountId);
            Customer customer = _customerRepository.GetById(account.CustomerId);

            account.IssueLumpSumOfInterest(customer);

            _accountRepository.Save(account);
        }
    }
}

public class Customer
{
    private List<Guid> _accountIds;

    public IEnumerable<Guid> AccountIds
    {
        get { return _accountIds.AsReadOnly();}
    }
}

public abstract class Account
{
    public abstract void IssueLumpSumOfInterest(Customer customer);
}

public class FixedAccount : Account
{
    public override void  IssueLumpSumOfInterest(Customer customer)
    {
        if (customer.AccountIds.Any(id => id != this._accountId))
            throw new Exception("Lump Sum cannot be issued to fixed accounts where the customer has other accounts");

        //Code to issue interest here
    }
}   

public class SavingsAccount : Account
{
    public override void  IssueLumpSumOfInterest(Customer customer)
    {
        //Code to issue interest here
    }
}

  1. The IssueLumpSumOfInterest method on the Account aggregate requires the Customer aggregate to help decide whether interest should be issued.
  2. The customer aggregate contains a list of account IDs - NOT a list of account aggregates.
  3. The base class 'Account' has a polymorphic method - the FixedAccount checks that the customer doesn't have any other accounts - the SavingsAccount doesn't do this check.

这篇关于DDD的方式获取外部信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆