1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AI時代だからこそDesign by Contractと不変条件を学ぶべき理由

1
Posted at

AIがコードを書く時代になりました。

Claude CodeやGitHub Copilotを使えば、CRUD実装やAPI作成は数分で完了します。

しかし最近、AIに実装を任せるほど強く感じることがあります。

「AIはコードは書けるが、正しいコードは人間が定義しなければならない」

ということです。

そして、そのために重要になるのが Design by Contract(契約による設計) と Invariant(不変条件) です。


AIはコードを書ける

例えばAIにこう依頼します。

会員登録APIを実装してください

するとAIは高い精度で実装します。

@PostMapping("/users")
public ResponseEntity<Void> register(
        @RequestBody RegisterUserRequest request) {

    userService.register(request);

    return ResponseEntity.ok().build();
}

しかし、ここでAIには分からないことがあります。

  • メールアドレスは重複可能か
  • 退会済ユーザは再登録可能か
  • 未成年は登録可能か
  • 法人ユーザは対象外か

これらはコードから推測できません。

つまりAIは、

「どう実装するか」

は得意ですが、

「何を守るべきか」

は人間が定義しなければならないのです。


Design by Contractとは

Design by Contract(DbC)は、ソフトウェアを「契約」で設計する考え方です。

代表的な契約は3つあります。

種類 内容
事前条件(Precondition) 呼び出し前に満たす条件
事後条件(Postcondition) 処理後に保証される条件
不変条件(Invariant) 常に成立し続ける条件

例えば銀行振込なら、

事前条件

振込金額 > 0

事後条件

残高が振込金額分減少している

不変条件

口座残高は常に0以上

です。


Invariant(不変条件)が最も重要

DDDでも重要視されるのがInvariantです。

なぜなら、

システムが壊れる原因の多くは不変条件の破壊だからです。

例えば返金システムを考えます。

返金状態は次のように管理されているとします。

public enum RefundStatus {
    WAITING,
    PROCESSING,
    SUCCESS,
    FAILED
}

しかし実際には、

返金成功なのに返金額が0円

という状態は許されません。

つまり本当に守るべきルールは

SUCCESSなら返金額 > 0

です。

これがInvariantです。


Spring Bootでの実装例

よくある実装はDTOバリデーションです。

@NotNull
@Positive
private BigDecimal amount;

もちろん有効です。

しかしこれは入力チェックでしかありません。

本当に重要なのはドメインモデル側です。

public class Refund {

    private final RefundStatus status;
    private final BigDecimal amount;

    public Refund(
            RefundStatus status,
            BigDecimal amount) {

        if (status == RefundStatus.SUCCESS
                && amount.signum() <= 0) {

            throw new IllegalArgumentException(
                    "返金成功時は返金額が必要");
        }

        this.status = status;
        this.amount = amount;
    }
}

これなら、

どのAPIから呼ばれても、

どのバッチから呼ばれても、

Invariantが守られます。


業務システムでよくあるInvariant

実際の業務システムには大量のInvariantがあります。

例えばECサイト。

注文確定後は商品数を変更できない

会員管理。

退会済ユーザはログインできない

決済システム。

返金額 <= 決済額

銀行送金。

ロック中アカウントは送金できない

これらは単なるバリデーションではありません。

業務ルールそのものです。

そしてAIは業務ルールを推測できません。


AI時代ほどDesign by Contractが重要になる

従来は人間がコードを書いていました。

そのため、

実装者自身が暗黙的にルールを理解していました。

しかしAI時代は違います。

実装担当はAIになります。

AIは契約が与えられれば守ります。

逆に契約がなければ勝手に解釈します。

例えばClaude Codeへ依頼するとき、

/**
 * Invariant:
 *
 * - SUCCESS時は返金額が必須
 * - FAILED時は失敗理由が必須
 * - 返金額は決済額を超えてはならない
 */
public class Refund {
}

と書いておけば、

AIはその制約を考慮して実装できます。

つまりDesign by Contractは、

人間同士のためだけでなく、

AIへ設計意図を伝えるための仕様書

にもなります。


まとめ

AIによってコードを書くコストは大幅に下がりました。

しかし、

何を守るべきかを定義する責任は人間に残ります。

そのため今後は、

  • 事前条件(Precondition)
  • 事後条件(Postcondition)
  • 不変条件(Invariant)

を明確に定義できるエンジニアの価値が高まります。

AI時代に必要なのは、

コードを書く力だけではありません。

「システムが守るべき契約を定義する力」

です。

そしてその基礎となるのが、Design by ContractとInvariantなのだと思います。


※本記事は、2026年5月開催の JJUG CCC 2026 Spring で得た学びをもとに整理した内容です。

1
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?