1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

カッペリーニコードとは何か 〜スパゲッティコードとの決定的な違い〜

1
Last updated at Posted at 2026-04-09

本記事は、2026/5/30開催の「JJUG CCC 2026 Spring」の登壇内容に関連した技術記事シリーズです。
AIエージェント(Copilot / Claude Code / Cursor)の普及により、Java開発の前提は大きく変わりました。
本シリーズでは「AI時代における設計の変化」をテーマに、実務視点で整理していきます。

【シリーズ一覧】

  1. AI時代にJava設計はどう変わったのか
  2. カッペリーニコードとは何か
  3. Java17/21は設計をどう変えたか
  4. AIは設計できるのか
  5. AI時代の設計ガードレール

はじめに

GitHub CopilotやClaude Codeを使ったことがある開発者なら、こんな経験があるはずです。

AIが生成したコードを見ると、クラスは小さく、構文は整っていて、一見するとお手本のように読みやすい。

なのに、いざ仕様変更に入ろうとすると、処理がどこにあるのか追えない。何かを変えたとき、影響範囲が把握できない。システムの「背骨」がどこにあるのかわからない。

これは、スパゲッティコードではありません。むしろ正反対の見た目をしています。

私はこの状態を 「カッペリーニコード」 と呼んでいます。

1. 定義

カッペリーニコードとは

クラスは小さく、構文は美しい。しかしシステム構造が見えなくなるコード。

カッペリーニはスパゲッティより細いパスタです。細く、軽く、一本一本はきれいです。しかし大量に絡み合うと、スパゲッティより扱いにくい。

コードも同じです。

単体で見れば美しい小クラスが無数に存在し、全体として何をしているのか把握できなくなる。これがカッペリーニコードの本質です。

2. スパゲッティコードとの決定的な違い

スパゲッティコードとは

長年、ソフトウェア開発者が戦ってきた古典的な敵です。

@Service
public class OrderService {

    public Order createOrder(CreateOrderRequest request) {
        // バリデーション
        if (request.items() == null || request.items().isEmpty()) {
            throw new IllegalArgumentException("items required");
        }

        // 合計金額計算
        BigDecimal total = request.items().stream()
            .map(item -> item.price().multiply(BigDecimal.valueOf(item.quantity())))
            .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 保存
        Order order = new Order(total);
        orderRepository.save(order);

        // メール送信
        mailService.send(order.email(), "注文確認", buildMailBody(order));

        return order;
    }
}

特徴はわかりやすいです。

  • クラスが巨大になる
  • 責務が一箇所に集中する
  • メソッドが長く、可読性が低い
  • 依存関係が絡まり合う

問題が 目に見える のが、スパゲッティコードの特徴でもあります。コードを開いた瞬間に「これはまずい」とわかります。

カッペリーニコードとは

AIが生成したコードはこうなります。

@Service
@RequiredArgsConstructor
public class OrderService {

    private final OrderValidator validator;
    private final OrderCalculator calculator;
    private final OrderRepository repository;
    private final OrderNotifier notifier;

    public Order create(CreateOrderRequest request) {
        validator.validate(request);
        Money total = calculator.calculate(request);
        Order order = new Order(total);
        repository.save(order);
        notifier.notify(order);
        return order;
    }
}

一見すると、理想的な構造です。

  • クラスが小さい
  • 責務が分離されている
  • メソッドが短い
  • 構文もモダン

しかしこれが大量に生成されると、何が起きるか。

OrderService
  └─ OrderValidator
  └─ OrderCalculator
       └─ PriceCalculator
            └─ DiscountCalculator
                 └─ DiscountRuleEvaluator
  └─ OrderRepository
  └─ OrderNotifier
       └─ MailSender
       └─ SlackNotifier

処理を追うために、何クラスも渡り歩かなければなりません。しかもそれぞれのクラスは「小さくて正しい」ので、問題があるとは気づきにくい。

対比表

観点 スパゲッティコード カッペリーニコード
クラスサイズ 巨大 極小
構文 古い・冗長 モダン・整っている
可読性(単体) 悪い 良い
可読性(全体) 悪い 悪い
問題の視認性 すぐわかる 気づきにくい
設計意図 崩壊している 存在しない

スパゲッティコードは「見た目でわかる悪さ」です。カッペリーニコードは「見た目が良いのに動かせない」という、ある意味でより厄介な問題です。

3. 実例:Spring Bootで起きること

Spring Bootプロジェクトでは、この現象が特に発生しやすいです。

DTO の爆発的増加

AIはAPIごとにDTOを丁寧に作ります。

public record UserRequest(String name, String email) {}
public record UserResponse(String id, String name, String email) {}
public record UserUpdateRequest(String name) {}
public record UserSearchRequest(String keyword, int page) {}
public record UserSearchResponse(List<UserSummary> users, int total) {}
public record UserSummary(String id, String name) {}
public record UserDetailResponse(String id, String name, String email, String role) {}

1エンティティに対して7クラス。10エンティティなら70クラス。これが正しいかどうかを判断する軸がないまま、クラス数だけが増えていきます。

Service が薄くなりすぎる

@Service
@RequiredArgsConstructor
public class UserService {

    private final UserCreator creator;

    public User create(CreateUserRequest request) {
        return creator.create(request);  // ただ委譲するだけ
    }
}
@Component
@RequiredArgsConstructor
public class UserCreator {

    private final UserValidator validator;
    private final UserMapper mapper;
    private final UserRepository repository;

    public User create(CreateUserRequest request) {
        validator.validate(request);
        UserEntity entity = mapper.toEntity(request);
        return repository.save(entity);
    }
}

UserService は何もしていません。UserCreator に委譲するためだけに存在しています。呼び出しスタックはこうなります。

Controller
  → UserService        // 委譲するだけ
    → UserCreator      // 本体
      → UserValidator  // バリデーション
      → UserMapper     // 変換
      → UserRepository // 永続化

このうちどれかを変更したとき、影響範囲を即座に把握できますか。

Mapper が乱立する

UserMapper
UserEntityMapper
UserResponseMapper
UserDtoMapper
UserConversionService

どこで何を変換しているのか、追わないとわかりません。しかもどれも単体では「小さくて正しい」クラスです。

ドメインモデルが存在しない

最も深刻な問題がこれです。

AIはフレームワーク中心の構造を優先します。

Controller → Service → Repository

この3層は常に存在しますが、ドメインモデルが存在しない ことが多いです。

結果として、ビジネスロジックがどこに行くかというと。

@Service
public class OrderService {
    // ここにロジックが入りはじめる
}

@Component
public class OrderHelper {
    // あふれてきたロジックがここにも入る
}

@Component
public class OrderUtil {
    // さらにここにも入る
}

HelperUtil の乱立は、ドメインモデル不在のサインです。

4. なぜ発生するのか

AIは「局所最適」が得意だから

AIは与えられたコンテキストの中で最適なコードを生成します。

  • メソッドが長い → 分割する
  • クラスが大きい → 分割する
  • 重複がある → 共通化する

いずれも正しい判断です。しかしAIはシステム全体のアーキテクチャを維持する主体ではありません。

プロンプト単位、ファイル単位で最適化されたコードの集積が、システム全体の構造を壊すことがあります。リファクタリングは得意でも、設計判断は人間が行う必要があります。

「きれいに見える」から問題に気づかない

スパゲッティコードはコードレビューで検出できます。巨大なクラスを見れば「これはまずい」とわかるからです。

カッペリーニコードは検出できません。小さくて整ったクラスを見ても、問題があるとは気づきにくい。問題はクラス単体ではなく、クラス間の関係と全体構造にある からです。

AIの生成サイクルが問題を加速させる

AIを使った開発では、コード生成のスピードが上がります。これは良いことですが、設計を考える時間が相対的に減るという副作用があります。

生成→動作確認→次の生成、というサイクルが繰り返されると、いつの間にかクラス数だけが膨れ上がります。

5. 問題点

変更影響が追えない

処理フローが多数のクラスに分散しているため、仕様変更の影響範囲を特定するのに時間がかかります。

設計意図が読めない

なぜこのクラスが存在するのか、誰がこれを呼ぶのか、このロジックはどこに属すべきなのか。コードを読んでも答えが見つかりません。

テストが書きにくい

クラスが細かく分割されていると、統合テストと単体テストの境界が曖昧になります。何をテストすべきかが不明確になります。

新規参入者が迷子になる

プロジェクトに新しく入った開発者が、処理を追うために10クラス以上を横断しなければならない状況は、スパゲッティコードと同等かそれ以上の参入コストです。

おわりに

AIはコードを書く。人間は構造を守る。

AI時代の設計で重要なのは、コードの美しさではなくシステムの構造です。

カッペリーニコードという概念は、「きれいなコード ≠ 良い設計」 というシンプルな事実を改めて問い直すためのヒントです。

次回は、カッペリーニコードをどう防ぐか、設計の観点から具体的なアプローチを書きます。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?