ゲッター撲滅
2006年2月22日
ゲッターメソッドを見ると、彼らの口角左側にぴくつきが見られます。そして、戦斧を素早く振り回し、別のゲッターが容赦なくクラスから切り離されると、満足げな叫び声を上げます。クラスは、男らしいゲッター撲滅者の足元で、感謝の恍惚状態に陥ります。
さて、イギリスのビールへの回帰が私を少し酔わせているのかもしれませんが、クリスによるちょっとした修正は、私のちょっとした気に障る点に触れました。私はしばしば、クラスにゲッターメソッドを持つことを避け、そのようなものをカプセル化の違反として扱うように言う人々に遭遇します。アレン・ホラブの記事はその中でも最もよく知られているものの1つです。
一般的な理由は、ゲッターがカプセル化を侵害することです。オーバー、ラン、ウィケットのフィールドを持つボーラークラスがある場合、ゲッター(getOvers、getRuns、getWickets)を追加するのは、フィールドをパブリックにすることとほとんど変わりません。
この議論には一定の道理があり、本当に必要になるまでアクセサーを書かないことを強くお勧めしますが、カプセル化の本質を見誤る危険性も伴います。私にとって、カプセル化の本質はデータの隠蔽ではなく、設計上の決定、特に変更が必要になる可能性のある領域における設計上の決定の隠蔽です。内部データ表現は、その一例ですが、唯一の例ではなく、常に最良の例というわけでもありません。外部データストアとの通信に使用されるプロトコルは、カプセル化の良い例です。これは、データ表現よりも、そのストアへのメッセージに関するものです。カプセル化について考えるときには、「隠蔽しようとしている変動性は何で、なぜなのか」という問いを、「データを公開しているか」という問いよりも優先して検討すべきだと思います。(クレイグ・ラーマンは、この点について素晴らしいコラムを書いてくれました。)
カプセル化の擁護は、ゲッター撲滅者の共通の合言葉ですが、彼らにとっての本当の動機は、もっと合理的で実用的なものだと思います。OO言語には、設計が手続き的なものが非常に多く存在します。OOコミュニティは、現代の言語がオブジェクトに支配されているという意味では「勝利」したかもしれませんが、OOプログラミングがまだ広く使用されていないという点では、まだ勝利していません。その結果、オブジェクトからデータを取り出して何かを行う手続きがまだ一般的であり、その動作はオブジェクト自体に適しているのに(「Tell Don't Ask」という実用的なプログラマーの原則に反します)、このような手続き型プログラミングはゲッターがないとできません。そのため、ゲッターを取り除くように言うことは、動作を適切な場所に移動するように促すのに役立ちます。
この動機には非常に共感しますが、ゲッターを避けるように言うだけでは、かなり鈍い手段であることを懸念しています。オブジェクトがデータ交換によって連携する必要がある場合が多くあり、そのためゲッターが本当に必要になる場合があります。
簡単な経験則を探すなら、私がケント・ベックから最初に聞いたものを好んで使っています。それは、あるコードが同じオブジェクトに対して複数のメソッドを呼び出す場合に常に注意することです。これは、アクセサーとより合理的なコマンドで発生します。オブジェクトに2つのデータビットを要求する場合、計算しているデータビットの単一の要求で置き換えることができますか?オブジェクトに2つのことを行うように指示する場合、それらを単一のコマンドで置き換えることができますか?もちろん、できない場合もたくさんありますが、常に自問自答する価値はあります。
もう1つの問題の警告サインは、データクラスです。これは、フィールドとアクセサーしかないクラスです。これは、動作がないため、ほとんどの場合問題の兆候です。そのようなものを見たら、常に疑うべきです。データを使用するユーザーを探し、その動作の一部をオブジェクトに移動できるかどうかを確認してみてください。このような場合、「このゲッターを取り除くことはできますか?」と自問自答すると役立ちます。できなくても、この質問をすることで、動作の良い移動につながる可能性があります。
オブジェクト間の動作の割り当ては、オブジェクト指向設計の本質であるため、他の設計と同様に、厳格なルールはなく、トレードオフの判断になります。クレイグ・ラーマンが「情報専門家」と呼ぶように、データと同じクラスに動作を配置することが最初に考慮すべき選択肢です。しかし、それは唯一の方法ではありません。レイヤリングはしばしばこれを凌駕します。多くのGang of Fourパターンは、特定のニーズのためにデータと動作を分離します。経験則としては、一緒に変化するものは一緒にすべきです。データとそれを使用する動作はしばしば一緒に変化しますが、しばしば他のグループ化の方が重要になります。