クリーンなアーキテクチャのほとんどの例では(Androidプロジェクトがほとんどですが)、ユースケース/インタラクタークラス(機能をカプセル化するユニット)に気づきました here または here のように、基本クラス/インターフェースを共有することがよくあります。他のものはしない( ここのように または ここ )。代わりに、インタラクターがいくつかのパラメーターを受け入れることを許可し、その後、いくつかのロジックを実行するために使用されます。
これらのアプローチのどちらかが他方よりも優れていますか?たとえば、ユーザー入力を必要とする何かのユースケースをパラメーターなしのアプローチで処理する方法に特に興味があります。たとえば、ユーザーがエンティティを編集してサーバーに渡せるようにしたいとします。同じエンティティをユースケースとそれを呼び出す人に注入することもできますが、その場合は変更可能である必要があるため、変更は両方の場所に反映されます。ただし、不必要なモデルを作成することはできません(スレッドの問題などが原因で)。そのような場合の対処方法は?
ユースケース/インタラクターという用語を誤って使用した場合はご容赦ください。ただし、これはAndroid土地で使用されている方法であり、設計パターンでは明らかに遅れている可能性があります。
私たちが同じページにいることを確認するために、あなたの言っていることを繰り返します。
クリーンなアーキテクチャで
here のように、ユースケース/インタラクタークラスは多くの場合、基本クラス/インターフェースを共有します。
_ 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();
}
_
他のものはそうではなく、代わりにインタラクターがいくつかのパラメーターを受け入れることを許可し、その後、いくつかのロジックを実行するために使用されます。
のように ここ
_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を持つものが他にある場合は、新しい関連付けを作成します。不変のエンティティーをいじり回さないでください。
新しいものを表すものを作成し続けるスペースがある限り、エンティティを更新することなく、変化する世界をモデル化することは完全に可能です。