如何使用DDD / CQRS写功能 [英] How to write functionality using DDD / CQRS

查看:180
本文介绍了如何使用DDD / CQRS写功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个银行帐户域如下所示。可以有SavingsAccount,LoanAccount,FixedAccount等。一个用户可以拥有多个账户。我需要添加一个新的功能 - 让所有账户的用户。凡应的功能写又如何呢?

这将是巨大的,如果解决方案遵循SOLID原则(开闭原则,...)和DDD。

任何重构这将使code更好是值得欢迎的。

注:AccountManipulator将使用一个网站的客户端通过Web服务

 命名空间BankAccountBL
{
公共类AccountManipulator
{
    //是否应该beprivate还是公开?
    私人IAccount ACC;

    公共AccountManipulator(INT使用accountNumber)
    {
        ACC = AccountFactory.GetAccount(使用accountNumber);
    }

    公共无效FreezeAccount()
    {
        acc.Freeze();
    }

}

公共接口IAccount
{
    无效冻结();
}

公共类AccountFactory
{
    公共静态IAccount是getAccount(INT使用accountNumber)
    {
        返回新SavingsAccount(使用accountNumber);
    }
}

公共类SavingsAccount:IAccount
{
    公共SavingsAccount(INT使用accountNumber)
    {

    }

    公共无效冻结()
    {

    }
}
}
 

阅读:

  1. 当使用CQRS设计模式?

  2. <一个href="http://stackoverflow.com/questions/596285/in-domain-driven-design-would-it-be-a-violation-of-ddd-to-put-calls-to-other-ob?lq=1">In领域驱动设计,会是违反DDD的把电话给其他对象的repostiories域中的对象?

  3. <一个href="http://stackoverflow.com/questions/1264944/refactoring-domain-logic-that-accesses-repositories-in-a-legacy-system?lq=1">Refactoring访问资源库中的遗留系统

  4. 域逻辑
  5. <一个href="http://stackoverflow.com/questions/4146410/which-of-these-examples-re$p$psent-correct-use-of-ddd?lq=1">Which这些例子再次present正确使用DDD的?

  6. 良好的领域驱动设计样本

  7. <一个href="http://stackoverflow.com/questions/1230571/advantage-of-creating-a-generic-repository-vs-specific-repository-for-each-obje?lq=1">Advantage中创建一个通用存储库与特定的资源库为每个对象?

解决方案

首先,要真正回答你的问题很重要,要知道为什么你需要得到所有用户帐户?你是:

  1. 撷取帐户的列表显示在屏幕上为用户 然后执行针对单个账户的命令/交易?
  2. 在所有的用户帐户执行一个命令/交易 - 如冻结所有用户帐户

我想问的原因是因为你只需要考虑DDD方面,如果是后者。如果这个功能的原因是前者(和阅读你的问题后,我怀疑这是) - 我真的建议只创建,获取你需要的用户的帐户数据薄薄的查询服务层屏幕。你并不需要添加DDD的这个'限制';有没有参与交易或模型的状态变化。提供了这个功能并没有涉及在域模型在所有。只是定义了一些简单的POCO DTO的,并使用实体框架来获取数据,并将其传递回用户界面。

这是什么 CQRS 左右;你不需要仓库,工厂或聚集给UI帐户列表从用户选择 - 你会在它复杂化,使很多更多的工作,为自己。

如果没有的<​​em>是的一个场景,需要在所有 单笔交易的用户的帐户,然后我会做这样的事情:

 公共类的Account:IAccountService
{
    私人IAccountRepository _accountRespository;

    公共无效FreezeAllAccountsForUser(GUID用户id)
    {
        IEnumerable的&LT; IAccount&GT;帐户= _accountRespository.GetAccountsByUserId(用户ID);

        使用(IUnitOfWork的UnitOfWork = UnitOfWorkFactory.Create())
        {
            的foreach(在_accounts IAccount帐户)
            {
                account.Freeze();
                _accountRespository.Save(账户);
            }
        }
    }
}
 

当帐户服务是一个Web服务,即应用层。

总之,我的建议是:只考虑DDD的背景下的命令要求交易。有关读取数据的列表;创建一个简单查询的UI可以消耗的服务。

P.S。我注意到在你的问题,一些答案的工厂模式的滥用。工厂的目的是提供一个对象的创建策略,给出特定的数据。不应该有一个是getAccount(帐户ID)的方法调用数据库;库调用数据库,然后将数据传递到工厂来创建对象。

I have a bank account domain as listed below. There can be SavingsAccount, LoanAccount, FixedAccount and so on. One user can have multiple accounts. I need to add a new functionality – get all accounts for a user. Where should be the function written and how?

It would be great if the solution follows SOLID principles( Open-Closed principle,…) and DDD.

Any refactoring that would make the code better is welcome.

Note: The AccountManipulator will be used by a website client over a web service.

namespace BankAccountBL
{
public class AccountManipulator
{
    //Whether it should beprivate or public?
    private IAccount acc;

    public AccountManipulator(int accountNumber)
    {
        acc = AccountFactory.GetAccount(accountNumber);
    }

    public void FreezeAccount()
    {
        acc.Freeze();
    }

}

public interface IAccount
{
    void Freeze();
}

public class AccountFactory
{
    public static IAccount GetAccount(int accountNumber)
    {
        return new SavingsAccount(accountNumber);
    }
}

public class SavingsAccount : IAccount
{
    public SavingsAccount(int accountNumber)
    {

    }

    public void Freeze()
    {

    }
}
}

READING:

  1. When to use the CQRS design pattern?

  2. In domain-driven design, would it be a violation of DDD to put calls to other objects' repostiories in a domain object?

  3. Refactoring domain logic that accesses repositories in a legacy system

  4. Which of these examples represent correct use of DDD?

  5. Good Domain Driven Design samples

  6. Advantage of creating a generic repository vs. specific repository for each object?

解决方案

Firstly, to really answer your question it's important to know why you need to get all user accounts? Are you:

  1. Fetching a list of accounts to display on screen for the user to then perform a command/transaction against a single account?
  2. Performing a single command/transaction on all of the users accounts - such as 'Freeze All User Accounts'?

The reason I ask is because you only need to consider the DDD aspect if it's the latter. If the reason for this 'functionality' is the former (and after reading your question I suspect it is) - I really recommend just creating a thin query service layer that gets the user's account data you need for the screen. You don't need to add the 'restrictions' of DDD for this; there are no transactions or model state changes involved. Providing this functionality doesn't have to involve the domain model at all. Just define some simple POCO DTO's and use Entity Framework to get the data and pass it back to the UI.

This is what CQRS is about; you don't need repositories, factories or aggregates to give the UI a list of accounts for the user to choose from - you would be over complicating it and making A LOT more work for yourself.

If there is a scenario that requires a single transaction over all of the user's accounts then I'd do something like:

public class AccountService : IAccountService
{
    private IAccountRepository _accountRespository;

    public void FreezeAllAccountsForUser(Guid userId)
    {
        IEnumerable<IAccount> accounts = _accountRespository.GetAccountsByUserId(userId);

        using (IUnitOfWork unitOfWork = UnitOfWorkFactory.Create())
        {
            foreach (IAccount account in _accounts)
            {
                account.Freeze();
                _accountRespository.Save(account);
            }
        }
    }
}

Where AccountService is a webservice, i.e. the Application Layer.

In summary, my advice is: Only consider DDD in the context of commands that require transactions. For fetching lists of data; create a simple query service that the UI can consume.

P.S. I've noticed the misuse of the Factory pattern in your question and some of the answers. Factories are designed to provide an object's CREATION strategy, given particular data. There shouldn't be a 'GetAccount(accountId)' method that calls the database; repositories call the database then pass data to a factory to create the object.

这篇关于如何使用DDD / CQRS写功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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