首先我的要求是
“当我们购买商品时,我们可以创建一个放钱的帐户”
所以我的AccountController看起来像
class AccountController
{
private IAccountDataSource _accountDataSource;
Create(Account anAccount)
{
_accountDataSource.Insert(anAccount);
Render(anAccount.Id);
}
}
但是有一个新的要求 “有些人可以拥有一个免费帐户(所有商品都是免费的),但如果我们创建一个真实帐户,那么我们会删除免费帐户”
所以我的controller.Create成了
Create(Account anAccount)
{
_accountDataSource.Insert(anAccount);
RemoveFreeAccount(anAccount.Customer);
Render(anAccount.Id);
}
RemoveFreeAccount(Customer aCustomer)
{
_accountDataSource.Remove(new AccountFilter() { Type='Free', CustomerId=aCustomer.Id });
}
但对我而言,感觉我应该将此RemoveFreeAccount
放在其他地方,但我不知道因为IAccountDataSource
只是假设处理数据存储。
答案 0 :(得分:1)
问题表明您正在打破SRP。您的控制器不应包含业务逻辑。直接在控制器中使用存储库会强制您将所有逻辑放入其中,从而获得两个职责(作为MVC +处理业务逻辑的M之间的桥梁)。
第一个重构部分应该是将业务逻辑移动到模型中(在MVC中不要与实体模型或视图模型混淆)
这为您的原始代码提供了以下结构:
public class AccountService
{
void CreateAccount(string accountName)
{
var account = new Account(accountName);
_dataSource.Create(account);
DomainEvents.Publish(new AccountCreated(account));
}
}
public class AccountController
{
private AccountService _service;
Create(AccountViewModel model)
{
var account = _accountDataSource.Create(model.Name);
Render(account.Id);
}
}
这种变化可能看起来很小,但很重要:
要添加对免费帐户的支持,我会使用事件驱动模型:
public class FreeAccountService : ISubscriberOf<UserCreated>, ISubscriberOf<AccountCreated>
{
public FreeAccountService(AccountService)
{
}
public void HandleEvent(UserCreated domainEvent)
{
accountService.Create(new FreeAccount());
}
public void HandleEvent(AccountCreated domainEvent)
{
var freeAccount = dbSource.GetFreeAccount();
if (freeAccount != null)
accountService.Delete(freeAccount)
}
}
因为其他帐户服务不需要更改。