0

首先我的要求是

“我们可以创建一个账户并在上面存钱,当我们购买一件物品时,我们会减少账户”

所以我的 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它只是假设处理数据存储。

4

1 回答 1

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

这种变化可能看起来很小,但很重要:

  1. 控制器现在只有一个改变的理由(视图和模型之间的映射)
  2. 任何业务需求的变化都不会强制改变 UI 层。
  3. 需求变更仅在一处进行

要添加对免费帐户的支持,我将使用事件驱动模型:

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

因为它不需要更改其他帐户服务。

于 2012-03-23T14:30:00.730 回答