[解決済み] メソッドチェイニング - なぜ良い習慣なのか、そうでないのか?
質問
メソッドチェイニング とは、オブジェクトのメソッドがオブジェクト自身を返すことで、その結果を別のメソッドに呼び出すことです。こんな感じ。
participant.addSchedule(events[1]).addSchedule(events[2]).setStatus('attending').save()
これは、読みやすいコード、あるいは流暢なインターフェイスを実現するために、良い習慣と考えられているようです。しかし、私には、その代わりに、オブジェクト指向が暗示しているオブジェクト呼び出しの記法を壊しているように思えます。 結果 これは、オブジェクト指向のコードが一般的に期待される動作です。
participant.getSchedule('monday').saveTo('monnday.file')
この違いによって、"calling the resulting object"というドット表記に2つの異なる意味を持たせることに成功しました。連鎖のコンテキストでは、上の例は 参加者 オブジェクトを保存することを意図していますが、実際には、getScheduleによって受信されたスケジュール・オブジェクトを保存することを意図しています。
ここでの違いは、呼び出されたメソッドが何かを返すことを期待するかしないか(その場合、連鎖のために呼び出されたオブジェクト自体を返す)であることは理解しています。しかし、この2つのケースは記法そのものから区別できるものではなく、呼び出されるメソッドのセマンティクスからしか区別できないのです。メソッドチェイニングを使用しない場合、メソッド呼び出しが、そのメソッドに関連する何かを操作していることは常に知ることができます。 結果 連鎖があると、この前提が崩れ、実際に呼び出されているオブジェクトが何であるかを理解するために、連鎖全体を意味的に処理しなければならなくなります。例えば
participant.attend(event).setNotifications('silent').getSocialStream('twitter').postStatus('Joining '+event.name).follow(event.getSocialId('twitter'))
最後の2つのメソッドコールはgetSocialStreamの結果を参照していますが、その前のメソッドコールは参加者を参照しています。コンテキストが変わるチェーンを実際に書くのはバッドプラクティスかもしれませんが(そうなのか?)、その場合でも、似ているドットチェーンが実際に同じコンテキストで維持されているか、結果に対してのみ動作しているかを常にチェックする必要があります。
私には、メソッドチェイニングは表面的には読みやすいコードを生成しますが、ドットノテーションの意味をオーバーロードすると、より混乱を招くだけだと思われます。私は自分がプログラミングの第一人者だとは思っていないので、私の責任だと思うのですが。 それで 私は何を見逃しているのでしょうか?私はメソッドチェイニングをどこか間違って理解しているのでしょうか?メソッドチェイニングが特に優れているケースと、特に劣っているケースがあるのでしょうか?
補足:この質問は、質問の仮面をかぶった意見表明と受け取られる可能性があることは承知しています。しかし、そうではありません。私は純粋に、なぜチェーンが良い習慣と考えられているのか、そして、それが本来のオブジェクト指向の記法を壊していると考えるのはどこが間違っているのかを理解したいのです。
どのように解決するのですか?
これは主観的なものであることに同意します。私はほとんどの場合、メソッドの連結を避けていますが、最近、それがちょうどいいケースも見つけました。10個ほどのパラメータを受け取るメソッドがあり、もっと必要でしたが、ほとんどの場合、数個だけ指定すればいいのです。オーバーライドを使用すると、これはすぐに非常に面倒になりました。その代わりに、私はチェイニングアプローチを選択しました。
MyObject.Start()
.SpecifySomeParameter(asdasd)
.SpecifySomeOtherParameter(asdasd)
.Execute();
メソッドチェイニングのアプローチはオプションでしたが、コードを書くのが楽になりました(特にIntelliSenseの場合)。しかし、これは一つの孤立したケースであり、私のコードにおける一般的なプラクティスではないことに注意してください。
要は、99%のケースでは、メソッドチェイニングを行わなくても同じように、あるいはそれ以上のことができる、ということです。しかし、1%の確率で、これが最良のアプローチとなる場合があるのです。
関連
-
[解決済み] メソッドと関数の違いは何ですか?
-
[解決済み] なぜゲッターとセッター/アクセッサーを使うのですか?
-
[解決済み] 抽象メソッドと仮想メソッドの違いは何ですか?
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] Pythonのクラスはなぜオブジェクトを継承するのですか?
-
[解決済み] mixinとは何か、なぜ有用なのか?
-
[解決済み】「結合度が低く、結合度が高い」とはどういう意味ですか?
-
[解決済み] PHPのメソッドチェイニングか、流暢なインターフェースか?
-
[解決済み] ProxyパターンとDecoratorパターンの違い
-
[解決済み] 実装ではなくインターフェースにプログラムする」とはどういう意味ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 新しいjQuery AJAXのコードには、成功とエラーの代わりに.done()と.fail()を使用すべきです。
-
[解決済み] インターフェースと抽象クラス(一般的なOO)
-
[解決済み] リスコフ置換原理の例として、どのようなものがありますか?
-
[解決済み] インターフェースとベースクラス
-
[解決済み] Java のコア・ライブラリにおける GoF デザイン・パターンの例
-
[解決済み】.append()、prepend()、.after()、.before()
-
[解決済み] プライベートとプロテクト-ビジビリティ・グッド・プラクティスの懸念点【終了しました
-
[解決済み] コンストラクタをprivateにするとどうなるのですか?
-
[解決済み] Dependency InjectionはEncapsulationを犠牲にしなければならないのか?
-
[解決済み] オブジェクト指向プログラミングにおける「インターフェイス」の定義とは?