当需求以这种方式发展时,如何分离责任?

时间:2011-12-20 17:09:07

标签: design-patterns solid-principles

首先我的要求是

“当我们购买商品时,我们可以创建一个放钱的帐户”

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

1 个答案:

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

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

  1. 控制器现在只有一个原因需要改变(视图和模型之间的映射)
  2. 任何业务要​​求的更改都不会强制更改UI层。
  3. 要求的变更仅在一个地方进行
  4. 要添加对免费帐户的支持,我会使用事件驱动模型:

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

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

相关问题