LoginSignup
11
5

More than 3 years have passed since last update.

Ray.Di オブジェクトグラフの視覚化

Last updated at Posted at 2019-12-02

オブジェクトグラフの視覚化

Guiceの"Grapher"

洗練されたアプリケーションを、Guiceの豊富なイントロスペクションAPIがオブジェクトグラフで詳細に記述することができます。 グラファー拡張機能はグラフを簡単に理解できるように視覚化します。 複雑なアプリケーションの複数のクラスのバインディングと依存関係を統合された図で表示できます。"

Using grapher to visualize Guice applications

以上はGoogle GuiceのGrapherというオブジェクトの依存関係を視覚化するツールの説明です。

これはModuleで設定したオブジェクトの依存関係を以下のようにdotlangという、"グラフを表現するためのデータ記述言語"にに変換することで実現しています。

injector.dot
digraph injector {
  graph [rankdir=TB];

  k_dd456f9 [shape=box, label=<<table cellspacing="0" cellpadding="5" cellborder="1" border="0"><tr><td 
      align="left" port="header" bgcolor="#000000"><font color="#ffffff">EnergySourceProvider<br 
      align="left"/></font></td></tr><tr><td align="left" port="m_f4b5f9f7">&lt;init&gt;</td></tr></table>>, 
      style=invis, margin=0.02,0]
  k_997fdab -> k_1c5031a6 [arrowtail=none, style=dashed, arrowhead=onormal]
  k_119e4fd8 -> k_17b87c3a [arrowtail=none, style=dashed, arrowhead=onormal]
  k_115c9d69 -> i_115c9d69 [arrowtail=none, style=dashed, arrowhead=onormalonormal]
  i_115c9d69:header:e -> k_9acc501 [arrowtail=none, style=solid, arrowhead=normal]
  k_9acc501 -> k_dd456f9 [arrowtail=none, style=dashed, arrowhead=onormalonormal]
}

Ray.ObjectGrapher

Ray.Diでこの機能を実現するRay.ObjectGrapherを開発中です。

例えば以下のモジュールがあるとします。

FakeModule.php
class FakeModule extends AbstractModule
{
    protected function configure()
    {
        $this->bind(LoggerInterface::class)->to(DatabaseLogger::class);
        $this->bind(PdoInterface::class)->toProvider(PdoProvider::class);
        $this->bind()->annotatedWith('dsn')->toInstance('');
        $this->bind()->annotatedWith('id')->toInstance('');
        $this->bind()->annotatedWith('pass')->toInstance('');
        $this->bind(FooInterface::class)->to(Foo::class);
    }
}

ObjectGrapherクラスをモジュールを引数にして実行するとdotファイルができます。

make_dot.php
$dot = (new ObjectGrapher)(new FakeModule);
file_put_contents(__DIR__ . '/test.dot', $dot);

dotコマンドでpng出力します。

dot -T png fake.dot -o fake.png

オブジェクトグラフが描画され、オブジェクトの構造やオブジェクトを繋ぐバインディングが理解しやすくなります。

image.png

線やノードの形や色には意味があります。

  1. 実線は型を表しています。
  2. 点線は型からクラスへのバインディングを表しています。
  3. 2つの矢印は依存がプロバイダーにバインドされてる事を表してます。

ノード

  1. 黒はクラスです。
  2. 灰色はインスタンス(実値)です。

BEAR.Resource

次はBEAR.Sundayのコンポーネントを描画してみましょう。まずはBEAR.Resourceのモジュールで宣言されたモジュールです。BEAR.SundayのコンポーネントはSRP原則を守り、複数のオブジェクトに分割されグラフを構成しています。

$dot = (new ObjectGrapher)(new ResourceModule);

このスクリプトで出力されたdotファイルをPNGに変換しました。

image.png

全体としては複雑ですが、部分を見るとオブジェクト同士の関係は単純です。
よく観察してみてください。Annotations\Readerが5つのクラスから依存されてる事がわかります。

この図なしにこの依存を理解するのは簡単ではありません。

image.png

BEAR.Package

次にBEAR.Sundayで一番大きなオブジェクトグラフ$appを服もBEAR.PackageのPackageModuleを描画しました。

image.png

複雑で大きなグラフですが、クリーンに分割できていると思います。

終わりに

このグラフ描画は、オートワイアリングが必須である GuiceやRay.Diだからこそできるものです。

グラフを描画する事でオブジェクトの構造を理解しやすいようにするだけではなく、誤ったバインディングや不要なバインディングを発見する事もできます。機能が適切な粒度を持って分割されてるか(SRP)のリファクターをする時にも役立つでしょう。

今までも print_oでオブジェクト間の繋がりを表す事ができましたが、このグラファーでは繋がりだけでなく、インターフェイスやプロバイダー、インスタンスなど、どのように繋がれたのかも確認する事ができます。

もうすぐ完成です。

11
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
5