ひがやすを技術ブログ

電通国際情報サービスのプログラマ

ダイコンがそこにある理由

従来のオブジェクト指向では、データと振る舞いを1つに
してクラスにまとめます。
これがオブジェクト指向の最も重要なポイントとされてきた
わけですが、業務アプリケーションに限っていうと
話が変わってきます。


例えば、手数料というデータがあったとします。
手数料を計算するという振る舞いは通常業務ごとにロジックが
異なるでしょう。
この振る舞いはいったいどこに置くべきでしょうか。
仮にデータといっしょにしたとしましょう。
業務が追加・変更されるたびにクラスを修正するということは、
ありえないので、業務ごとに派生クラスを作って手数料を計算する
メソッドを実装することになるでしょう。
新たな業務Cができ、この業務Cは、業務Aと業務Bを組み合わせた
業務だとします。このとき業務CはAを継承すべきでしょうか、
Bを継承すべきでしょうか。
たぶん、どっちを継承してもうまくいかないでしょう。
これは、継承は元のクラスに対する依存性が高くなるので
できるだけ委譲を使って処理した方が良いという話につながって
きます。


それではどうすれば良いのでしょうか。
手数料を計算するという振る舞いを別のクラスに切り出します。
業務Cは業務AとBの手数料を計算するという振る舞いをもった
オブジェクトをインスタンス変数として持ち、
それぞれに処理を委譲すれば良いのです。


業務ロジックは、複数の業務ロジックの組み合わせで成り立って
いることが多いでしょう。このような場合、継承を使うよりも
個々の業務ロジックを疎結合にして、それぞれの業務ロジックに
処理を委譲した方が変更に強く、保守性に優れたシステムになります。


このように考えていくと、業務ロジックはデータから分離し、
できるだけ疎結合にした方が、良いということが分かるでしょう。
つまりはステートレスです。
また、業務ロジック同士をできるだけ疎結合にするためには、
実装クラスではなく、インターフェースを通じて処理をした方が
いいでしょう。
これは、インスタンス変数の型は実装クラスのものではなく、
インターフェースで宣言しておき、インターフェース型の
オブジェクトに処理を依頼した方が良いということです。
インターフェースと実装を分離することで、

  • モックを使って簡単にテストできるようになったり
  • 実装が出来上がってなくても平行して開発が進められるようになったり

するというメリットが生まれます。


このような開発スタイルをとった場合、誰かが業務ロジック同士の
依存関係を解決する必要があります。
このようなニーズは汎用的であるため、フレームワーク化されていた方が
いいでしょう。
設定ファイルに書いてある内容をもとに依存関係を解決する仕組みが
Dependency Injection Container -> DIContainer -> ダイコン
になるわけです。
ダイコンで管理されている業務ロジックがステートレスで
シングルトンなのもこのような理由があるのです。