よろしくお願いします。
現在、クラス設計を行っています。
has-aの関係が多かったので、コンポジションを多く使いました。
例えば、下記のようなクラス構成だったとします。
Houseクラス ┗Bathroomクラス ┗Bathクラス ┗Waterクラス ┗temperatureフィールド
この時、Houseインスタンスからtemperatureフィールドの値を取得しようとすると、Getterの嵐になってしまうのですが、これは設計としては普通でしょうか?
わかりにくくて申し訳ありません。
Getterは出来るだけ定義したくないという思想で設計をしたかったので、不安です。
ご教示をよろしくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
あまりプログラムの事情もわからずに設計の良し悪しは申し上げられませんが、お気付きの通り良くない設計です。
何が良くないかというと、Getterだらけになることそのものではありません。Getterだらけになっているのは結果です。
この例だと、「お風呂の水温」を家の外側で取得しなければいけないことがすでに設計の誤りです。
家を与えられたとき、その家のお風呂の水温を使って何かする処理、というのを家の外側で書かないといけないのが抽象化不足なのです。
処理そのものをお風呂の中に、家の中に、閉じ込められませんか?
もっと大きな処理要求を家にメソッドとして持たせるようにできませんか?
動作状況のログを取るような目的だとそうも言っていられなかったりしますが。
投稿2016/07/15 09:49
編集2016/07/15 13:15総合スコア5568
0
ベストアンサー
こんにちは。
Getterの嵐になってしまう
この嵐ですが、下記イメージでしょうか?
house.getBathroom().getBath().getWater().getTemplature();
もし、YESなら、これでは情報の隠蔽になりません。正にGetterの暗黒面に該当すると思います。
もし、houseの外から、風呂の温度を取得する必要があるのなら、
house.getBathTemplature();
だと思います。
そして、実は、風呂の温度を家の外から取得できると言うことは、風呂桶には温度計が付いていて、Bathroomもしくは、Houseの中にお風呂のコントローラが設置されていると思います。
つまり、温度は温度計が計測し、その温度情報は風呂の水の中にあるのではなく、お風呂のコントローラが保持している姿になるケースが多いように感じます。
つまり、house.getBathTemplature()は、Houseに含まれるBathControllerからお湯の温度を獲得するわけですね。
更にどちらかと言うと、getBathTemplature()で取得できる値は設定温度で、他に風呂の温度が規定範囲内か外かのフラグを返す関数が別途ある印象を受けます。
要するに、yubaさんの見解に賛成です。
【追記】
iwamoto_takaakiさんへのコメントを見て追記しています。
PNG画像データは構造を持っていますね。その各構造をオブジェクト指向的なクラスとして実装するのは間違いと私は考えています。
「PNG画像データに何かメッセージを送って何らかの処理をさせる」がオブジェクト指向的な発想ですね。
しかし、PNG画像データは単にデータに過ぎず、自律的に何かの処理を行うのは違和感が強いです。
そのようなデータを保持することが主目的な構造データは「構造体」です。
それは、全てのデータはpublicフィールドで保持し、メソッドはコンストラクタくらいしか持たないものをイメージしています。
そのように考えるとすっきり設計できるのではないでしょうか?
逆に、この概念を排除すると、今回悩まれているようにPNG画像データのような多少複雑な構造を持つデータのハンドリングが悩ましくなります。
投稿2016/07/15 12:01
編集2016/07/16 01:41総合スコア23272
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2016/07/20 13:11
0
知りたいのは”お風呂の温度”ですよね。だったら、Bath.getWaterTemparature()で取得出来るべきかなと思います。当然お湯がなかったら、NoWaterExceptionが帰ってきます。
私は実際のコードが言語に近いほうが、良い設計だと思います。
オブジェクト指向を学ぶ際は、実行可能なコードを書くことを強くおすすめします。概念的になりすぎて、実際のコードに反映出来ないのであれば、オブジェクト指向のコードの勉強として意味が無いです。(実際のプログラムでは無いですよね?念のため・・・)
投稿2016/07/15 13:40
総合スコア2883
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2016/07/15 15:27 編集
2016/07/15 23:56
退会済みユーザー
2016/07/20 13:05
0
"この時、Houseインスタンスからtemperatureフィールドの値を取得しようとする" 用途が多ければ非常に使いづらいので、別途Utiltilyを作成して簡単に属性を取得できるクラスを設けるくらいでしょうか。
アクセサメソッドが多くなってしまう問題とクラス階層が深くなってしまう話はそこまで密接な関係ではないように思えますし、あまりに煩雑だと思うのであればCommons-OGNLのようなライブラリを使うなどで回避するでしょう。
DataTransferObjectのような、属性の出し入れしか提供しないクラスであれば、つけてもつけなくても一緒です。
投稿2016/07/15 10:31
総合スコア12011
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2016/07/15 15:05
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/07/15 13:16
退会済みユーザー
2016/07/15 15:01