★このページは書きかけです
!!!どのメソッドをどのクラスに記述するのかの原則は2つだけ
例えば
#Aクラス
#Bクラス
という2つのクラスがある場合、
*両方の属性を参照しながら処理するメソッドはどちらのクラスに実装すべきなのか?
というのがこの章でのテーマです。\\
メソッドはパラメータ(引数)を持つので、必要なオブジェクトをパラメータで渡すようにすればどのクラスのメソッドとしても実装できてしまいます。しかしそれでは、
#第三者が保守する時に解りづらい
#仕様変更に弱い
という状態になりがちです。\\
保守しづらくなる理由は規則性がないからです。そして仕様変更に弱いのは、クラス間でオブジェクトを不規則に渡してしまうと、変更の影響が思わぬクラスに出てしまうからです。\\
\\
原則は2つしかありません。
#コンポジット集約のような上下関係がクラスにある場合、必要な属性の最上位に当たるクラスのメソッドとする。
#クラスの関係が対等または並列である場合、第3のクラスを作ってそのメソッドとする。(Mediatorパターンの利用)
順に見ていきましょう。

!!必要な属性の最上位に当たるクラスのメソッドとする
この原則は簡単です。受注伝票で考えてみます。\\
受注伝票は、商品ごとの受注個数と商品単価を明細として持ちます。この時、
*ある受注における受注総額を返すメソッド
をどのクラスに実装すべきかを検討してみます。\\
クラス図は次です。\\
[order_methods.png]\\
受注総額を求めるためには、
#各明細ごとの受注額を計算する(受注個数 × 商品単価)
#全明細の受注額を加算する
#受注額を返す
という流れになります。関係するクラスは、
*金額
*商品単価
*受注個数
*受注明細
*受注明細一覧
*受注伝票
と6つありますが、受注総額を返すメソッドはどのクラスで実装するべきでしょうか?\\
答えは簡単で、
*関連するクラスのうち最上位のクラス、つまり受注伝票クラス
です。シーケンス図を見て下さい。
[order_amount.png]
受注伝票を起点にして処理が始まっているのが解ると思います。\\
よくある誤りは、受注伝票クラス内にループ処理を実装してしまうことです。シーケンス図にある
*受注明細の数だけXXする
という部分です。\\
ループ処理が必要になるのは受注明細一覧が受注明細を複数持っているからですが、その実体が
*配列
*List
*Map
*その他
のいずれなのかというのは隠蔽されているべきです。\\
その実体を受注伝票にさらしてしまう実装をすると、複数の受注明細を格納するデータ構造が仕様変更によって変わった時、例えばListからMapに変わったような場合に受注伝票も変えなくてはならなくなります。\\
これを避けるために、そのデータ構造を持っている受注明細一覧の中でループ処理を実装します。つまり、
*複数の受注明細というデータ構造の最上位のクラスが受注明細一覧クラス
なのでここで実装することになります。\\
さらに、
*受注明細一覧クラスから受け取った金額を受注伝票ラスが受注総額として返す
ようにします。\\
ここで注意すべきなのは、受注伝票クラスの「受注総額を返すメソッド」が必要ないと判断する勘違いです。\\
受注伝票を扱うアプリケーションに対して受注明細一覧オブジェクトを返せば一見うまくいくように見えますが、受注明細一覧オブジェクトだけではどの受注に対する明細なのかを特定できません。そのため、受注明細一覧に委譲する形で受注伝票が「受注総額を返すメソッド」を持つべきなのです。\\