我有一个银行帐户域名,如下所示。可以有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()
{
}
}
}
读:
答案 0 :(得分:4)
如果您的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);
}
为了说明您的域名是否为SOLID,您应该使用以下原则进行分析:
答案 1 :(得分:3)
首先,要真正回答您的问题,了解为什么您需要获取所有用户帐户非常重要?你是:
我问的原因是因为如果是后者,你只需要考虑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可以使用的简单查询服务。
P.S。我注意到你的问题和一些答案中滥用了Factory模式。工厂旨在根据特定数据提供对象的CREATION策略。不应该有一个调用数据库的'GetAccount(accountId)'方法;存储库调用数据库,然后将数据传递给工厂以创建对象。
答案 2 :(得分:1)
首先为什么需要AccountManipulator?它绝对没有,但使代码更复杂。
至于获取用户的所有帐户,放置此方法的最合理的位置将在User类中。您可以将帐户工厂传递给该方法,进一步的实施可能取决于您存储帐户的方式。
答案 3 :(得分:0)
我将'AccountFactory'重命名为AccountRepository
并在其中添加一个额外的方法GetAccountsForUser( int userId )
,该方法会检索特定用户的所有帐户。
如果AccountManipulator
是网络服务,那么此课程将使用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);
}
}