case / interactorの `execute`メソッドを使用してパラメーターを受け入れる必要があります


8

クリーンアーキテクチャのほとんどの例(Androidプロジェクトはほとんどですが)では、ユースケース/インタラクタークラス(機能をカプセル化するユニット)が、ここここのように、基本クラス/インターフェースを共有することが多いことに気付きました。他のものは(hereまたはhereのように)しません。代わりに、インタラクターがいくつかのパラメーターを受け入れることを許可し、その後、いくつかのロジックを実行するために使用されます。

これらのアプローチのいずれかが他よりも優れていますか?たとえば、ユーザー入力を必要とする何かのユースケースをパラメーターなしのアプローチがどのように処理するかに特に興味があります。たとえば、ユーザーにエンティティを編集させてサーバーに渡したいとします。同じエンティティをユースケースとそれを呼び出す人に注入することもできますが、その場合は変更可能である必要があるため、変更は両方の場所に反映されます。ただし、不必要なモデルを作成することはできません(スレッド化の問題などのため)。そのような場合の対処方法は?

ユースケース/インタラクターという用語を誤って使用した場合はご容赦ください。ただし、これはAndroidランドでの使用方法であり、確かにデザインパターンで少し遅れている可能性があります。

回答:


6

私たちが同じページにいることを確認するために、あなたの言っていることを繰り返します。

クリーンなアーキテクチャで

ここに画像の説明を入力してください

ケースA

ユースケース/インタラクタークラスは、多くの場合、このように基本クラス/インターフェースを共有します

  public abstract class UseCase {

  private final ThreadExecutor threadExecutor;
  private final PostExecutionThread postExecutionThread;

  private Subscription subscription = Subscriptions.empty();

  protected UseCase(ThreadExecutor threadExecutor,
      PostExecutionThread postExecutionThread) {
    this.threadExecutor = threadExecutor;
    this.postExecutionThread = postExecutionThread;
  }

  /**
   * Builds an {@link rx.Observable} which will be used when executing the current {@link UseCase}.
   */
  protected abstract Observable buildUseCaseObservable();

  /**
   * Executes the current use case.
   *
   * @param UseCaseSubscriber The guy who will be listen to the observable build
   * with {@link #buildUseCaseObservable()}.
   */
  @SuppressWarnings("unchecked")
  public void execute(Subscriber UseCaseSubscriber) {
    this.subscription = this.buildUseCaseObservable()
        .subscribeOn(Schedulers.from(threadExecutor))
        .observeOn(postExecutionThread.getScheduler())
        .subscribe(UseCaseSubscriber);
  }

  /**
   * Unsubscribes from current {@link rx.Subscription}.
   */
  public void unsubscribe() {
    if (!subscription.isUnsubscribed()) {
      subscription.unsubscribe();
    }
  }
}

そしてここ

package cat.ppicas.framework.task;

public interface Task<R, E extends Exception> {

    TaskResult<R, E> execute();

}

ケースB

他のものはそうではなく、代わりにインタラクターがいくつかのパラメーターを受け入れることを許可し、その後、いくつかのロジックを実行するために使用されます。

ここのよう

package pl.charmas.shoppinglist.domain.usecase;

public interface UseCase<Result, Argument> {
  Result execute(Argument arg) throws Exception;
}

またはここ

AbstractInteractor.java
GetMarvelCharactersLimit.java
GetMarvelCharactersLimitImp.java
GetMarvelCharactersPaginated.java
GetMarvelCharactersPaginatedImp.java

やめる

どちらも正しいです。

インターフェースまたは基本クラスの共有は継承の一部です。

パラメータを介してロジックを実行できるようにパラメータを受け入れることは、構成の一部です。

これらのアプローチのいずれかが他よりも優れていますか?

どちらも得意分野が優れています。人気のある設計原則では、「継承よりも構成を優先する」と述べられています。

私が理解しているのであれば、合成と継承の両方が多態性をどのように可能にするかを理解していると思います。これをパターン言語で言うと、テンプレートパターンまたは戦略パターンを使用してポリモーフィズムを取得できます。

継承は、それ自体でポリモーフィズムを提供します。したがって、キーボードでの入力が少なくなります。構成では、委任を追加してインターフェースを公開し、パラメーターに接続する必要があります。それはより多くのタイピングを意味します。しかし、コンポジションは静的にバインドされていないため、非常に柔軟でテスト可能です。

ケース/インタラクターexecuteメソッドを使用してパラメーターを受け入れる必要がありますか?

このメソッドx.y()とこの関数y(x)は基本的に同じであることを覚えておいてください。execute() この方法は、常に、少なくとも1つのパラメータを取得しています。

たとえば、ユーザー入力を必要とする何かのユースケースをパラメーターなしのアプローチがどのように処理するかに特に興味があります。たとえば、ユーザーにエンティティを編集させてサーバーに渡したいとします。同じエンティティをユースケースとそれを呼び出す人に注入することもできますが、その場合は変更可能である必要があるため、変更は両方の場所に反映されます。ただし、不必要なモデルを作成することはできません(スレッド化の問題などのため)。そのような場合の対処方法は?

さて、私たちはエンティティについて話しているのであり、ユースケースやポリモーフィズムについてではありません。

エンティティにはIDがあります。エンティティを不変にすることは非常に良いことです。ユーザーが不変のものを編集するのはなぜですか?なぜ2つの場所に存在する情報が必要なのですか。もしそうなら、どの場所が一番知っていますか?

いいえ、ユーザーが何か新しいものを作成できるようにした方がいいです。IDが必要な場合は、新しい一意のIDを取得します。そうでない場合、それは値オブジェクトです。この情報を関連付ける必要がある既存のIDを持つものが他にある場合は、新しい関連付けを作成します。不変のエンティティーをいじり回さないでください。

新しいものを表すものを作成し続けるスペースがある限り、エンティティを更新することなく、変化する世界をモデル化することは完全に可能です。


しかし、まだ疑問は残ります。継承の例であるAとBの両方のアプローチではないですか?そして、いくつかのロジックを実行するために別のクラスを持つことは構成です。Aが継承、Bが構成であることを確認できません。詳しく説明していただけますか?method is always getting at least one parameter必要executeに応じて-それは技術的です。「メソッドは複数のパラメータを受け入れる必要があります」。最後に、不変性に関する部分でも問題に対処していません。「executeメソッドがパラメーターを受け入れない場合、(ユーザーの変更を反映する)新しい不変エンティティをユースケースに渡すにはどうすればよいですか?
wasyl
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.