Harus menggunakan case / interaksor `eksekusi` metode menerima parameter

8

Dalam sebagian besar contoh arsitektur bersih (sebagian besar proyek Android) saya perhatikan bahwa kelas use-case / berinteraksi (unit yang merangkum fitur) sering berbagi kelas dasar / antarmuka, seperti di sini atau di sini . Yang lain tidak ( seperti di sini atau di sini ), sebagai gantinya memungkinkan interaksor untuk menerima beberapa parameter yang kemudian digunakan untuk menjalankan beberapa logika.

Apakah salah satu dari pendekatan ini lebih baik dari yang lain? Saya terutama tertarik pada bagaimana pendekatan parameterless menangani kasus penggunaan untuk sesuatu yang memerlukan input pengguna misalnya - katakan kita ingin membiarkan pengguna mengedit entitas dan meneruskannya ke server. Kita bisa menyuntikkan entitas yang sama ke dalam use case dan siapa pun yang memintanya, tetapi kemudian harus bisa berubah, sehingga perubahan tercermin di kedua tempat. Tetapi kemudian kita tidak dapat membuat model yang tidak dapat diubah, yang mungkin tidak kita inginkan (karena masalah threading dll). Bagaimana cara menangani kasus seperti itu?

Maafkan saya jika saya menggunakan istilah usecase / berinteraksi secara tidak benar, tetapi ini adalah bagaimana mereka digunakan di Android Land, yang memang diakui mungkin sedikit ketinggalan dalam pola desain.

wasyl
sumber

Jawaban:

6

Izinkan saya mengulangi apa yang Anda katakan untuk memastikan kami berada di halaman yang sama.

Dalam arsitektur bersih

masukkan deskripsi gambar di sini

Kasus A

kelas use-case / interactor sering berbagi kelas dasar / antarmuka, seperti di sini

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

dan disini

package cat.ppicas.framework.task;

public interface Task<R, E extends Exception> {

    TaskResult<R, E> execute();

}

Kasus B

Yang lain tidak, dan sebagai gantinya memungkinkan interaksor untuk menerima beberapa parameter yang kemudian digunakan untuk mengeksekusi beberapa logika.

seperti disini

package pl.charmas.shoppinglist.domain.usecase;

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

atau disini

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

Berhenti

Keduanya benar.

Berbagi antarmuka atau kelas dasar adalah bagian dari warisan.

Menerima parameter sehingga Anda dapat menjalankan logika melalui mereka adalah bagian dari komposisi.

Apakah salah satu dari pendekatan ini lebih baik dari yang lain?

Keduanya lebih baik dalam hal apa yang mereka lakukan. Meskipun prinsip desain populer menyatakan, "lebih menyukai komposisi daripada warisan" .

Jika saya memahami, Anda melihat bagaimana komposisi dan warisan dapat memungkinkan terjadinya polimorfisme dan sekarang setelah Anda melihatnya, Anda berjuang untuk memilih di antara keduanya. Mengatakan ini dalam bahasa pola: Anda dapat menggunakan pola template atau pola strategi untuk mendapatkan polimorfisme.

Warisan memberi Anda polimorfisme sendiri. Jadi, kurang mengetik di keyboard. Komposisi mengharuskan Anda menambahkan delegasi untuk mengekspos dan menghubungkan antarmuka ke parameter. Itu berarti lebih banyak mengetik. Tetapi komposisi tidak terikat secara statis sehingga sangat fleksibel dan dapat diuji.

Haruskah menggunakan case / executemetode interaksi menerima parameter?

Ingat bahwa metode x.y()dan fungsi y(x)ini pada dasarnya sama. Suatu execute() metode selalu mendapatkan setidaknya satu parameter.

Saya terutama tertarik pada bagaimana pendekatan parameterless menangani kasus penggunaan untuk sesuatu yang memerlukan input pengguna misalnya - katakan kita ingin membiarkan pengguna mengedit entitas dan meneruskannya ke server. Kita bisa menyuntikkan entitas yang sama ke dalam use case dan siapa pun yang memintanya, tetapi kemudian harus bisa berubah, sehingga perubahan tercermin di kedua tempat. Tetapi kemudian kita tidak dapat membuat model yang tidak dapat diubah, yang mungkin tidak kita inginkan (karena masalah threading dll). Bagaimana cara menangani kasus seperti itu?

Nah, sekarang kita berbicara tentang entitas, bukan kasus penggunaan, atau polimorfisme.

Entitas memiliki ID. Sangat bagus untuk membuat sebuah entitas tidak berubah. Mengapa Anda ingin pengguna mengedit sesuatu yang tidak berubah? Mengapa Anda ingin informasinya ada di dua tempat? Jika ya, tempat mana yang paling tahu?

Tidak, lebih baik membiarkan pengguna membangun sesuatu yang baru. Jika harus memiliki ID maka mendapat ID unik baru. Jika tidak, itu adalah objek nilai. Jika ada sesuatu yang lain dengan ID yang sudah ada sebelumnya bahwa informasi ini harus dikaitkan dengan kemudian membangun asosiasi baru. Jangan mencari-cari entitas tidak berubah.

Sangat mungkin memodelkan dunia yang berubah tanpa pernah memperbarui entitas Anda, asalkan Anda memiliki ruang untuk terus menciptakan hal-hal yang mewakili apa yang baru.

candied_orange
sumber
Namun, saya masih ragu. Bukankah kedua pendekatan, A dan B, contoh pewarisan? Dan memiliki kelas terpisah untuk menjalankan beberapa logika adalah komposisi. Saya gagal melihat bahwa A adalah warisan, dan B adalah komposisi - dapatkah Anda menguraikannya? Adapun method is always getting at least one parameter- itu teknis. "Haruskah executemetode menerima lebih dari satu parameter", jika Anda mau. Dan akhirnya bagian tentang imutabilitas juga tidak mengatasi masalah, yaitu "bagaimana saya meneruskan penggunaan kami ke entitas yang tidak berubah (yang mencerminkan perubahan pengguna) jika metode pelaksanaannya tidak menerima parameter?
wasyl