Teeda Extension featuring Goya 〜内部設計【AOPの適用】〜

要件定義外部設計(アーキテクチャ)内部設計コーディング単体テスト結合テスト

AOPの適用は、自分でも何となくやってしまっているところがあり、設計手法として改めて考えてみると、説明が難しいところがあります。
今回は、自分なりの考えをまとめてみます。

AOPをどこに適用すれば良いのか?

AOPとは何か?」って聞かれたら答えやすいのですが、「AOPをどこに適用すれば良いのか?」と聞かれると、答えるのが難しいですね・・・。


自分で設計していても、感覚的に決めてしまっているように思います。
AOPの例として、トランザクションやロギング処理が良く取り上げられるますが、それらはシステム全体としては、どのように位置づけられるのでしょうか?


システムとして、ユーザに適用する機能(core concern)とAOPで実現する機能(crosscutting concern)は、縦横のような関連を持ちます。
そこで、トランザクションやロギングの処理を考えてみると、共通項として得られるのは、

    • レイヤー
    • 業務に依存しない共通処理

ではないかと思います。


AOPの適用箇所について、いろいろと調べて見ましたが、僕が考えるAOPの適用ポリシーでも、似たようなことが書かれていました。


Seasar2では、便利なInterceptorが標準で多く提供されている(S2AOPで用意されているInterceptor)ため、独自で作成する機会はあまりないかもしれませんが、私の場合、上のような視点で適用箇所を見出しています。

AOPに対する危惧

AOPの解説などを見ていると、「機能をあとづけできます!」という記述を良く見かけます。
しかしながら、それって、AOPを「銀の弾」扱いしすぎているように思います。


たしかに、あとづけ「も」できますよ。
ただ、AOPは、適用箇所(JointPoint)なども限られます。S2やSpringなどのDIコンテナで、確実にAOPは利用しやすくなりましたが、やはりある程度設計しておかないと、後から適用できないことがわかって、全機能を修正する必要がでてきた、なんてことに陥る可能性があります。


少なくとも、適用するレイヤーと、そこで必要となるパラメータぐらいは決めておくと良いでしょう。
大抵は、それでAOPで実現できるかどうかを判断できると思います。

また、アーキテクチャ設計で、レイヤー設計をきちんと行っておくと、AOPの適用箇所も考えやすくなります。

Teeda Extension featuring Goya 〜内部設計〜

要件定義外部設計(アーキテクチャ)内部設計コーディング単体テスト結合テスト

今回から、数回に分けて内部設計について紹介していきます。

工程の位置づけ

システムがユーザに提供するものが、システム内部でどのように振舞うかを定義します。

  • 各機能で、外部設計と実装を結びつけるもの(外部設計の検証にもなる)
  • 機能横断的に呼び出されるもの

成果物

  • UIモックアップ(更新)
  • CRUDマトリクス
    • 機能毎にCRUDの処理内容をまとめる。操作シナリオとデータモデル(DB設計)の検証にもなる。
    • 作成するのは手間がかかるが、試験のときのことを考えても作成しておくことをお勧めする。
  • 業務ロジック設計
    • 複雑な業務ロジックについて設計を行う(すべてのロジックについて行う必要はない)。主に、処理レシピとして書き出した内容が設計の対象となる。
  • 共通機能設計
    • Interceptor/Helper/Utilityに関する設計を行う。


設計では、どのような手法を利用しても構いません。設計/実装者が慣れた方法を取ることが良いでしょう。


共通機能を抽出する際の考え方

共通機能は、先に述べたInterceptor/Helper/Utilityに大別されます。それぞれの内容と抽出する考え方は、以下のようになります。

Interceptor
  • 内容
  • 抽出する際の考え方
    • 業務的な処理には、あまり関係しない処理である
    • 特定のレイヤーの呼び出しの前後で処理を行いたい
Helper
  • 内容
    • 機能横断的に呼び出されるが、パラメータ設定などのため、DI対象となるコンポーネント
  • 抽出する際の考え方
    • 事前にパラメータを設定したい
    • アプリケーション側から明示的に呼び出す必要がある
    • メール送信*1、ファイルアップロード/ダウンロード
Utility
  • 内容
  • 抽出する際の考え方
    • staticに呼び出すだけ
    • 引数だけで戻り値が一意に決まり、状態などには因らない
    • 文字列変換処理

*1:簡単な通知処理ならば、Interceptorとして実現できることもあります。条件によって送信先が変わるような場合は、Helperとして実装した方が実現しやすいでしょう