JIG を使用した開発のチュートリアルです。 以下の順番で進めます。
- プロジェクトの準備
- JIGの導入
- ビジネスルールの開発
- アプリケーションの開発
このチュートリアルを終えれば、コードをどまんなかに据えたモデリングができるようになります。
- 🎓 は説明です。操作はありません。
- 🏷 は本リポジトリのコミットです。やっていることがわからない場合などに使用してください。
- 📝 はチュートリアルからは外れる内容ですが、知っておくと役立つことを書いています。
開発するアプリケーションのプロジェクトを作成します。ここでは以下を使用します。
- JDK
11 - JIG
2019.12.1 - Gradle
6.0.1 - Graphviz
2.43.0 - Spring Boot
2.2.2.RELEASE
このセクションは一般的なJavaプロジェクトの作成です。 Gradleでビルドできるなら、どのような方法で作成しても構いません。
GradleのBuild Init Pluginを使用してプロジェクトを作成します。
$ gradle init --type java-library \
--test-framework junit-jupiter \
--dsl groovy \
--project-name jig-tutorial \
--package jig.tutorialGradleのbuildタスクを実行してください。
$ ./gradlew build
BUILD SUCCESSFUL in 5s
4 actionable tasks: 4 executed上記のように BUILD SUCCESSFUL が出力されればOKです。JDKとGradleの確認ができました。
お好きなIDEに取り込んでください。
🏷 b61193ca161c711066dd424b29badae963d6bd24
JIGが標準でサポートするアーキテクチャは ドメインを独立させる Isolating the Domain です。 Isolating the Domainのパッケージ構成は以下の通りです。
.
+-- presentation
| +-- controller
| +-- view
+-- application
| +-- service
| +-- repository
+-- infrastructure
| +-- datasource
| +-- transfer
+-- domain
+-- type
+-- model
JIGではこれらを「ビジネスルール」と「アプリケーション」に分類します。
- アプリケーション: 三層。
presentation,application,infrastructureパッケージ。 - ビジネスルール: ドメインモデル。
domainパッケージ。
📝 Isolating the Domainに準拠していなくても、JIGドキュメント自体の出力は可能です。
JIG Gradle Plugin を導入します。
build.gradle の plugins に org.dddjava.jig-gradle-plugin を追加します。
plugins {
id "org.dddjava.jig-gradle-plugin" version "2019.12.1"
}JIGドキュメント出力時にコンパイルするよう、 build.gradle に以下を追加します。
[compileJava, processResources]*.mustRunAfter(clean)
jigReports.dependsOn(clean, classes)jigReports を実行して BUILD SUCCESSFUL となればOKです。
$ ./gradlew jigReports
> Task :jigReports
skipped ...
BUILD SUCCESSFUL in 11s
1 actionable task: 1 executed🏷 a643f07c5762d49e7166a58b48332c5e9c5df5e3
📝 jigReports の実行はIDEのワンアクションで行えるようにしておくとスムーズです。
📝 Gradleを使用していない、Gradleのバージョンが古いなどで JIG Gradle Plugin が使用できない場合は コマンドライン版 を使用して出力できます。
JIGはダイアグラム出力にGraphvizを使用しています。 インストールされていることを確認してください。
$ dot -V
dot - graphviz version 2.43.0 (0)JIG Gradle Plugin 2019.12.2 以降なら verifyJigEnvironment タスクで実行環境を検証できます。
$ ./gradlew verifyJigEnvironment
> Task :verifyJigEnvironment FAILED
-- JIG ERROR -----------------------------------------------
+ 実行可能なGraphVizが見つけられませんでした。
+ dotにPATHが通っているか確認してください。
+ JIGはダイアグラムの出力にGraphVizを使用しています。
+
+ GraphVizは以下から入手できます。
+ https://www.graphviz.org/
------------------------------------------------------------JIGドキュメントには以下があります。
- ビジネスルールドキュメント
- BusinessRuleList
- PackageRelationDiagram
- BusinessRuleRelationDiagram
- CategoryDiagram
- CategoryUsageDiagram
- アプリケーションドキュメント
- ApplicationList
- BranchList
- ServiceMethodCallHierarchyDiagram
- BooleanServiceDiagram
- アーキテクチャドキュメント
- ArchitectureDiagram
- PackageTreeDiagram
これらを使用して開発をすすめます。
ビジネスルールを開発してみましょう。 チュートリアルでは「商品の注文を受けて出荷する」を扱います。
はじめに jig.tutorial.domain.model.product パッケージに商品クラスを作成します。
中身は空で構いません。
package jig.tutorial.domain.model.product;
public class Product {
}作成できたらGradleで jigReports タスクを実行します。
./build/jig に business-rule-relation.svg が出力されます。
🏷 ce64e504f95e1d72b35412e24493bfbbdbc91a85
商品としての関心ごとを挙げ、全てに対するクラスを作成していきます。 ここでは商品名と定価を持つとします。
先ほどと同様にNameクラスとPriceクラスを作成します。
🏷 65467f34507d197d5a50096d1fb75fd119e21f7e
商品名と定価は商品が使用するので、Productのフィールドに追加します。
public class Product {
Name name;
Price price;
}🏷 48470763c78c7f3aa27e5bfa47256bfccff11119
Javadocコメントに日本語名を記述します。
/**
* 商品
*/
public class Product {🏷 4a072917cd9caeba8339870a34fb393d0a22d6a3
次に注文と出荷を開発します。 商品と同様にパッケージとクラスを作成します。
- 注文:
jig.tutorial.domain.model.order - 出荷:
jig.tutorial.domain.model.shipment
🏷 4a0dd1192fd2b1adbef39c410bf71c868d4dcb94
注文は商品、出荷は注文と商品を扱います。それぞれフィールドに追加します。
パッケージ間の関連ができると package-relation-depth*.svg が出力されます。
和名は package-info.java のJavadocで記述できます。
🏷 36f089f4f049bc13db7912afe3cc467da33176d6
取り扱うステータスを enum で列挙します。
- 商品在庫: 在庫あり、在庫なし
- 注文ステータス: 注文受付済み、出荷済み、キャンセル
enum は category.png に出力されます。
商品在庫を商品のメソッドで返します。
public class Product {
...
public ProductStock productStock() {
return ProductStock.在庫あり;
}使用が category-usage.png に出力されます。
🏷 37f68c5b0f669bab4433de7ec634b01ec5a69d59
ここまでの設計は business-rule.xlsx で一覧できます。
相互依存があると赤矢印が出力されます。
相互依存の原因となっているクラスは bidirectionalRelations-depth*.txt に出力されます。
パッケージをネストするとパッケージの深さごとにパッケージ関連図が出力されます。
ビジネスルールを自由に開発してみましょう。
ドメインの言葉でクラスを作成してJavadocに日本語名を書いていきます。
関連すると思われるクラスをフィールドやメソッドなどで使用しながらラフに関連を設計します。 このアプローチでは処理は二の次で構いません。
ある程度関連が設計できたら処理を記述していきます。 想定外の依存が発生するなどぎこちなくなるとJIGドキュメントからフィードバックが得られます。
アプリケーションを開発してみましょう。 このチュートリアルではSpringBootを使用します。
最低限
spring-contextさえあれば開発は可能です。
spring-boot-starter-web を依存関係に追加します。
dependencies {
implementation platform('org.springframework.boot:spring-boot-dependencies:2.2.2.RELEASE')
implementation("org.springframework.boot:spring-boot-starter-web")
}🏷 3022c08f6b43111ab67dc0c467e0e67b4d6425b4
@Controller, @Service, @Repository を付与したクラスを作成します。
jig.tutorial.presentation.controller.SampleControllerjig.tutorial.application.service.SampleServicejig.tutorial.application.repository.SampleRepositoryjig.tutorial.infrastructure.datasource.SampleDataSource
クラスを作成したら商品を取得するメソッドを作成します。
続いてJavadocを記述します。JIGはJavadocから以下を読み取って使用します。
Controllerのクラス名Serviceのクラス名、メソッド名Repositoryのクラス名
サービスのメソッド呼び出しが service-method-call-hierarchey.svg に出力されます。
🏷 de6ef6ead230fb8d9a349f4a12c09204c2197fd4
ここまでの設計は application.xlsx で一覧できます。
アプリケーションを自由に開発してみましょう。 必要に応じてビジネスルールを充実させていきましょう。
ArchitectureDiagram architecture.svg には、アーキテクチャブロックの関連が出力されます。
domainから他への依存のような、意図しない依存が発生していないかの確認に役立ててください。
BooleanServiceDiagram は真偽値を返すサービスを作成した場合に出力されます。 サービスが真偽値を返すと、呼び出し元で機械的な判定を行う必要があります。
BranchList branches.xlsx はアプリケーションの各メソッドの分岐数です。
分岐はビジネスルールの可能性があります。
ビジネスルールであればアプリケーションからビジネスルールに移動し、ドメインモデル貧血症を予防しましょう。
JIGでの開発は以下のようになります。
- 頭の中やホワイトボードなどで描く
- コードで書いてみる
- JIGドキュメントを眺める
- フィードバックを得ながら考える
- コードで書いてみる
- JIGドキュメントを眺める
- ...(以下ループ)
参考: JIGを使った設計
















