1. 序章

この記事は、C4モデルに基づくアーキテクチャの定義と視覚化へのプログラムによるアプローチを提供するツールであるStructurizrについてです。

Structurizrは、UMLなどのアーキテクチャダイアグラムエディタの従来のドラッグアンドドロップアプローチを打ち破り、私たちが最もよく知っているツールであるJavaを使用してアーキテクチャアーティファクトを記述できるようにします。

2. 入門

開始するには、 structurizr-core依存関係をpom.xml:に追加しましょう。

<dependency>
    <groupId>com.structurizr</groupId>
    <artifactId>structurizr-core</artifactId>
    <version>1.0.0</version>
</dependency>

3. システム

サンプルアーキテクチャのモデリングを始めましょう。 マーチャントが支払いを清算するために使用する不正検出対応の決済端末を構築しているとします。

まず、ワークスペースモデルを作成する必要があります。

Workspace workspace = new Workspace("Payment Gateway", "Payment Gateway");
Model model = workspace.getModel();

また、そのモデル内でユーザーと2つのソフトウェアシステムを定義します。

Person user = model.addPerson("Merchant", "Merchant");
SoftwareSystem paymentTerminal = model.addSoftwareSystem(
  "Payment Terminal", "Payment Terminal");
user.uses(paymentTerminal, "Makes payment");
SoftwareSystem fraudDetector = model.addSoftwareSystem(
  "Fraud Detector", "Fraud Detector");
paymentTerminal.uses(fraudDetector, "Obtains fraud score");

システムが定義されたので、ビューを作成できます。

ViewSet viewSet = workspace.getViews();

SystemContextView contextView = viewSet.createSystemContextView(
  paymentTerminal, "context", "Payment Gateway Diagram");
contextView.addAllSoftwareSystems();
contextView.addAllPeople();

ここでは、すべてのソフトウェアシステムと人を含むビューを作成しました。 次に、ビューをレンダリングする必要があります。

4. PlantUML経由で表示

前のセクションでは、単純な支払いゲートウェイのビューを作成しました。

次のステップは、人間にわかりやすい図を作成することです。 おそらく、すでに PlantUML を使用している組織にとって最も簡単な解決策は、StructurizrにPlantUMLエクスポートを実行するように指示することです。

StringWriter stringWriter = new StringWriter();
PlantUMLWriter plantUMLWriter = new PlantUMLWriter();
plantUMLWriter.write(workspace, stringWriter);
System.out.println(stringWriter.toString());

ここでは、結果のマークアップが画面に印刷されますが、ファイルに送信するのも同じくらい簡単です。 この方法でデータをレンダリングすると、次の図が生成されます。

5. StructurizrWebサイトから表示

ダイアグラムをレンダリングするための別のオプションがあります。 アーキテクチャビューは、クライアントAPIを介してStructurizrWebサイトに送信できます。 次に、豊富なUIを使用して図が生成されます。

APIクライアントを作成しましょう:

StructurizrClient client = new StructurizrClient("key", "secret");

キーとシークレットのパラメーターは、Webサイトのワークスペースダッシュボードから取得されます。 ワークスペースは、次の方法で参照できます。

client.putWorkspace(1337, workspace);

もちろん、ウェブサイトに登録してワークスペースを作成する必要があります。 単一のワークスペースを持つ基本的なアカウントは無料です。 同時に、商業プランも利用できます。

6. コンテナ

いくつかのコンテナを追加して、ソフトウェアシステムを拡張しましょう。 C4モデルでは、コンテナーはWebアプリケーション、モバイルアプリ、デスクトップアプリケーション、データベース、ファイルシステムなど、コードやデータを保持するほとんどすべてのものになります。

まず、決済端末用のコンテナをいくつか作成します。

Container f5 = paymentTerminal.addContainer(
  "Payment Load Balancer", "Payment Load Balancer", "F5");
Container jvm1 = paymentTerminal.addContainer(
  "JVM-1", "JVM-1", "Java Virtual Machine");
Container jvm2 = paymentTerminal.addContainer(
  "JVM-2", "JVM-2", "Java Virtual Machine");
Container jvm3 = paymentTerminal.addContainer(
  "JVM-3", "JVM-3", "Java Virtual Machine");
Container oracle = paymentTerminal.addContainer(
  "oracleDB", "Oracle Database", "RDBMS");

次に、これらの新しく作成された要素間の関係を定義します。

f5.uses(jvm1, "route");
f5.uses(jvm2, "route");
f5.uses(jvm3, "route");

jvm1.uses(oracle, "storage");
jvm2.uses(oracle, "storage");
jvm3.uses(oracle, "storage");

最後に、レンダラーにフィードできるコンテナービューを作成します。

ContainerView view = workspace.getViews()
  .createContainerView(paymentTerminal, "F5", "Container View");
view.addAllContainers();

結果の図をPlantUMLでレンダリングすると、次のようになります。

7. コンポーネント

C4モデルの次の詳細レベルは、コンポーネントビューによって提供されます。 作成するのは、以前に行ったことと似ています。

まず、コンテナ内にいくつかのコンポーネントを作成します。

Component jaxrs = jvm1.addComponent("jaxrs-jersey", 
  "restful webservice implementation", "rest");
Component gemfire = jvm1.addComponent("gemfire", 
  "Clustered Cache Gemfire", "cache");
Component hibernate = jvm1.addComponent("hibernate", 
  "Data Access Layer", "jpa");

次に、いくつかの関係を追加しましょう。

jaxrs.uses(gemfire, "");
gemfire.uses(hibernate, "");

最後に、ビューを作成しましょう。

ComponentView componentView = workspace.getViews()
  .createComponentView(jvm1, JVM_COMPOSITION, "JVM Components");

componentView.addAllComponents();

PlantUMLを介して結果の図を表現すると、次のようになります。

8. コンポーネントの抽出

Springフレームワークを使用する既存のコードベースの場合、Structurizrは、Spring注釈付きコンポーネントを抽出し、それらをアーキテクチャアーティファクトに追加する自動化された方法を提供します。

この機能を利用するには、さらに別の依存関係を追加する必要があります。

<dependency>
    <groupId>com.structurizr</groupId>
    <artifactId>structurizr-spring</artifactId>
    <version>1.0.0-RC5</version>
</dependency>

次に、1つ以上の解決戦略で構成されたComponentFinderを作成する必要があります。 解決戦略は、モデルに追加されるコンポーネント、依存関係ツリーの走査の深さなどに影響します。

カスタム解決戦略をプラグインすることもできます。

ComponentFinder componentFinder = new ComponentFinder(
  jvm, "com.baeldung.structurizr",
  new SpringComponentFinderStrategy(
    new ReferencedTypesSupportingTypesStrategy()
  ),
  new SourceCodeComponentFinderStrategy(new File("/path/to/base"), 150));

最後に、ファインダーを起動します。

componentFinder.findComponents();

上記のコードは、パッケージ com.baeldung.structurizr でSpringアノテーションが付けられたBeanをスキャンし、それらをコンポーネントとしてコンテナーJVMに追加します。 言うまでもなく、独自のスキャナー、JAX-RSアノテーション付きリソース、さらにはGoogleGuiceバインダーを自由に実装できます。

サンプルプロジェクトの簡単な図の例を以下に示します。

9. 結論

このクイックチュートリアルでは、StructurizrforJavaプロジェクトの基本について説明します。

そして、いつものように、サンプルコードはGitHubにあります。