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 が壊れていることを示しています。コントローラーにビジネス ロジックを含めないでください。コントローラーでリポジトリを直接使用すると、すべてのロジックをコントローラーに配置する必要があり、そのため 2 つの責任 (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. コントローラーを変更する理由は 1 つだけになりました (ビューとモデルの間のマッピング)。
  2. ビジネス要件が変更されても、UI レイヤーの変更が強制されることはありません。
  3. 要件の変更は 1 か所でのみ行われます

無料アカウントのサポートを追加するには、イベント ドリブン モデルを使用します。

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 に答える