C# · 12月 23, 2021

c# – 如何使用DDD / CQRS编写功能

我有一个银行帐户域名,如下所示.可以有SavingsAccount,LoanAccount,FixedAccount等.一个用户可以拥有多个帐户.我需要添加一个新功能 – 为用户获取所有帐户.应该写的功能在哪里以及如何?

如果解决方案遵循SOLID原则(开放 – 封闭原则,……)和DDD,那将是很好的.

任何可以使代码更好的重构都是受欢迎的.

注意:AccountManipulator将由网站客户端通过Web服务使用.

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() { }}}

读:

> When to use the CQRS design pattern?
> In domain-driven design,would it be a violation of DDD to put calls to other objects’ repostiories in a domain object?
> Refactoring domain logic that accesses repositories in a legacy system
> Which of these examples represent correct use of DDD?
> Good Domain Driven Design samples
> Advantage of creating a generic repository vs. specific repository for each object?

解决方法 首先,要真正回答您的问题,了解您需要获取所有用户帐户的原因非常重要吗?你是:

>获取要在用户显示的屏幕上显示的帐户列表
然后针对单个帐户执行命令/交易?
>对所有用户帐户执行单个命令/事务 – 例如“冻结所有用户帐户”?

我问的原因是因为如果是后者,你只需要考虑DDD方面.如果这个“功能”的原因是前者(并且在阅读了我怀疑它的问题之后) – 我真的建议只创建一个瘦查询服务层来获取屏幕所需的用户帐户数据.您不需要为此添加DDD的“限制”;没有涉及的交易或模型状态变化.提供此功能根本不需要涉及域模型.只需定义一些简单的POCO DTO并使用Entity Framework获取数据并将其传递回UI.

这就是CQRS的意思;您不需要存储库,工厂或聚合来为UI提供一个帐户列表供用户选择 – 您可能会过度复杂化并为自己做更多的工作.

如果存在需要在所有用户帐户上进行单个事务的方案,那么我会执行以下操作:

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); } } }}

其中AccountService是Web服务,即应用程序层.

总之,我的建议是:仅在需要事务的命令的上下文中考虑DDD.用于获取数据列表;创建UI可以使用的简单查询服务.

附:我注意到你的问题和一些答案中滥用了Factory模式.工厂旨在根据特定数据提供对象的CREATION策略.不应该有一个调用数据库的’GetAccount(accountId)’方法;存储库调用数据库,然后将数据传递给工厂以创建对象.