---
type: Reference
title: "アノテーション導入ガイド"
description: "『Living Documentation』第 4 章「Knowledge Augmentation」に基づき、設計判断・意図・根拠をコード上の構造化されたアノテーションとして残す導入手順（本質的な知識の判定、語彙カタログ、命名・コミット規約、ツール連携と検証、アンチパターン、チェックリスト）をまとめた導入ガイド。"
tags: [reference]
status: draft
generated: { by: claude-code/claude-opus-5-5, at: 2026-09-29T00:00:00Z }
---

# アノテーション導入ガイド

## 1. 目的と対象

このガイドは、チームが設計判断・意図・根拠をコード上の**構造化されたアノテーション**として残し、ツールと人の両方が読める状態にするための導入手順をまとめたものです。

- **対象**: Java（Spring Boot）や .NET（C#）でドメイン設計を行う開発チーム
- **出典**: 『Living Documentation』第 4 章「Knowledge Augmentation」
- **基本方針**: コードは「どう作るか」を語るが、「なぜそうしたか」は語らない。欠けている知識をコードの近くに、機械が解析できる形で補う。

補強の手段は 3 系統あります。このガイドは主にアノテーション（内部ドキュメント）を扱い、規約とコミットメッセージにも触れます。

| 手段 | 置き場所 | 向く知識 | 主な弱点 |
| --- | --- | --- | --- |
| アノテーション | コード内 | 役割・性質・レイヤー・根拠 | 付けすぎるとノイズになる |
| 規約（命名・パッケージ） | コード内 | 分類・レイヤー | 根拠や代替案は書きにくい |
| サイドカー/メタデータ DB | コード外 | 元ファイルに触れられない場合 | 名前変更・移動で関係が壊れる |

## 2. 何に注釈を付けるか

**要素そのものの性質（本質的な知識）だけを付け、状況や関係に依存する知識（外在的な知識）は付けない**のが原則です。

判断の問いは 1 つです。「この要素を変更したとき、注釈の更新は最小の作業で済むか」。

| 観点 | 本質的（付ける） | 外在的（付けない） |
| --- | --- | --- |
| 定義 | 要素を消せば一緒に消える知識 | 他の要素や状況との関係で決まる知識 |
| 変更頻度 | 低い | 高い |
| 例 | 値オブジェクトである、不変である、副作用がない | 誰が所有しているか、画面上のどこにあるか |
| 保守コスト | 小さい | 大きい（注釈が常に古くなる） |

### 付けすぎを防ぐ 3 つの方針

1. **デフォルトを活用する**: 大半のクラスに当てはまる性質は注釈せず、例外だけに付ける。全クラスが不変なら、可変クラスにだけ `@Mutable` を付ける。
2. **注釈のコストを意識する**: すべてのクラスに付く注釈はノイズになる。チームの方針を「例外だけ明示」に寄せる。
3. **外在的な知識は別の手段で**: 変わりやすい情報は、コードの注釈ではなく外部ドキュメントや規約側に置く。

## 3. 導入ステップ

小さく始め、チームで語彙を合意してから広げる 5 段階です。

1. **現状を棚卸しする**: 既存コードで、名前やコメントから読み取れる設計上の役割（値オブジェクト、リポジトリ、レイヤーなど）と、決定の理由が失われている箇所を洗い出す。
2. **語彙を決める**: 標準文献（DDD、GoF、Fowler の PoEAA など）から借りる語彙と、自分たちの文脈固有の語彙を分けて一覧にする。最初は 5〜10 個に絞る。
3. **アノテーション用パッケージを作る**: 参照元の書籍やスタイルが分かる名前にする(例: `com.acme.annotation.ddd`、`com.acme.annotation.algebra`)。メタアノテーションで性質を束ねるバンドルも用意する。
4. **1 つのモジュールで試す**: `package-info.java` にレイヤーやスタイルを宣言し、主要なクラスにステレオタイプを付ける。IDE の検索とツールでの検証が動くことを確認する。
5. **運用に組み込む**: コードレビューとコミット規約に組み込み、静的解析で違反を検出する。語彙は使いながら育て、不要になったものは削除する。

どの段階でも、アノテーションは**リファクタリング耐性**を持つよう、対象のコードに直接付けます。クラス名変更や移動に追従するため、後から手作業で直す手間が減ります。

## 4. アノテーション語彙カタログ

語彙は目的別に 4 種類に分けると整理しやすくなります。

| 種類 | 目的 | 例 |
| --- | --- | --- |
| ステレオタイプ | クラスの設計上の役割を示す | `@ValueObject`、`@Entity`、`@DomainService`、`@DomainEvent` |
| 性質 | 望ましい振る舞いを宣言する | `@Immutable`、`@SideEffectFree`、`@IdentityByValue`、`@NotNull` |
| レイヤー・スタイル | パッケージ単位の設計方針を示す | `@Layer(LayerType.INFRASTRUCTURE)`、`@FunctionalFirst` |
| 根拠 | 判断の理由を記録する | `@MyAnnotation(rationale = "...")` |

### 4.1 ステレオタイプ

役割を表す注釈は、Spring の `@Service`・`@Repository` のように、フレームワーク側の意味と一致する場合だけ流用します。一致しない場合は独自の注釈を定義し、必要なら Spring の注釈で**メタ注釈**として束ねます。

```java
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ValueObject {}
```

### 4.2 性質のバンドル

複数の性質を 1 つにまとめると、付ける手間とノイズが減ります。

```java
@Immutable
@SideEffectFree
@IdentityByValue
public @interface ValueObject {}
```

こう宣言しておけば、クラスに `@ValueObject` を付けるだけで、不変・副作用なし・値による同一性の 3 つを宣言したことになります。

### 4.3 レイヤーの宣言

レイヤーは、`package-info.java` にパッケージ単位で 1 回だけ宣言します。

```java
@Layer(LayerType.INFRASTRUCTURE)
package com.example.infrastructure;
```

レイヤーごとに独自のカスタム注釈(`@Layer(id = "repositories")` など)を作る方法もあります。

### 4.4 根拠の記録

判断が行われた箇所に、その理由を注釈で残します。

```java
@MyAnnotation(rationale = "We only know how to do that way")
```

実際には、次の 3 点を含めます。

- **文脈**: 当時の制約や優先度（例: 「1000 人のユーザーで、1 週間だけ持てばよい」）
- **問題・要件**: 何を解決したかったか
- **選んだ理由と却下した代替案**: 他の候補と、採用しなかった理由

### 4.5 .NET での対応

.NET では、属性（Attribute）で同じことができます。アセンブリ単位の宣言は `AssemblyInfo` に書きます。命名は Java 版と揃え、チームで同じ語彙を使います。

```csharp
[AttributeUsage(AttributeTargets.Class)]
public sealed class ValueObjectAttribute : Attribute { }

[assembly: Layer(LayerType.Infrastructure)]
```

### 4.6 アノテーションのパッケージ名

名前が意味を持つよう、参照元をパッケージ名に埋め込みます(例: DDD 由来なら `annotation.ddd`、Gang of Four 由来なら `annotation.gof`)。読む人が、その語彙の出典をたどれるようになります。

## 5. 命名規約とコミット規約

アノテーションが付けにくい場面や、既存コードに手を入れたくない場面では、**規約**が文書の役割を果たします。

### 5.1 命名・パッケージ規約

| 規約 | 例 |
| --- | --- |
| レイヤー別パッケージ | `*.domain.*`、`*.infra.*` |
| 技術的ステレオタイプ別パッケージ | `*.dao.*`、`*.ejb.*`、`*.pojo.*` |
| 別チームの公開規約を採用 | Rails の「テーブル名は `orders`、コントローラは `orders_controller`」 |

- 規約は README などの**外部ドキュメント**に 1 か所でまとめ、新メンバーの参照先にする。
- 別会社が公開している規約を採用すれば、自分で説明する手間が減る。
- `Service` や `DTO` のような接頭辞・接尾辞をすべてのクラスに付けるのは避ける。情報を足さないノイズになる。
- 規約は守られて初めて機能する。JDepend、ArchUnit、自作の解析ツールで検証する。

### 5.2 コミットメッセージ規約

コミットメッセージは、1 行ごとの変更に対する文書です。構造化しておけば、ツールが読めます。Angular 流の形式は次のとおりです。

```text
<type>(<scope>): <subject>

<body>

<footer>
```

| type | 用途 |
| --- | --- |
| `feat` | 新機能 |
| `fix` | バグ修正 |
| `docs` | ドキュメントのみの変更 |
| `style` | 意味を変えない整形（空白、セミコロンなど） |
| `refactor` | 機能追加でも修正でもないコード変更 |
| `perf` | 性能改善 |
| `test` | テストの追加・修正 |
| `chore` | ビルドや補助ツールの変更 |

- **scope**: 影響範囲。チームで一覧を決める(例: `pricing`、`ui`、`trade-feeding`)。
- **破壊的変更**: footer に `BREAKING CHANGE:` から始めて、変更内容と移行方法を書く。
- **Issue 参照**: footer に `Closes #8125` のように書く。

```text
feat(trade-feeding): Support trade feeding for negative-coupon

Some bonds have negative coupon rates, e.g. -0.21 percent.
Change the validation to not reject trades on bonds.

Closes #8125
```

### 5.3 changelog の自動生成

規約に沿ったメッセージは、`git log <last tag>..HEAD --grep feature` のようなコマンドで種別ごとに取り出せ、changelog の素案を生成できます。リリース前に、人が目を通して編集します。

## 6. ツール連携と検証

アノテーションは**機械可読**なので、ツールに任せられる作業が増えます。

| 用途 | 使い方 |
| --- | --- |
| 検索・ナビゲーション | IDE で注釈を検索し、`@ValueObject` が付いたクラスを一覧する |
| 補完・リファクタリング | 注釈はコードの一部なので、リネームや移動に自動で追従する |
| 依存関係の検証 | `@Layer` を読み、レイヤー間の禁止依存を JDepend や ArchUnit で検出する |
| 性質の強制 | `@Immutable` のクラスに可変フィールドがないか、静的解析で確認する |
| 生成ドキュメント | 注釈を走査して、用語集やレイヤー図などの living document を出力する |

### 導入時の注意

- **注釈にコンパイラのチェックが効く形にする**: 文字列より列挙型(例: `LayerType.INFRASTRUCTURE`)を使い、誤記をコンパイル時に検出する。
- **知識を 1 か所に集める**: 関連する注釈と、それを読むツールを同じモジュールに置く。
- **CI で検証する**: 違反をビルドの失敗にすると、規約が形骸化しない。
- **人が読む文書は生成物にする**: 手書きの設計図は古くなる。注釈から生成すれば、コードと同期を保てる。

## 7. アンチパターンと代替手段

### 避けること

| アンチパターン | なぜ問題か | 代わりに |
| --- | --- | --- |
| 感情的な注釈(`@WTF`、`@Facepalm`、`@CantTouchThis`) | 型階層を汚し、理由が伝わらない | 構造化コメントで理由を書く、または根拠付きの注釈にする |
| 標準注釈の流用（JPA など） | 永続化などの技術的関心事で、ドメインの意味が薄まる | 独自の注釈を定義し、必要ならメタ注釈で束ねる |
| すべてのクラスに同じ注釈 | 情報量がゼロでノイズになる | デフォルトを決め、例外にだけ付ける |
| 外在的な知識の注釈 | すぐ古くなり、変更コストが高い | 外部ドキュメントや規約に置く |
| 推測に基づく文書化 | 使われない設計の説明が増える | 作ったものに対して、必要になった時点で書く |

### 注釈が使えない場合

| 手段 | 使う場面 | 注意 |
| --- | --- | --- |
| 構造化コメント（Javadoc タグなど） | 注釈がない言語、注釈を増やしたくない場面 | ツール支援が弱く、リファクタリングで壊れやすい |
| サイドカーファイル | 元ファイルに触れられない（画像や音声など） | 名前変更・移動で関係が切れる |
| メタデータ DB | 多数のファイルを一括管理する | 元ファイルと同期がずれるリスク |

サイドカーファイルとメタデータ DB は最後の手段です。可能な限り、コード内のアノテーションを優先します。

### 命名のヒント

- 注釈が独自の意味を持つなら、標準の語彙（GoF、DDD）を出発点にし、自分たちの語彙を足す。
- 感情や好みなど、注釈で表しにくい微妙な内容は、コメントやコミットメッセージ、ブログなど別の媒体に書く。

## 8. 導入チェックリストと出典

### 導入前

- [ ] 決めたい知識（役割・性質・レイヤー・根拠）を、チームで 3〜5 項目に絞った
- [ ] 各項目が本質的な知識か、外在的な知識かを判定した
- [ ] 標準文献から借りる語彙と、独自の語彙を分けた

### 設計時

- [ ] 注釈用パッケージ名が、参照元（DDD、GoF など）を示している
- [ ] 大半のクラスに当てはまる性質は、デフォルトにして注釈を省いた
- [ ] 感情的・冗長な注釈を定義していない
- [ ] 根拠には、文脈・問題・選択理由・却下した代替案を含めている

### 運用時

- [ ] レイヤーや性質の違反を、CI で検出できる
- [ ] IDE で注釈を検索し、一覧できることを確認した
- [ ] 規約（命名・コミット）を README にまとめた
- [ ] 使われない注釈を定期的に見直し、削除している

### 出典

- 『Living Documentation』第 4 章「Knowledge Augmentation」（pp.95–133）。本ガイドは、この章の内容を導入手順としてまとめ直したもの。コード例は説明用に書き起こしたもの。

### 関連ガイド

- [Living Documentation導入ガイド](LivingDocumentation導入ガイド.md) - 知識の補い方（Knowledge Augmentation）の全体像
- [ダイナミックキュレーション導入ガイド](ダイナミックキュレーション導入ガイド.md) - アノテーションを選択基準にして知識を選び出す
- [ガイドツアー・サイトシーイング導入ガイド](ガイドツアー・サイトシーイング導入ガイド.md) - アノテーションから見どころとツアーを生成する
- 本プロジェクトのコミット規約は `git-commit` スキル、根拠の記録は `creating-adr` スキル（ADR）を使う
