【问题标题】:How should services be implemented with domain driven design?应该如何使用领域驱动设计来实现服务?
【发布时间】:2017-12-17 12:15:06
【问题描述】:

在遵循域驱动设计时,实际实现服务类的最佳方式是什么?

例如说我想要一个AccountService 可以用来将资金从一个帐户转移到另一个帐户?以下哪项(如果有)是实现此目的的最佳方式?

public class AccountService1
{
    private IAccountRepository _accountRepo;

    public AccountService1(IAccountRepository accountRepo)
    {
        _accountRepo = accountRepo;
    }

    public void TransferFunds(double ammount, int sourceAccountNumber, int targetAccountNumber)
    {
        //FUNDS TRANSFER CODE
    }
}

public class AccountService2
{
    public void TransferFunds(double ammount, Account sourceAccount, Account targetAccount)
    {
        //FUNDS TRANSFER CODE
    }
}


public static class AccountService3
{
    public static void TransferFunds(double amount, Account sourceAccount, Account targetAccount)
    {
        //FUNDS TRANSFER CODE
    }
}

public static class AccountService4
{
    public static void TransferFunds(double amount, int sourceAccountNumber, int targetAccountNumber, IAccountRepository repository)
    {
        //FUNDS TRANSFER CODE
    }
}

【问题讨论】:

    标签: domain-driven-design ddd-service


    【解决方案1】:

    你列出的每一种方式都会导致一个贫乏的领域。

    是否有某些原因它不能成为您帐户实体上的实例方法?

    public class Account {
        public void Transfer(decimal amount, Account recipient);
    }
    

    【讨论】:

      【解决方案2】:

      不清楚您的示例是应用程序服务还是域服务。示例 1 是应用程序服务的外观,示例 2 是域服务的外观。放在一起,它看起来像这样:

      public class AccountApplicationService
      {
          private IAccountRepository _accountRepo;
      
          public AccountApplicationService(IAccountRepository accountRepo)
          {
              _accountRepo = accountRepo;
          }
      
          public void TransferFunds(double ammount, int sourceAccountNumber, int targetAccountNumber)
          {
              Account sourceAccount = _accountRepo.GetById(sourceAccountNumber);
              Account targetAccount = _accountRepo.GetById(targeteAccountNumber);
      
              IAccountDomainService accDomService = new AccountDomainService();
      
              accDomService.TransferFunds(ammount, sourceAccount, targetAccount);
      
              using(Transaction tran = _accountRepo.BeginTransaction()) //note: pseudo code.
              {
                   _accountRepo.Save(sourceAccount);
                   _accountRepo.Save(targetAccount);
                   tran.Commit();
              }
          }
      }
      

      【讨论】:

        【解决方案3】:

        您的第一个实施是最佳选择。但是,您还应该在 Account 类本身上实现一个 Transfer 方法,该方法也接受一个金额和一个目标 Account 实例。在这种情况下,服务的作用是使用存储库加载 Account 实例、保存它们、管理工作单元,以及提供对可能需要的任何外部服务的访问。 Account类的Transfer方法的作用是保护Account类自身内部数据的完整性,保证一致性,抛出异常等。

        class Account {
        
          public string State { get; private set; } 
        
          public decimal Total { get; private set; } 
        
          public void Transfer(decimal amount, Account dest) {
             if (amount > this.Total) throw Exception();
        
             if (this.State == "Closed") throw Exception();
        
             this.Total -= amount;
             dest.Total += amount;
        
          }
        }
        

        因此,Account 类定义了哪些操作是可能的,而服务层是在域层上操作的,因此涉及所有操作职责。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-08-18
          • 2019-06-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多