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

发布于 2024-12-22 15:31:42 字数 826 浏览 2 评论 0原文

首先,我的要求是

“我们可以创建一个帐户并存入资金,当我们购买商品时,我们会减少帐户”

所以我的 AccountController 看起来像

class AccountController
{
    private IAccountDataSource _accountDataSource;

    Create(Account anAccount)
    {
        _accountDataSource.Insert(anAccount);
         Render(anAccount.Id);
     }
}

但是有一个新的要求 “有些人可以拥有一个免费帐户(所有项目都是免费的),但如果我们创建一个真实帐户,那么我们会删除免费帐户”

所以我的控制器。创建变成了

Create(Account anAccount)
{
    _accountDataSource.Insert(anAccount);
    RemoveFreeAccount(anAccount.Customer);
    Render(anAccount.Id);
}

RemoveFreeAccount(Customer aCustomer)
{
    _accountDataSource.Remove(new AccountFilter() { Type='Free', CustomerId=aCustomer.Id });
}

但对我来说,感觉我应该把这个 在其他地方删除FreeAccount,但我不知道在哪里,因为IAccountDataSource 只是假设处理数据存储。

First my requirement was

"We can create an account an put money on it, when we buy an item we decrease the account"

So my AccountController looked like

class AccountController
{
    private IAccountDataSource _accountDataSource;

    Create(Account anAccount)
    {
        _accountDataSource.Insert(anAccount);
         Render(anAccount.Id);
     }
}

But then there is a new requirement
"Some people can have a free account (all the items will be free), but if we create a real account then we remove the free account"

So my controller.Create became

Create(Account anAccount)
{
    _accountDataSource.Insert(anAccount);
    RemoveFreeAccount(anAccount.Customer);
    Render(anAccount.Id);
}

RemoveFreeAccount(Customer aCustomer)
{
    _accountDataSource.Remove(new AccountFilter() { Type='Free', CustomerId=aCustomer.Id });
}

But for me it feels like I should put this RemoveFreeAccount somewhere else, but I don't know where because IAccountDataSource is just suppose to handle the data storing.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

简单 2024-12-29 15:31:42

该问题表明您违反了 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)
    }
}

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

The problem shows that you are breaking SRP. Your controller should not contain business logic. Using a repository directly in the controller forces you do put all logic in it and therefore getting two responsibilities (being a bridge between the M in MVC + handling the business logic).

The first refactoring part should be to move the business logic into the model (in MVC not to be confused with an entity model or a view model)

this giving your original code the following structure:

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

The change might look minor, but is important:

  1. The controller now has only one reason to change (mapping between the view and the model)
  2. Any change of business requirements will not force changes to the UI layer.
  3. Changes in requirements are only made in one place

To add support for free accounts I would use an event driven model:

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

Since it requires no changes in the other account service.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文