ダイコン時代の設計手法 - 例外のログ
例外のログをどの層でとるべきなのか。例えば、DAO層で発生した例外は、サービス層、プレゼンテーション層も通ることになり、基本的にどの層でもcatchすることはできる。
例外のログを書き出しは、次の場所が考えられると思います。
- 例外をthrowするクラス
- プレゼンテーション層でサービスを呼び出すクラス(例えばStrutsのAction)
- プレゼンテーション層から最初に呼び出されるサービス層のメソッド
1は自分達でthrowしない例外もログをとる必要があるので中途半端。
2と3は呼び出す側か呼び出される側かの違いですが、3の方がお勧めです。
3はプレゼンテーション層に関係無くログをとることができるためです。
例えば、2の場合、ある機能は、インタラクティブな操作が要求されるので、
Flashにしたいなんて時に困ることになります。
次に実装方法ですが、必要なすべてのクラスでtry,catchするのではなく
AOP(ThrowsInterceptor)を使うことが望ましいでしょう。
ダイコン時代の設計手法 - ロジックをどこに置くのか
そうなのかっと感心するとともに、実は当惑…。データとそのデータを扱う処理をひとつのものとして扱うのがオブジェクト指向設計であり、保守を容易にするにはそれを目指すべきだと思い込んでいました。
これはもちろん真実だと思います。しかし、次の重要な点が
関連のあるデータと振る舞いを1つに集めることで、
凝集度を上げ結合度を下げることよって保守が容易になる
これまでは語られていないんじゃないかと思います。
これによって上記の言葉は次のように言い換えられると思います。
振る舞いは最も結びつきの高いオブジェクトにおくべきだ
業務ロジックは次のように分解されます。
データとそのデータに最も結びつきの高い振る舞いを1つに集めることで、
凝集度を上げ結合度を下げることよって保守が容易になる
- ユースケース固有
- 永続化
- 共通
ユースケース固有のロジックはエンティティに含めるべきでしょうか?
エンティティに最も結びつきが強いと果たして言えるでしょうか?
例えば、手数料というエンティティがあったとします。
手数料を計算するという振る舞いは通常業務ごとにロジックが
異なるでしょう。
手数料を計算するという振る舞いが最も強く結びついているのは
どのオブジェクトでしょうか。
それは業務(ユースケース)でしょう。
業務ごとにロジックが異なるのを考えても明らかです。
ユースケース固有のロジックはサービス層に置くほうがのが自然です
保守性があがるとおもいます。
永続化のロジックについても考えてみましょう。
例えば、従業員番号で従業員を検索するというロジックを
考えてみましょう。
このロジックが従業員エンティティに存在するのは明らかに変です。
このロジックを呼び出すのは、従業員オブジェクトを手に入れる前の話だからです。
エンティティそのものを更新したり削除したりするロジックは
どうでしょうか。
これはエンティティにあっても良いのかもしれません。
しかし、同一エンティティに対する検索と更新のロジックが
別々の場所に存在すると保守性が悪くなります。
永続化ロジックをエンティティにではなく、永続化層に置く
のは自然なことです。ほうが保守性が高くなると思います。
このように考えていくと、業務ロジックを
サービス層、永続化層におくことは、狭い意味でのオブジェクト指向とは
異なりますが、振る舞いは最も結びつきの強いオブジェクトに置いたほうが
分かりやすく保守性が高まるという点では現実的だと思います。
OO設計
データとそのデータを扱う処理をひとつのものとして扱うのがオブジェクト指向
というのが教科書に必ず書かれていますが、すでにこの考え方はdepricatedじゃないかと。デザインパターンやDependency Injectionを書いていく際のクラス抽出というのは、こうじゃない気がするんですよね。だから教科書の言葉を疑うことから設計をはじめないといけない気がします。
なるほどdeprecatedか(笑)
確かにそういってもいいのかも。ダイコン時代には。
より結びつきの強い部分に振る舞いを割り当てるというのが
その根拠だと。