web-dev-qa-db-ja.com

イベント駆動型プログラミング:いつ価値があるのか​​?

わかりました、この質問のタイトルは イベントベースのプログラミングをいつ使用する必要がありますか? とほぼ同じであることを知っています直面しています。

小さなアプリケーションを開発しています。シンプルなアプリであり、その機能の大部分は基本的なCRUDです。

特定のイベント(特定のデータを変更する場合)では、アプリケーションは、そのデータのローカルコピーをファイルに書き込む必要があります。これを実装する最良の方法は何なのかわかりません。できます:

  • データが変更されたときにイベントを起動し、そのようなイベントに応答をバインド(ファイルを生成)します。または、オブザーバーパターンを実装します。それは不必要な複雑さのようです。
  • データを変更するコードからファイル生成コードを直接呼び出します。はるかに単純ですが、依存関係がこのようになっていることは間違っているようです。つまり、アプリのコア機能(データを変更するコード)がその余分な特典(バックアップファイルを生成するコード)に結合されているのは間違っているようです。ただし、このアプリは、そのカップリングが問題となるポイントまで進化しないことを知っています。

この場合の最善のアプローチは何ですか?

19
abl

KISSの原則:シンプルに保つ、愚か、またはYAGNIの原則:あなたはそれを必要としない。

次のようなコードを書くことができます:

void updateSpecialData() {
    // do the update.
    backupData();
}

または、次のようなコードを記述できます。

void updateSpecialData() {
     // do the update.
     emit SpecialDataUpdated();
}

void SpecialDataUpdatedHandler() {
     backupData();
}

void configureEventHandlers() {
     connect(SpecialDataUpdate, SpecialDataUpdatedHandler);
}

やむを得ない理由がない限り、より単純なルートに従います。イベント処理などの手法は強力ですが、コードが複雑になります。機能するためにはより多くのコードが必要であり、コード内で何が起こっているかを追跡するのが難しくなります。

イベントは適切な状況で非常に重要です(イベントなしでUIプログラミングを試みることを想像してみてください!)KISSまたはYAGNIの代わりにできる場合は使用しないでください。).

31
Winston Ewert

変更が何らかの効果をトリガーする単純なデータについて説明する例は、 observer design pattern を使用して完全に実装できます。

  • これは、完全なイベント駆動型コードよりも実装と保守が簡単です。
  • サブジェクトとオブザーバー間の結合は抽象的である可能性があり、関心事の分離を容易にします。
  • 1対多の関係に最適です(被験者には1人または複数のオブザーバーがいます)。

イベント駆動型アプローチは、多対多の状況で多くの異なる相互作用が発生する可能性がある場合、または連鎖反応が想定される場合(たとえば、サブジェクトがオブザーバーに通知し、場合によっては件名またはその他の件名)

13
Christophe

あなたが言うように、イベントはクラス間の結合を減らすための素晴らしいツールです。そのため、イベントのサポートが組み込まれていない一部の言語で追加のコードを記述する必要がある場合もありますが、全体像の複雑さが軽減されます。

イベントは間違いなくOOによる最も重要なツールの1つです(Alan Kayによると オブジェクトはメッセージの送受信によって通信します )。イベントのサポート、または関数をファーストクラスの市民として扱い、それらを使用することは簡単です。

組み込みサポートのない言語でも、オブザーバーパターンのようなものの定型文の量はごくわずかです。ボイラープレートを最小限に抑えるためにすべてのアプリケーションで使用できる適切な汎用イベントライブラリをどこかに見つけることができる場合があります。 (汎用イベントアグリゲーターまたはイベントメディエーターは、ほとんどすべての種類のアプリケーションで役立ちます)。

小さなアプリケーションでそれは価値がありますか?私は間違いなくはいと言います。

  • クラスを互いに分離しておくことで、クラス依存関係グラフをきれいに保つことができます。
  • 具体的な依存関係のないクラスは、テストの他のクラスを考慮せずに分離してテストできます。
  • 具体的な依存関係のないクラスでは、完全なカバレッジのために必要な単体テストが少なくなります。

「ああ、それは実際には非常に小さなアプリケーションにすぎないので、それほど重要ではない」と考えている場合は、次の点を考慮してください。

  • 小さなアプリケーションは、後で大きなアプリケーションと結合されることがあります。
  • 小規模なアプリケーションには、後で他のアプリケーションで再利用する必要がある可能性がある、少なくともいくつかのロジックまたはコンポーネントが含まれている可能性があります。
  • 小規模なアプリケーションの要件は変更される可能性があり、リファクタリングの必要性を促します。これは、既存のコードが分離されている場合に簡単です。
  • 後で追加機能を追加できるため、既存のコードを拡張する必要が生じます。これは、既存のコードがすでに分離されている場合にもはるかに簡単です。
  • 疎結合のコードは、通常、密結合のコードよりも書くのにそれほど時間はかかりません。ただし、密結合コードは、疎結合コードよりもリファクタリングとテストに時間がかかります。

全体として、アプリケーションのサイズは、クラスを疎結合にしておくかどうかを決定する要素にはなりません。 SOLID原則は、大きなアプリケーションだけでなく、あらゆる規模のソフトウェアやコードベースに適用できます。

実際、疎結合クラスを個別に単体テストする際に節約される時間は、それらのクラスの分離に費やされる追加の時間と釣り合うはずです。

5
Ben Cottrell

オブザーバーパターンは、プログラミング言語が「コールバック」や「デリゲート」のようなものをサポートしていると仮定して、 Wikipediaの記事 (またはGOFの本)が説明するよりもはるかに小さい方法で実装できます。コールバックメソッドをCRUDコード(一般的な「ファイルへの書き込み」メソッドまたは空のメソッドのいずれか)に渡すだけです。 「イベント発生」の代わりに、そのコールバックを呼び出すだけです。

結果のコードは、ファイル生成コードを直接呼び出すよりも最小限の複雑さで済みますが、無関係なコンポーネントの密結合の欠点はありません。

「YAGNI」のデカップリングを犠牲にすることなく、「両方の長所」をもたらすでしょう。

2
Doc Brown