可能な限り、オブジェクト間の通信を要求と応答のモデルに制限しようとしています。2つのオブジェクトAとBの間で、Aが直接または間接的にBのメソッドを呼び出す方法、またはBが直接または間接的にAのメソッドを呼び出す方法が存在する可能性があるという、プログラム内のオブジェクトの暗黙的な部分的な順序があります。ただし、AとBが相互にメソッドを相互に呼び出すことはできません。もちろん、メソッドの呼び出し元への逆方向の通信が必要な場合もあります。これを行うにはいくつかの方法があり、どちらもコールバックではありません。
1つの方法は、メソッド呼び出しの戻り値により多くの情報を含めることです。つまり、プロシージャが制御を返した後、クライアントコードはそれをどうするかを決定します。
もう1つの方法は、相互の子オブジェクトを呼び出すことです。つまり、AがBのメソッドを呼び出し、BがAに情報を伝達する必要がある場合、BはCのメソッドを呼び出します。AとBはどちらもCを呼び出すことができますが、CはAまたはBを呼び出すことができません。オブジェクトAはBがAに制御を戻した後、Cから情報を取得する責任があります。これは、私が最初に提案した方法とは根本的に異なっていません。オブジェクトAは、戻り値からのみ情報を取得できます。オブジェクトAのメソッドはいずれもBまたはCによって呼び出されません。このトリックのバリエーションは、Cをパラメーターとしてメソッドに渡すことですが、CとAおよびBの関係に対する制限は依然として適用されます。
さて、重要な質問は、なぜ私がこのように物事を主張するのかです。主な理由は3つあります。
- それは私のオブジェクトをより疎結合に保ちます。私のオブジェクトは他のオブジェクトをカプセル化できますが、それらは呼び出し元のコンテキストに依存することはなく、コンテキストはカプセル化されたオブジェクトに依存することはありません。
- それは私の制御フローを推論しやすくします。
self
メソッドの実行中に内部状態を変更できる唯一のコードは、1つのメソッドであり、他のメソッドではないことを想定できるのは素晴らしいことです。これは、ミューテックスを並行オブジェクトに配置するのと同じ理由です。
- オブジェクトのカプセル化されたデータの不変条件を保護します。パブリックメソッドはインバリアントに依存することが許可されており、別のメソッドが既に実行されているときに1つのメソッドを外部から呼び出すことができる場合、それらのインバリアントに違反することがあります。
コールバックのすべての使用に反対しているわけではありません。「呼び出し元を呼び出さない」という私の方針に従い、オブジェクトAがBのメソッドを呼び出してそれにコールバックを渡した場合、コールバックはAの内部状態を変更せず、AとAのコンテキスト内のオブジェクト。言い換えると、コールバックは、Bによって指定されたオブジェクトのメソッドのみを呼び出すことができます。実際には、コールバックはBと同じ制限の下にあります。
結び付ける最後のゆるい終わりは、私が話していたこの部分的な順序に関係なく、すべての純粋な関数の呼び出しを許可することです。純粋な関数はメソッドとは少し異なり、変更できないか、変更可能な状態や副作用に依存できないため、混乱を招く心配がありません。