基本的な API
katachi の主要な API を紹介します。 ここに挙げる API を覚えれば、katachi の基本的な使い方を理解できるはずです。
1. architecture { }
Section titled “1. architecture { }”architecture { } はプロジェクト全体のアーキテクチャを定義するエントリーポイントです。
このブロックの中に、プロジェクトにあるファイルの Role を書きます。
architecture { "UseCase" { /* ... */ } "RepositoryInterface" { /* ... */ }}// このプロジェクトには `UseCase` と `RepositoryInterface` という2つの Role があるアーキテクチャを構成する要素 (Role) は、後のセクションで詳しく説明します。
2. アーキテクチャをテストする assert()
Section titled “2. アーキテクチャをテストする assert()”architecture { } で定義したアーキテクチャをテストする関数が assert() です。
val projectArchitecture = architecture { "UseCase" { /* ... */ } "RepositoryInterface" { /* ... */ }}
@Testfun `アーキテクチャに沿ったファイル配置になっている`() { projectArchitecture.assert()}3. Role を定義する "名前" { }
Section titled “3. Role を定義する "名前" { }”"名前" { } はプロジェクトの中に登場するファイルの役割 (Role) を定義します。
architecture { "UseCase" { /* ... */ }
"RepositoryInterface" { /* ... */ }}architecture { } ブロックの中に "名前" { } を書くと、プロジェクトに登場するファイルの Role を定義できます。
Role の例
Section titled “Role の例”よく知られたアーキテクチャを採用しているなら、Role はたとえば次のようになるでしょう。
| アーキテクチャ | Role |
|---|---|
| MVC | Controller |
View |
|
Model |
|
| MVVM | View |
ViewModel |
|
| Clean architecture | Service |
UseCase |
|
Entity |
|
RepositoryInterface, RepositoryImplementation |
Deny by default
Section titled “Deny by default”katachi では、宣言した Role のファイルしかプロジェクトに存在を許されません。
つまり katachi を導入するときは、プロジェクトの規約に合った Role を列挙する必要があります。
関連ドキュメント
Section titled “関連ドキュメント”Role については Role 定義の詳細 も参照してください。
4. Role をグルーピングする "...".group { }
Section titled “4. Role をグルーピングする "...".group { }”"名前".group { } は Role をまとめるためのブロックです。
例えば Clean architecture では、UseCase と RepositoryInterface は 同じドメインレイヤーの Role です。
architecture { "domain".group { "UseCase" { /* ... */ } "RepositoryInterface" { /* ... */ } }}Role のグループをドメインレイヤーとして DSL で表すと、Role 同士の関係や階層構造が明確になります。分かりやすいアーキテクチャ定義を作るには、分かりやすい粒度で Role をグループ化することが大切です。
関連ドキュメント
Section titled “関連ドキュメント”Role のグループについては Role 定義の詳細 も参照してください。
5. ファイルが存在して良い位置を定義する layout { }
Section titled “5. ファイルが存在して良い位置を定義する layout { }”"..." { } で Role を定義しただけでは、その Role のファイルをどこに置いてよいかは決まりません。
layout { } は Role に対応するファイルをどこに置けるかを定義するためのブロックです。
architecture { "UseCase" { layout { "src/main/kotlin/com/example/useCase" / "*UseCase".ktFile() } }}
// UseCase は `src/main/kotlin/com/example/useCase/*UseCase.kt` に置くことができるどのように機能するか
Section titled “どのように機能するか”Deny by default の原則により、layout { } で宣言していない場所にはファイルを置けません。
たとえば AI Agent が、新しい UseCase ファイルを src/main/kotlin/com/example/GetItemUseCase.kt に置こうとしたとします (本来は useCase パッケージの中に置くべきです)。
assert() が呼び出された時点で、katachi はこのパスに一致する Role が無いことを検知し、テストが失敗します。
ディレクトリsrc/main/kotlin/com/example/
- GetItemUseCase.kt ❌
layout { }で宣言していない場所 ディレクトリuseCase/
- GetUserUseCase.kt ⭐️ 宣言どおりの場所
- GetItemUseCase.kt ❌
関連ドキュメント
Section titled “関連ドキュメント”layout { } については Layout 定義の詳細 も参照してください。
6. ファイル内の制約を定義する "...".konsist { }
Section titled “6. ファイル内の制約を定義する "...".konsist { }”Role を定義したファイルには、Konsist で制約をかけられます。
architecture { "UseCase" { layout { "src/main/kotlin/com/example/useCase" / "*UseCase".ktFile() }
"invoke 関数を1つだけ持つこと".konsist { classes().must { it.functions().map { f -> f.name } == listOf("invoke") } } }}制約の対象は layout { } で指定したファイルで、制約そのものは Konsist の API で書きます。
制約を検査するには、テストで assert() の代わりに assert(FileConstraintCheck()) を呼びます。assert() だけでは制約が評価されず、[UncheckedFileConstraint] としてテストが落ちます。
関連ドキュメント
Section titled “関連ドキュメント”"...".konsist { } については Konsist 連携ガイド も参照してください。
| API | 何をするか | 例 |
|---|---|---|
| プロジェクト全体のアーキテクチャを定義する、エントリーポイントの関数です。 |
|
| 定義どおりにファイルが置かれているかを検査します。テストから呼ぶ1行で、これが無いと何も起きません。 |
|
| プロジェクトの中に登場するファイルの役割 (Role) を定義します。 |
|
| Role をまとめて階層を作ります。使うかどうかは任意で、使わなくても Role は書けます。 |
|
| その Role のファイルをどこに置いてよいかを定義します。 |
|
| その Role のファイルの中身に制約をかけます。別モジュール |
|
次のステップ
Section titled “次のステップ”- 初めてのアーキテクチャ定義 … あなたのプロジェクトに katachi を導入して、この6つを実際に書いてみましょう。
- Role … Role に説明を書く方法と、定義がディレクトリ構造のコピーにならないようにする考え方を学びましょう。
- Layout … 置き場所の書き分けと、
anyFile()/ignore()という deny by default の逃げ道の使いどころを学びましょう。