DIな実装とそのクラス図

// 旧実装
public class Hoge {
  public void invokeFoo() {
    Foo foo = new Foo();
    foo.executeFoo();
  }
}
public class Foo {
  public void executeFoo() { ... }
}

というクラスは、DIconを使うことで↓こうなります。

// DI実装
public class Hoge {
  private Foo foo;
  public void setFoo(Foo foo) { ... }
  public void invokeFoo() {
    foo.executeFoo();
  }
}
public class Foo {
  public void executeFoo() { ... }
}

※FooはDIで管理するに足る機能を持っているとします。


ここではFooをインスタンス変数に保持するようになったところがポイントです。
両者の違いが、開発容易性(EoD)、テスト容易性(EoT)、保守性などにどのように効いてくるのか、というのはDependencyInjection自体の話題なのでここでは触れません。


ついさっき、上記のようにクラス実装が変わると、UMLの(実装レベルの)クラス図の記述も変わることに気づきました。

旧実装の場合、HogeクラスからFooへ引かれるのは「依存」線が妥当だと思います。useステレオタイプをつけるとベストだと思います。クラスの静的構造としてFooに関連しているわけではないからです。あくまでメソッド内部の現在の実装でFooに依存しているだけで、将来的にFooを使わない実装になるかもしれません。
(参考)Martin Fowler's Bliki in Japanese - クラス図におけるローカル変数


これがDI実装になると、「関連」線になります。

このような関連/依存の使い分けは、当然人によって色々意見があると思いますが、実際ツール(JUDE等)などでソースからリバースエンジニアリングでクラス図を作成してみると、大体こんな感じで解釈しているように思えます。スケッチや、分析・仕様レベルのクラス図であれば、全て「関連」で表現して構わないと思います。


いったい何が言いたいのかというと、
ある既存システムのコードを解析しようとして、手始めにJUDEでソースからクラス図を作成させたわけです。
すると、インスタンス変数なクラスへの関連はきちんと表示されるんですが、ローカル変数なクラスへの依存線は表示されなかったんです。残念ながら依存を解釈/表示するオプションも見つかりませんでした。


そこでふと思ったわけです。
依存じゃなくて関連なのであれば表示されるのになぁと。


で、気がついたわけです。

DI実装だと、HogeはFooをインスタンス変数で保持するので「関連」である。
  ↓
HogeとFooの関連がクラス図上できちんと表示される。
  ↓
アプリケーションの構造が把握しやすくて助かる。
  ↓
(゚Д゚)ウマー

DI指向でやっているとこんなところでもいいことがあるんだなぁと。

もちろん、きれいなクラス図を作成させるためだけに、無駄にインスタンス変数に保持させる実装にしたりするのは本末転倒です。


クラス間の相互作用はコラボレーション図で書けばいいのでは、という声が聞こえてきそうですが、それってリバースでは作成できないでしょ?