添付ファイルの追加

ログイン済のユーザのみが添付ファイルをアップロード出来ます。

添付ファイル一覧

Kind Attachment Name Size Version Date Modified Author Change note
png
inventory.png 5.2 kB 1 03-1-2012 00:06 ytp
png
inventory2.png 1.9 kB 1 03-1-2012 00:07 ytp
png
order_amount.png 20.0 kB 1 09-1-2012 22:22 ytp
png
order_classes10.png 8.8 kB 1 09-1-2012 22:22 ytp
png
order_classes11.png 17.8 kB 1 09-1-2012 22:22 ytp
png
order_methods.png 14.2 kB 2 31-12-2011 22:38 ytp
png
receipt.png 6.1 kB 1 02-1-2012 21:25 ytp
png
receipt2.png 1.8 kB 1 03-1-2012 00:07 ytp
png
receipt_inventory.png 3.3 kB 1 03-1-2012 00:53 ytp
png
receipt_inventory_seq.png 11.5 kB 1 03-1-2012 20:17 ytp

This page (revision-19) was last changed on 25-7-2014 20:58 by ytp

This page was created on 30-8-2011 15:57 by ytp

Only authorized users are allowed to rename pages.

Only authorized users are allowed to delete pages.

Difference between version and

At line 1 changed 2 lines
★このページは書きかけです
!!!どのメソッドをどのクラスに記述するのかの原則は2つだけ
!!!メソッド実装場所の原則は2つだけ
At line 9 changed one line
メソッドはパラメータ(引数)を持つので、必要なオブジェクトをパラメータで渡すようにすればどのクラスのメソッドとしても実装できてしまいます。しかしそれでは、
メソッドはパラメータ(引数)を持つので、必要なオブジェクトをパラメータで渡すようにすればどのクラスのメソッドとしても実装できてしまいます(AでもBでも実装できる)。\\
しかしそれでは、
At line 13 changed one line
保守しづらくなる理由は規則性がないからです。そして仕様変更に弱いのは、クラス間でオブジェクトを不規則に渡してしまうと、変更の影響が思わぬクラスに出てしまうからです。\\
保守しづらくなる理由は規則性がないからです。そして仕様変更に弱いのは、クラス間でオブジェクトを不規則に渡していると変更の影響が思わぬクラスに出てしまうからです。\\
At line 16 changed 2 lines
#コンポジット集約のような上下関係がクラスにある場合、必要な属性の最上位に当たるクラスのメソッドとする。
#クラスの関係が対等または並列である場合、第3のクラスを作ってそのメソッドとする。(Mediatorパターンの利用)
#ヘッダと明細のような上下関係がクラスにある場合、必要な属性の最上位に当たるクラスのメソッドとする
#クラスの関係が対等または並列である場合、第3のクラスを作ってそのメソッドとする(Mediatorパターンの利用)
At line 24 changed 3 lines
をどのクラスに実装すべきかを検討してみます。\\
クラス図は次です。\\
[order3.png]
をどのクラスに実装すべきかを検討してみましょう。分析クラス図は次です。\\
[order_classes10.png]\\
At line 28 changed one line
#各明細ごとの受注額を計算する(受注個数 × 商品単価)
#明細ごとの受注額を計算する(受注個数 × 商品単価)
At line 31 changed 9 lines
という流れになります。\\
関係するクラスは、
*金額
*受注個数
*商品単価
*受注明細
*受注明細一覧
*受注伝票
と6つありますが、受注総額を返すメソッドはどのクラスで実装するべきでしょうか?\\
という流れになります。関係するクラスは、
#金額
#商品単価
#商品単価一覧
#受注個数
#受注明細
#受注明細一覧
#受注伝票
と7つありますが、受注総額を返すメソッドはどのクラスで実装するべきでしょうか?\\
At line 43 changed one line
[order_amount.png]
[order_amount.png]\\
%%sup ※シーケンス説明の__*__印は繰り返す処理を意味します。/%\\
受注伝票を起点にして処理が始まっているのが解ると思います。\\
よくある誤りは、受注伝票クラス内にループ処理を実装してしまうことです。シーケンス図にある
*受注明細の数だけXXする
という部分です。\\
ループ処理が必要になるのは受注明細一覧が受注明細を複数持っているからですが、その実体が
*配列
*List
*Map
*その他
のいずれなのかというのは隠蔽されているべきです。\\
その実体を受注伝票にさらしてしまう実装をすると、複数の受注明細を格納するデータ構造が仕様変更によって変わった時、例えばListからMapに変わったような場合に受注伝票も変えなくてはならなくなります。\\
これを避けるために、そのデータ構造を持っている受注明細一覧の中でループ処理を実装します。つまり、
*複数の受注明細というデータ構造の最上位のクラスが受注明細一覧クラス
なのでここで実装することになります。\\
さらに、
*受注明細一覧クラスから受け取った金額を受注伝票ラスが受注総額として返す
ようにします。\\
ここで注意すべきなのは、受注伝票クラスの「受注総額を返すメソッド」が必要ないと判断する勘違いです。\\
受注伝票を扱うアプリケーションに対して受注明細一覧オブジェクトを返せば一見うまくいくように見えますが、受注明細一覧オブジェクトだけではどの受注に対する明細なのかを特定できません。そのため、受注明細一覧に委譲する形で受注伝票が「受注総額を返すメソッド」を持つべきなのです。\\
結果的に設計クラス図は次のようになります。\\
[order_classes11.png]\\
!!第3のクラスを作ってそのメソッドとする(Mediatorパターン)
2つのクラスに上下関係にあたるものがない場合、その2つを仲介する3つ目のクラスを作ります。この原則は、Gofのデザインパターンにおける__Mediatorパターン__に応用されています。\\
2つのクラスの関係が密接ではない場合に相手のメソッドを直接呼び出す設計をしていると、どちらかのクラスの仕様変更によってもう一方のクラスも修正しなくてはならない事態に陥りがちです。\\
商品の入荷と在庫を例に考えてみます。必要になるのは、
*入荷伝票
*在庫商品一覧
の2つです。(下図)\\
[receipt.png]\\
[inventory.png]\\
実際の業務では、入荷された商品を倉庫に保存することになります。この時、システム的には入荷伝票を基に在庫数を増やす処理が必要になりますが、この処理(メソッド)をどのクラスで実装するかというのがこの節での命題です。\\
考えられるのは、
#入荷伝票クラス
#在庫商品一覧クラス
#第3のクラス
の3通りです。\\
\\
入荷伝票に実装する場合は、在庫商品一覧クラスをそのメソッドに引数として渡すことになります。\\
[receipt2.png]\\
この時そのメソッド内では、
#入荷明細一覧内の入荷明細の数だけ以下を繰り返す
#在庫商品インスタンスを生成する
#商品、個数、ロケーション、入庫日付を在庫商品に設定する
#在庫商品インスタンスを在庫商品一覧インスタンスに追加する
というように実装することになります。入荷伝票クラスは在庫商品一覧クラスの仕様を熟知している必要があります。\\
\\
逆に在庫商品一覧クラスで実装する場合は、入荷伝票クラスをそのメソッドに引数として渡すことになります。\\
[inventory2.png]\\
この時そのメソッド内では、
#入荷伝票から入荷明細一覧を取り出す
#入荷明細の数だけ以下を繰り返す
#在庫商品インスタンスを生成する
#商品、個数、ロケーション、入庫日付を在庫商品に設定する
#在庫商品インスタンスを自身(在庫商品一覧)のインスタンスに追加する
というように実装することになります。今度は逆に、在庫商品一覧クラスは入荷伝票クラスの仕様を熟知している必要があります。\\
\\
入荷の結果である入荷伝票と在庫の結果である在庫商品一覧が密接に結びついても問題ない場合は上記のいずれかでも構わないのですが、相手側クラスの仕様に変更があった場合はその影響を免れません。\\
こういう場合は、
*第3のクラス
を設計しておく方が、片方のクラスの仕様変更を相手クラスに影響させずに済みます。Gofのデザインパターンにおける
*Mediator(仲介者)パターン
はこの原則を応用したものです。\\
[receipt_inventory.png]\\
この時の処理シーケンスは次のようになります。\\
[receipt_inventory_seq.png]\\
%%sup ※シーケンス説明の__*__印は繰り返す処理を意味します。/%\\
入荷伝票と在庫商品一覧の仲介者として入荷在庫クラスが働いていることが解ります。この手法を理解する上での注意点は、入荷伝票と在庫商品一覧の両方のデータを持つクラスとして入荷在庫クラスを設計することです。\\
単なる仲介者として設計してしまうと「仲介する」処理だけを実装することになります。そうではなく、
*入荷伝票と在庫商品一覧の両方のデータをひとかたまりとしたクラスである
と強く意識して設計して下さい。\\
\\
この節の冒頭にも書きましたが、入荷伝票と在庫商品一覧をあえて強く結びつけたい場合はいずれかのメソッドとして設計して下さい。
#仲介者を通じて疎結合にするのか
#直接呼び出す密結合にするのか
いずれの方法を採るのかは設計者の意図によって変わってきます。しかし迷った場合は第2の原則に従いましょう。\\
!!まとめ
どのメソッドをどのクラスで実装するのかの原則は2つ。
#ヘッダと明細のような上下関係がクラスにある場合、必要な属性の最上位に当たるクラスのメソッドとする
#クラスの関係が対等または並列である場合、第3のクラスを作ってそのメソッドとする(Mediatorパターンの利用)
!!コラム
メソッド実装の原則が2つしかないというのはにわかには信じがたいかも知れません。複雑な関連を持つクラス図を考えるともっとたくさんありそうだと感じるのも無理はありません。\\
しかし複雑な関連も紐解いていけば、最終的には2つのクラスの関係に分解できます。その2つのクラスにまたがる処理を考える場合、その2つのクラスが
#上下関係がある
#並列関係になっている
の2パターンに分類できるのは理解できることでしょう。\\
このように、一見複雑なものもその原則は単純であることが多いのです。複雑に絡み合った結果であるパターンの奥には単純な原則が隠れています。それを見抜く力を付けることが一番大切だと私は感じています。\\
\\
次: [業務シナリオで考える]
Version Date Modified Size Author Changes ... Change note
19 25-7-2014 20:58 3.888 kB ytp to previous
18 11-3-2012 23:19 3.902 kB ytp to previous | to last
17 09-1-2012 22:25 3.902 kB ytp to previous | to last
16 09-1-2012 03:07 3.893 kB ytp to previous | to last
15 09-1-2012 02:59 3.852 kB ytp to previous | to last
14 09-1-2012 02:52 3.843 kB ytp to previous | to last
13 03-1-2012 23:57 3.791 kB ytp to previous | to last
12 03-1-2012 23:42 3.766 kB ytp to previous | to last
11 03-1-2012 23:41 3.766 kB ytp to previous | to last
10 03-1-2012 22:52 3.781 kB ytp to previous | to last
9 03-1-2012 00:44 2.894 kB ytp to previous | to last
8 03-1-2012 00:39 2.839 kB ytp to previous | to last
7 02-1-2012 22:28 2.793 kB ytp to previous | to last
6 01-1-2012 01:19 1.854 kB ytp to previous | to last
5 31-12-2011 23:25 1.607 kB ytp to previous | to last
4 10-9-2011 12:02 1.594 kB ytp to previous | to last
3 31-8-2011 01:21 1.592 kB ytp to previous | to last
2 30-8-2011 22:20 0.926 kB ytp to previous | to last
1 30-8-2011 15:57 0.626 kB ytp to last
« This page (revision-19) was last changed on 25-7-2014 20:58 by ytp