本記事は、2026/5/30開催の「JJUG CCC 2026 Spring」の登壇内容に関連した技術記事シリーズです。
AIエージェント(Copilot / Claude Code / Cursor)の普及により、Java開発の前提は大きく変わりました。
本シリーズでは「AI時代における設計の変化」をテーマに、実務視点で整理していきます。
【シリーズ一覧】
- AI時代にJava設計はどう変わったのか
- カッペリーニコードとは何か
- Java17/21は設計をどう変えたか
- AIは設計できるのか? ~AIコーディングツール時代に見えた限界と誤解~
- AI時代の設計ガードレール
はじめに
Claude Code、Cursor Agent、GitHub Copilot Workspace。
2026年現在、AIエージェントはコードを書くだけでなく、アーキテクチャ図・API設計・ER図まで生成できるようになった。
「AIが設計もできるなら、エンジニアは何をすればいいのか」という問いが現場で出始めている。
この記事では AIの能力を過小評価せず正確に整理した上で、それでも設計が人間の責務である理由を断定する。
前提:「設計」を定義する
議論の前に「設計」を明確にしておく。
本記事での「設計」とは以下の3要素を指す。
| 要素 | 定義 | 例 |
|---|---|---|
| 構造 | コンポーネントの責務分割と依存関係 | レイヤー構成・パッケージ設計 |
| 責務 | どこが何を知るべきか | ServiceがRepositoryを知る、その逆は知らない |
| 制約 | 変えてはいけないルール | 循環参照の禁止・ドメインの独立性 |
コードを書くことは設計ではない。構造・責務・制約を決めることが設計である。
1. AIでできること
まず正直に整理する。AIは非常に強力だ。
1-1. 既知パターンの高精度再現
Spring Bootアプリの典型構造はAIが正確に生成する。
@RestController
@RequiredArgsConstructor
public class OrderController {
private final OrderService orderService;
@GetMapping("/orders/{id}")
public OrderResponse getOrder(@PathVariable Long id) {
return orderService.getOrder(id);
}
}
Controller → Service → Repository のレイヤー構造は、指示なしでも自然に再現される。
これは学習データに大量の実例があるためだ。
1-2. リファクタリングと構文最適化
既存コードの改善もAIの強みだ。
// Before
public class UserDto {
private String name;
private String email;
// getter/setter...
}
// After(AI生成)
public record UserDto(String name, String email) {}
メソッド分割・重複除去・Java 21構文への置き換えは、AIによって大きく効率化されている。
1-3. テスト生成
正常系・境界値・例外ケースのテストコードをAIは瞬時に生成する。
@Test
void 存在しないユーザーを取得するとNotFoundExceptionが発生する() {
when(userRepository.findById(999L)).thenReturn(Optional.empty());
assertThrows(UserNotFoundException.class, () -> userService.getUser(999L));
}
テスト観点の列挙という意味でも、AIはかなり有用だ。
1-4. 設計案の生成
ここが重要な点だ。最新のAIは設計案そのものも生成できる。
- アーキテクチャ構成図
- マイクロサービスの分割案
- ER図
- API設計(OpenAPI形式)
たとえば「ECサイトのドメイン設計を提案して」と聞けば、Order・Product・User・Inventory の境界を整理した設計案が返ってくる。
AIは設計を生成できる。これは事実だ。
ただし、ここで重要な問いが生まれる。
生成された設計を、誰が採用するのか。
2. AIでできないこと
AIが設計を「生成」できても、「担う」ことはできない。その理由を整理する。
2-1. 局所最適と全体最適の違い
AIエージェントは現在のコンテキストで最適な答えを出す。これが問題だ。
たとえば以下のような状況を考える。
要求:「注文処理にメール通知を追加して」
AIはServiceクラスに emailService.send() を追加する。局所的には正しい。
しかし設計観点では問題がある。
// AIが生成するコード(局所最適)
@Service
public class OrderService {
private final OrderRepository orderRepository;
private final EmailService emailService; // ← 追加された依存
public void placeOrder(OrderRequest request) {
Order order = orderRepository.save(request.toEntity());
emailService.sendOrderConfirmation(order); // ← 追加された処理
}
}
全体最適の観点では何が問題か。
-
OrderServiceがメール送信の責務を持つことで、責務が混在する - メール通知をイベント駆動にしたい場合、OrderServiceの修正が必要になる
- テスト時にEmailServiceのモックが必須になり、テストの複雑度が上がる
正しい設計はドメインイベントを発行することだ。
// 設計を意識したコード(全体最適)
@Service
public class OrderService {
private final OrderRepository orderRepository;
private final ApplicationEventPublisher eventPublisher;
public void placeOrder(OrderRequest request) {
Order order = orderRepository.save(request.toEntity());
eventPublisher.publishEvent(new OrderPlacedEvent(order.getId()));
}
}
@Component
public class OrderNotificationHandler {
@EventListener
public void onOrderPlaced(OrderPlacedEvent event) {
emailService.sendOrderConfirmation(event.orderId());
}
}
AIは「追加」という指示に従い局所最適を実行する。全体の責務配置を見て「イベントにすべき」という判断はしない。
2-2. 境界定義は文脈依存
AIが設計案を生成できても、正しい境界は組織・チーム・ビジネスに依存する。
たとえば「在庫管理と注文管理を分割すべきか」という問いに対して、AIは一般的な回答を返す。
しかし実際の判断は以下に依存する。
- チームが2人か20人か
- 将来的にマイクロサービス化するか
- DBは共有か分離か
- デプロイ頻度はどの程度か
これらの文脈をAIは持っていない。AIが提案する境界は常に「一般論」だ。
2-3. 制約の設定と維持
設計には「やってはいけないこと」を決める側面がある。
-
infrastructureパッケージからdomainパッケージへの直接依存を禁止する -
@Transactionalを Controller に書かない - ドメインオブジェクトにSpringアノテーションを持ち込まない
AIはこれらの制約を指示されれば守る。しかし制約そのものを設計するのは人間の仕事だ。
Claude CodeやCursorのCustom Instructions(.cursorrules / CLAUDE.md)に制約を書けば、AIはそれを守るエンジンとして機能する。
# CLAUDE.md(設計制約の例)
## レイヤールール
- Controller は Service のみ呼ぶ。Repository を直接呼ばない。
- Service はドメインロジックを持つ。HTTPの概念を知らない。
- ドメインクラスに Spring アノテーションを付けない。
## 依存ルール
- domain パッケージは infrastructure パッケージに依存しない。
- 循環参照を絶対に作らない。
制約を書くのは人間。守らせるのがAI。 この役割分担が正しい使い方だ。
3. なぜ設計は難しいのか
3-1. 設計は「意思決定」であり「責任」だ
設計の本質は技術的な判断だけではない。
| 判断の種類 | 具体例 |
|---|---|
| 技術判断 | イベント駆動にするかトランザクション内で完結させるか |
| ビジネス判断 | 整合性とパフォーマンスどちらを優先するか |
| 運用判断 | 障害時のリカバリをどう設計するか |
| 将来予測 | 1年後の機能追加を見越した抽象化をどこまでするか |
これらの判断には責任主体が必要だ。
AIは選択肢を提示できる。しかし選択の結果に責任を持つのは人間だ。
3-2. AI生成コードが引き起こす「設計の侵食」
AIエージェントを使い続けると、気づかないうちに設計が壊れていく。
典型的な侵食パターンを示す。
Step 1:最初は正しい構造
OrderService → OrderRepository
Step 2:AIが機能追加を繰り返す
OrderService → OrderRepository
→ UserRepository ← 追加
→ ProductRepository ← 追加
→ EmailService ← 追加
→ PaymentService ← 追加
Step 3:気づいたときには責務が爆発している
各追加の判断は局所的に正しかった。しかし全体を見ると OrderService が「なんでも知っているクラス」になっている。
これがカッペリーニコードの発生メカニズムだ(詳細は第2回記事を参照)。
3-3. 設計のレビューはコードのレビューより難しい
コードのレビューはdiffを見ればよい。
設計のレビューは変更の文脈・将来・全体構造を見る必要がある。
- この変更はドメイン境界を侵食していないか
- 責務が正しく配置されているか
- 後で変更しにくい構造になっていないか
AIはdiffの生成は得意だ。しかし上記の問いに答えるのは人間しかいない。
4. 結論:AIは設計の「生成」はできるが「担う」ことはできない
整理する。
| 能力 | AIにできるか |
|---|---|
| コード生成 | ✅ できる |
| リファクタリング | ✅ できる |
| テスト生成 | ✅ できる |
| 設計案の生成 | ✅ できる |
| 局所最適の実行 | ✅ できる |
| 全体最適の判断 | ❌ できない |
| 境界定義(文脈込み) | ❌ できない |
| 制約の設計 | ❌ できない |
| 設計の責任を持つ | ❌ できない |
AIは強力な設計補助ツールだ。しかし設計の責任主体ではない。
AI時代の開発において、エンジニアに求められる能力は変わった。
- コードを書く速度 → AIが担う
- テストを書く量 → AIが担う
- 構造を設計する判断 → 人間が担う
- 制約を定義する責任 → 人間が担う
- 全体最適を維持する意思決定 → 人間が担う
AIが「コードを書く力」を代替した時代に、人間が持つべきは「構造を設計する力」だ。
次回の第5回では、この設計責任を実務で担うための設計ガードレールを具体的に示す。
シリーズ一覧
- AI時代にJava設計はどう変わったのか
- カッペリーニコードとは何か
- Java17/21は設計をどう変えたか
- AIは設計できるのか? ~AIコーディングツール時代に見えた限界と誤解~
- AI時代の設計ガードレール