C# 如何使用DDD/CQR编写功能
我有一个银行帐户域,如下所示。可以有储蓄账户、贷款账户、固定账户等。一个用户可以有多个帐户。我需要添加一个新功能–获取用户的所有帐户。函数应该写在哪里,如何写 如果解决方案遵循固体原理(开闭原理,…)和DDD,那就太好了 任何可以使代码更好的重构都是受欢迎的 注意:AccountManipulator将由网站客户端通过web服务使用C# 如何使用DDD/CQR编写功能,c#,.net,design-patterns,domain-driven-design,cqrs,C#,.net,Design Patterns,Domain Driven Design,Cqrs,我有一个银行帐户域,如下所示。可以有储蓄账户、贷款账户、固定账户等。一个用户可以有多个帐户。我需要添加一个新功能–获取用户的所有帐户。函数应该写在哪里,如何写 如果解决方案遵循固体原理(开闭原理,…)和DDD,那就太好了 任何可以使代码更好的重构都是受欢迎的 注意:AccountManipulator将由网站客户端通过web服务使用 namespace BankAccountBL { public class AccountManipulator { //Whether it shoul
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()
{
}
}
}
阅读:
首先,你为什么需要会计?它完全不做任何事情,但会使代码更加复杂
至于获取一个用户的所有帐户,放置此方法的最合理位置是User类。您可以将帐户工厂传递给该方法,进一步的实现可能取决于您存储帐户的方式。如果您的
AccountManipulator
是您域的一个门面,我不会将帐户号放在构造函数中。我会这样重构它:
public class AccountManipulator
{
private AccountFactory _factory;
private UserRepository _users;
public AccountManipulator(AccountFactory factory, UserRepository users)
{
_factory = factory;
_users = users;
}
public void FreezeAccount(int accountNumber)
{
var acc = _factory.GetAccount(accountNumber);
acc.Freeze();
}
public IEnumerable<IAccount> GetAccountsOf(User user) {
return _users.GetAccountIds(user).Select(_factory.GetAccount);
}
}
public interface UserRepository {
IEnumerable<int> GetAccountIds(User user);
}
公共类AccountManipulator
{
私人会计工厂(工厂),;
私有用户存储库用户;
公共AccountManipulator(AccountFactory工厂、UserRepository用户)
{
_工厂=工厂;
_用户=用户;
}
公共帐户(int accountNumber)
{
var acc=_factory.GetAccount(accountNumber);
根据冻结();
}
公共IEnumerable GetAccountsOf(用户){
返回_users.getAccountId(user)。选择(_factory.GetAccount);
}
}
公共接口用户存储库{
IEnumerable GetAccountId(用户);
}
为了说明您的域是否可靠,您应该使用以下原则进行分析:
- 单一责任:每个对象都有自己的责任(并且只有那一个):
- AccountFactory:创建IAccounts
- SavingsAccount:IAccount的实现,它从(数据库?web服务?)读取/写入数据
- AccountManipulator:提供一组最小且简单的操作来处理域对象
- 打开/关闭:您的类是否对扩展开放,对更改关闭?
- AccountFactory:没有。如果您编写了IAccount的新实现,为了使用它,您必须更改AccountFactory。解决方案:抽象工厂
- 储蓄账户?这取决于它是否将使用外部依赖项。需要更多的代码来说明
- 会计:是的。如果需要对域对象执行其他操作,则可以直接使用其他服务,而无需更改AccountManipulator。或者你可以从中继承
- Liskov替换:您能用另一个实现替换任何类吗?需要更多的代码来说明。您现在没有IAccount或IAccountFactory的其他实现
- 依赖项反转:
- AccountManufactor应该依赖于抽象:AccountFactory和UserRepository应该是接口
AccountRepository
,并在其中添加一个额外的方法getAccountsfourser(int-userId)
,用于检索特定用户的所有帐户
如果AccountManipulator
是一个Web服务,则此类将使用AccountRepository
,如下所示:
public class AccountManipulator
{
public void FreezeAccount( int accountNr )
{
var repository = new AccountRepository();
var account = repository.GetAccount(accountNr);
account.Freeze();
repository.Save(account);
}
public ICollection<Account> GetAccountsForUser( int userId )
{
var repository = new AccountRepository();
return repository.GetAccountsForUser (userId);
}
}
公共类AccountManipulator
{
公共账户(国际账户编号)
{
var repository=new AccountRepository();
var account=repository.GetAccount(accountNr);
账户冻结();
保存(账户);
}
公共ICollection GetAccountsFruser(int userId)
{
var repository=new AccountRepository();
return repository.getaccountsfourser(userId);
}
}
首先,要真正回答您的问题,重要的是要知道为什么您需要获得所有用户帐户?你是:
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:IAccountService
{
私人IAccountRepository\u accountRespository;
public void FreezeAllAccountsForUser(Guid用户ID)
{
IEnumerable accounts=\u accountRespository.GetAccountsByUserId(userId);
使用(IUnitOfWork unitOfWork=UnitOfWorkFactory.Create())
{
foreach(IAccount账户在_账户中)
{
账户冻结();
_accountRespository.Save(account);
}
}
}
}
其中AccountService是一个Web服务,即应用层
总之,我的建议是:只有