システムを最初から設計するとき、オブジェクトがPush別のオブジェクトに情報を提供するかどうかORオブジェクトを使用する必要があるかどうかpull =別のオブジェクトからの必要なデータ。
OOPデザインの標準のようなものはありますか、オブジェクトへのデータのプッシュよりもオブジェクトによるデータのプルを優先する必要がありますか?
長期的な観点の観点から、またはOOP構造/ framework/diagramはより複雑になりますか?
tell dont ask によると、Push is better-以上のOO。オブジェクトにデータのクエリを実行したくないので、何かを行うことができます。データを知っているのは彼だからです。
ここでの議論は、プルとプッシュに関する重要なポイントが欠けているようなものであり、個々の例やケースに固執しています。
Pushing:プッシュの利点は、データを理解していて、何をプッシュしているのかを知っていることです。データを所有しているコンポーネントよりもデータをよく知っている(または知らない)コンポーネントはありません。これは、理論的には、より優れた設計とより堅牢なシステムを意味します。
Pulling:プルアプローチで見られる唯一の利点は、プルするコンポーネントが、プルするタイミングを正確に把握していることです。データが必要で、コンポーネントがデータを必要とするコンポーネントよりもデータが必要な場合を知らない(または知らない)場合に、会話を開始できます。
それに関する私の結論は次のとおりです:コンポーネントがトランザクションを所有している場合は、トランザクションを開始します。 APIからデータを取得する場合、明らかにAPIクライアントがトランザクションを所有するため、プルを行います。メッセージをブロードキャストする場合、ブロードキャスターはトランザクションを所有しているため、プッシュを行います。
他の回答で述べたように、プッシュもプルも優れていませんが、デザインのニーズに最適なものを選択する必要があります。
here から、オブザーバーモデルをプッシュベースにするかプルベースにするかについて議論します。
誰が更新をトリガーしますか?
サブジェクトとそのオブザーバー間の通信は、オブザーバーインターフェイスで宣言された通知メソッドを介して行われます。ただし、サブジェクトまたはオブザーバーオブジェクトからトリガーできます。通常、通知メソッドは、状態が変更されたときにサブジェクトによってトリガーされます。ただし、更新が頻繁に行われる場合、サブジェクトの連続的な変更によって、オブザーバーでの多くの不要な更新操作が決定されることがあります。このプロセスをより効率的にするために、オブザーバーは、必要に応じて通知操作を開始する責任があります。
このパターンの場合、決定的な特性は、データが変化する頻度であり、観測者がそのデータの受信を希望する対応する速度です。オブザーバーが、対象がデータを生成するよりも遅い速度でデータを必要とする場合(例:電話のGPSの場合、常に位置を必要とせず、特定の用途がある場合のみ)、ポーリングはもっと効率的。オブザーバーがサブジェクトが生成するのと同じ速さでデータを必要とする場合(考えられる例は、リアルタイムの株式相場表示アプリケーションです)、プッシュ通知の方が良いでしょう。
OOP(私が見逃したものがあるかもしれません)で違いはないはずですが、プルアプローチの方が優れています。
これは、最近のデザインパターンの傾向によるものです。 ドメイン駆動設計 と [〜#〜] cqrs [〜#〜] は非常に目立つものの1つであり、疎結合を促進しますが、これは非常に良いことです。
オブジェクトは、別のオブジェクトがそのデータをどのように処理するかを気にする必要はありません。言うまでもありません。オブジェクトはデータを使用可能にするだけで、データを必要とするオブジェクトはそのオブジェクトからデータをフェッチ/プルする必要があります。イベント駆動型の設計を見てください。
これにより、オブジェクトが他のオブジェクトから独立し、移植性が向上します(プルされるため、プッシュ先を変更する必要はありません)。
TL; DRプッシュよりプルをお勧めします。
注:これらすべての異なる設計パターンは、相互に排除するのではなく、共存します。
宛先.プッシュ(ソース)
ソース.プル(宛先)
コードに含める依存関係を確認して、ソリューションを選択します。
SourceとDestinationが前のスキームに必要なものに依存できない場合は、SourceとDestinationの両方を知っている(依存している)外部メソッドによってアクションを実行する必要があります。ただし、両方へのアクセスは公開されています。
IDestinationをフィードするために仮想ISourceが必要な場合は、外部メソッドがアクションを実行するために必要なすべてのメソッドを公開するためにそれらのインターフェースが必要です。
単一の外部メソッドがISourceおよびIDestinationでアクションを実行できない場合は、Visitorパターンを確認する必要があります。Visitorクラスは、特定のSource1およびSourceX Destination1およびDestinationYですべての特定のアクションを実行します。
プッシュ/プルという言葉は相対的です。データを持っているプッシャーとデータを必要とするプーラーがあります。実際にデータをニュートラルな場所に保存し、Push-er/pull-erの内部ではない場合、特定の問題に適した多くの可能性が発生します。1人がデータを持っているときにデータを更新し(必要に応じて通知を送信)、もう1人はプルします彼の都合の良い時のデータ。多くのデザインパターン、MVC、オブザーバー、コマンドなどがシナリオを処理するために配置されます。
答えはアーキテクチャの目標によって異なります。つまり、一般的な解決策はありません。
クライアントサーバーアーキテクチャでは、オブジェクトが他のオブジェクトから状態をプルするバックエンドに階層化システムがある可能性があります。つまり、特定の「サービス」だけが最終的にオブジェクトの状態を更新します。例:新しいオブジェクトの作成、オブジェクトのフィールドの更新など(新しい注文アイテムを注文全体に追加するように)。
モノリシックデスクトップアプリケーションでは、まったく異なる場合があります。 「Model-View-Controller」のバリエーションやオブザーバーパターンなどを使用している可能性があります。この場合、情報をプッシュします。 UIに。
通常、「データのプル」とは、ajax呼び出しを実行し、応答が成功したときにコールバックを実行していることを意味します。これは悪いことではありませんが、データの更新をチェックしているために間隔を置いて実行している場合は、過度に集中する可能性があります。
しかし、オンラインWebアプリケーションのコンテキストでは、これに代わるものとして、ロングポーリングを使用したプッシュがあります。ロングポーリングは最初の方法とそれほど変わらないので、以下を実行することをお勧めします。
セミパブリックプッシュURLエンドポイント(別名pubsubのWebサービス)からデータをプルする長いポーリングメソッドを作成し、クライアントでパブリッシャー/サブスクライバーデザインパターンを使用して更新する必要があるすべてを更新します。これにより、更新がデータソースからより分離されます。
これは、IBMがこのトピックについて書いたホワイトペーパーです。 http://www.ibm.com/developerworks/library/specification/ws-pubsub/
まず、一般的なガイドラインは明確です:オブジェクトはdataとbehaviorです。これにより、内部データを使用して何かをdoするメソッドを提供することで、getterを減らし、pullsを減らすことができます。
一部のクラスではプッシュ操作がプッシュされたオブジェクトで新しいプルを必要とする可能性があるため、「受け入れられた回答では」「プッシュの方が良い」だけでは十分に機能しません。代わりに、抽象化に最も適した場所にプッシュ操作を追加することをお勧めします。これにより、さらに抽象的なクラス/クラスの構成に至る可能性もあります( オブジェクト指向設計ヒューリスティックス 、Riel、1996、37ページを参照)。
私の観点から... mvcを使用するデスクトップアプリケーション開発者として、モデルオブジェクトで利用可能なときにデータをプッシュし、次にモデルのロジック(タイマー/非同期イベント/通知)に基づいてデータをプッシュする微妙なバランスがあります。コントローラーにプッシュされ、次にビューに... UIの相互作用は、設定に応じてどちらの方向にも進むことができます。コントローラーは、何かをする必要があることを通知する更新メッセージまたは更新メッセージを起動できます。コントローラ、そして多くの場合はモデルです。
もちろん、これは単純化されており、実際のシナリオでは混乱していますが、特定の方法で実行するための十分な準備ができていれば、長い道のりになる可能性があります。