概要
ドメインオブジェクト自体が複雑になってくると、その生成ロジックも同じく複雑になりやすい。
複雑化したドメインオブジェクトの生成ロジックをクライアント側にもたせると、ドメインが流出してしまう懸念がある。
上記の課題を解決するには、以下のような解決策が考えられる。
- ドメインオブジェクト自身にFactoryメソッドをもたせる
- ドメインオブジェクトの生成を責務とするFactoryクラスを用意する
今回は「ドメインオブジェクト自身にFactoryメソッドをもたせる」ことをArchUnitを使用して機械的にチェックしてみる。
実行環境
// build.gradle
dependencies {
testImplementation 'com.tngtech.archunit:archunit-junit5:0.14.1'
}
test {
useJUnitPlatform()
}
テスト対象のイメージ
// Hoge.java
public class Hoge {
public Hoge create() {
return this;
}
public void fuga() {}
private Hoge(){};
}
テストコード
@AnalyzeClasses(packages = "com.example")
public class DomainObjectTest {
// コンストラクタはすべてprivateであること
@ArchTest
static ArchRule domain_object_has_no_public_constructors =
constructors()
.that().areDeclaredInClassesThat().haveSimpleName("Hoge")
.should().bePrivate();
// Hogeクラスにcreateという名前の自身を返すpublicメソッドが存在すること
@ArchTest
static ArchRule domain_object_has_factory_methods =
methods()
.that().areDeclaredInClassesThat().haveSimpleName("Hoge")
.and().haveName("create")
.should().haveRawReturnType(Hoge.class)
.andShould().bePublic();
テストしている内容はコメントに記載の通り。
新しいドメインオブジェクトが追加されたときでも、パッケージやクラス名で動的にテスト対象を追加できるような仕組みにできるとより実用的になりそう。