コンテンツにスキップ
  • 中級者向け

Layout システムでディレクトリ構成を厳守させる

ファイルをどこに置けるかを定義する

Section titled “ファイルをどこに置けるかを定義する”

Role に対応するファイルをどこに置けるかを定義するのが layout { } です。

architecture {
"UseCase" {
// UseCase は useCase/ の中の *UseCase.kt にだけ置けます
layout {
"src/main/kotlin/com/example/useCase" / "*UseCase".ktFile()
}
}
}

ディレクトリ宣言の書き方のスタイル

Section titled “ディレクトリ宣言の書き方のスタイル”

ディレクトリ宣言にはいくつか書き方があり、好みのスタイルで書けます。

各階層に置くものが1つだけのときは、/ で繋いで1行で書けます。

layout {
"src/main/kotlin/com/example/useCase" / "*UseCase".ktFile()
}

同じディレクトリに複数のものを置くときは、ブロックで囲みます。

layout {
"src/main/kotlin/com/example/useCase" {
"Get*UseCase".ktFile()
"Update*UseCase".ktFile()
}
}

ブロックの中では description を書けます。生成ドキュメントで「この置き場所は何か」の説明になります。

layout {
"src/main/kotlin/com/example/useCase" {
description = "複数の画面から使われるもの"
"*UseCase".ktFile()
}
}

anyFile() — 直下のファイルだけ許す

Section titled “anyFile() — 直下のファイルだけ許す”

そのディレクトリの直下に限って、どんなファイルでも置けるようにします。

layout {
"generated" { anyFile() }
}

この例ではサブディレクトリは許されません。 1階層下にファイルがあれば、それは違反のまま報告されます。

ignore() — 以下すべての検査をやめる

Section titled “ignore() — 以下すべての検査をやめる”

そのディレクトリより下を、どの深さでも検査しなくなります。

layout {
"build".ignore()
}

"build" { ignore() } とブロックの中に書くこともできます。

ワイルドカードに名前を付ける

Section titled “ワイルドカードに名前を付ける”

生成先のワイルドカードに名前を付ける capture() は、テンプレートと一緒に使います。layout の検査だけなら capture() は要らず、* のままで構いません。書き方は テンプレートからコード生成 を参照してください。

すべての Role にディレクトリのパスを丸ごと書くのは非効率です。 意味のある単位でパスを定数にしましょう。

val appPackageDir = "src/main/kotlin/com/example"
architecture {
"UseCase" {
layout {
appPackageDir / "useCase" / "*UseCase".ktFile()
}
}
}
  • layout { } は Role のファイルが現れてよい場所 を宣言します。宣言していない場所のファイルは違反になります。
  • anyFile() と ignore() は任意のファイルの配置を許可しますが、これは deny by default の逃げ道 です。注意して使ってください。
  • 生成先のワイルドカードに名前を付ける capture() は、テンプレートと一緒に使います(テンプレートからコード生成)。layout の検査だけなら * のままで構いません。
val appPackageDir = "src/main/kotlin/com/example" // パスは定数に切り出せる
architecture {
"UseCase" {
layout {
appPackageDir / "useCase" / "*UseCase".ktFile() // "/" で繋いで置き場所を宣言する
appPackageDir { // ブロックで囲んでも同じ宣言になる
"legacy" / "*UseCase".ktFile()
}
}
}
"GeneratedFile" {
summary = "ツールが生成するファイル"
layout {
"generated" { anyFile() } // 直下ならどんなファイルでもよい(サブディレクトリは不可)
}
}
"BuildOutput" {
summary = "ビルドの出力"
layout {
"build".ignore() // それより下は検査しない
}
}
}
  • Role … 定義が大きくなってきたときに、ファイルと関数へ切り分ける方法を学びましょう。
  • Konsist との統合 … 置き場所だけでなく、ファイルの中身にも制約をかける方法を学びましょう。
  • 初めてのアーキテクチャ定義 … あなたのプロジェクトに katachi を導入して、実際に宣言を書いてみましょう。