Hatena::ブログ(Diary)

yvsu pron. yas このページをアンテナに追加 RSSフィード

2004-06-10

台風接近飛行機飛ぶのか!!!

Seasarのからさわぎ in 沖縄

OO設計

データとそのデータを扱う処理をひとつのものとして扱うのがオブジェクト指向

というのが教科書に必ず書かれていますが、すでにこの考え方はdepricatedじゃないかと。デザインパターンDependency Injectionを書いていく際のクラス抽出というのは、こうじゃない気がするんですよね。だから教科書の言葉を疑うことから設計をはじめないといけない気がします。

hysteric programmer diary: OO設計

なるほどdeprecatedか(笑)

確かにそういってもいいのかも。ダイコン時代には。

より結びつきの強い部分に振る舞いを割り当てるというのが

その根拠だと。

ダイコン時代の設計手法 - ロジックをどこに置くのか

そうなのかっと感心するとともに、実は当惑…。データとそのデータを扱う処理をひとつのものとして扱うのがオブジェクト指向設計であり、保守を容易にするにはそれを目指すべきだと思い込んでいました。

はてなダイアリー - taediumの日記

関連のあるデータと振る舞いを1つに集めることで、
凝集度を上げ結合度を下げることよって保守が容易になる

これはもちろん真実だと思います。しかし、次の重要な点が

これまでは語られていないんじゃないかと思います。

振る舞いは最も結びつきの高いオブジェクトにおくべきだ

これによって上記の言葉は次のように言い換えられると思います。

データとそのデータに最も結びつきの高い振る舞いを1つに集めることで、
凝集度を上げ結合度を下げることよって保守が容易になる

業務ロジックは次のように分解されます。

  • ユースケース固有
  • 永続化
  • 共通

ユースケース固有のロジックはエンティティに含めるべきでしょうか?

エンティティに最も結びつきが強いと果たして言えるでしょうか?


例えば、手数料というエンティティがあったとします。

手数料を計算するという振る舞いは通常業務ごとにロジックが

異なるでしょう。

手数料を計算するという振る舞いが最も強く結びついているのは

どのオブジェクトでしょうか。

それは業務(ユースケース)でしょう。

業務ごとにロジックが異なるのを考えても明らかです。

ユースケース固有のロジックはサービス層に置くほうがのが自然です

保守性があがるとおもいます。


永続化のロジックについても考えてみましょう。

例えば、従業員番号で従業員を検索するというロジックを

考えてみましょう。

このロジックが従業員エンティティに存在するのは明らかに変です。

このロジックを呼び出すのは、従業員オブジェクトを手に入れる前の話だからです。

エンティティそのものを更新したり削除したりするロジックは

どうでしょうか。

これはエンティティにあっても良いのかもしれません。

しかし、同一エンティティに対する検索と更新のロジックが

別々の場所に存在すると保守性が悪くなります。

永続化ロジックをエンティティにではなく、永続化層に置く

のは自然なことです。ほうが保守性が高くなると思います。


このように考えていくと、業務ロジックを

サービス層、永続化層におくことは、狭い意味でのオブジェクト指向とは

異なりますが、振る舞いは最も結びつきの強いオブジェクトに置いたほうが

分かりやすく保守性が高まるという点では現実的だと思います。

テストはいつ作る

うちの会社は詳細設計書の中に事前条件・事後条件を記述するようになっていて

詳細設計書がテスト仕様書を兼ねています。

ロジックのレビューと同時にテスト仕様書のレビューも行えるので、

精度がかなり上がります。

ダイコン時代の設計手法 - 例外のログ

例外のログをどの層でとるべきなのか。例えば、DAO層で発生した例外は、サービス層、プレゼンテーション層も通ることになり、基本的にどの層でもcatchすることはできる。

OZACC.blog

例外のログを書き出しは、次の場所が考えられると思います。

  1. 例外をthrowするクラス
  2. プレゼンテーション層でサービスを呼び出すクラス(例えばStrutsのAction)
  3. プレゼンテーション層から最初に呼び出されるサービス層のメソッド

1は自分達でthrowしない例外もログをとる必要があるので中途半端。

2と3は呼び出す側か呼び出される側かの違いですが、3の方がお勧めです。

3はプレゼンテーション層に関係無くログをとることができるためです。

例えば、2の場合、ある機能は、インタラクティブな操作が要求されるので、

Flashにしたいなんて時に困ることになります。


次に実装方法ですが、必要なすべてのクラスでtry,catchするのではなく

AOP(ThrowsInterceptor)を使うことが望ましいでしょう。

makotanmakotan 2004/06/10 07:51 今のままだと離陸さえ出来れば大丈夫の予感

ukki4903ukki4903 2004/06/10 13:05 うちも詳細設計に事前条件・事後条件は書いてます。が、所詮条件なので、実際の値をあてはめたテストは必要ですよね?

higayasuohigayasuo 2004/06/10 13:33 もちろん、JUnitなどの実際のテストはおこないます。ほぼ、テストコードにそのまま落とせるくらい詳細に事前条件・事後条件は書かせてます。

ukki4903ukki4903 2004/06/10 14:04 うちは納品物としてテストの*ドキュメント*を納めないといけないので辛いです。(T_T) JUnitのJavaDocを工夫して〜でOKの場合もあるのですが、ExcelあるいはWordのチェックリストを納品せよと…。

uguuuguu 2004/06/10 18:56 doclet を拡張して Excel や Word のリストをはき出せる doclet ツールを作成してしまえばいいのではないかと。便利だと思います。>ukki4903

SaisseSaisse 2004/06/10 22:17 僕の場合は、はじめにオブジェクトをデータと処理に分けてしまって、その中に実装を振り分けていくって方法を使ってます。

guionguion 2004/07/13 11:21 ”ユースケース固有のロジックはエンティティに含めるべきでしょうか?”っていう問いは、定番の格言である”継承より委譲”という言葉の焼き直しです…よね?ユースケース側とエンティティ側のオブジェクトが委譲--被委譲の関係(どっちがどっちなのかはともかく)にあるんだと思います。自分的には前者を”する側オブジェクト”、後者を”される側オブジェクト”と呼んでます。両方の性(?)が居て世の中バランスが取れるんだろうなと。