
AIが生成したコードの品質を定量的に測定・比較してみた
リテールアプリ共創部マッハチームの五反田です。
マッハチームでは小売業界のお客様に向け、新規アプリ開発の立ち上げを専門に行っています。
新規開発の立ち上げでは、短期間で高品質なアプリケーションを開発することが求められます。
マッハチームのメンバーで「品質」をテーマに知見を共有するブログの連載を始めました。
今回は私から、第4弾としてAIが生成したコードの品質を定量的に測定・比較してみた内容をご紹介します。
メンバーによる過去の投稿もぜひ読んでみてください!
はじめに
現在生産性をあげるため、CursorやClaude Codeなどを利用して開発を進めています。
ソフトウェアアーキテクチャ手法(以下、アーキテクチャと記載)の有無が品質に影響するのかを実際にTODOアプリのAPIを作成し、定量的に比較してみます。
結論
TODOアプリのAPIという小さなアプリケーションであり、あくまで数値上の話とはなりますが、
今回の検証では、TODOアプリのAPIという小規模なアプリケーションにおいて、
アーキテクチャをコンテキストに含めた方が可読性・保守性ともに高い傾向が見られました。
| メトリクス | アーキテクチャあり | アーキテクチャなし |
|---|---|---|
| コード行数(平均) | 29.46 | 39.50 |
| サイクロマチック複雑度(平均) | 2.39 | 4.73 |
| サイクロマチック複雑度(最大) | 9 | 22 |
| 保守容易性インデックス(平均) | 133.49 | 125.45 |
検証条件
比較のため以下の内容で実施し、プロンプト以外の条件を統制することで、定量的な比較を行うように検証しました。
- CLAUDE.mdファイルを共通化
- アーキテクチャに関する情報を含めないようにCLAUDE.mdファイルを作成
- 初期のプロンプトの基本部分を同じとする
- TODOアプリとして動作しない場合は、動作するまで修正を実行
- 比較は定量的に実施するため、ツールを使用し比較を実施
使用したCLAUDE.md
# アプリのバックエンド プロジェクト概要
## 技術スタック
- Runtime: Node.js + TypeScript
- Framework: Hono
- Validation: Zod
- Database: SQLite
- ORM: Prisma(マイグレーション) + Kysely(クエリビルダー)
- Monorepo: pnpm workspaces
## コーディング規約
### 命名規則
- ファイル名: kebab-case
- 型/インターフェース: PascalCase
- 関数/変数: camelCase
- 定数: UPPER_SNAKE_CASE
### TypeScript
- `any`禁止、`unknown`を使用
- 明示的な戻り値の型定義を推奨
- Branded Types で型安全性を確保
- `as`によるキャストは値オブジェクトのファクトリ関数内のみ許可
### テスト
- ユニットテスト: Vitest
- テストファイル: `*.test.ts`
- モック: `vi.mock()`を使用
## 開発コマンド
```bash
pnpm install # 依存関係インストール
pnpm dev # 開発サーバー起動
pnpm build # ビルド
pnpm test # テスト実行
pnpm lint # リント
pnpm db:migrate # DBマイグレーション
pnpm db:generate # Prismaクライアント生成
```
プロンプトの差分
今回は1文だけ足して、アーキテクチャの内容をコンテキストに含めて、アーキテクチャありとなしを実装するようにします。
下記に仕様書を記載します。
全てのAPIを作成してください。
+ドメイン駆動設計でかつDIPを用いたレイヤードアーキテクチャを基本のアーキテクチャとして作成をしてください。
# TODOアプリ バックエンドAPI仕様書
## 概要
マルチユーザー対応のTODOアプリケーションのバックエンドAPI
---
## データモデル
### User
| フィールド | 型 | 必須 | 説明 |
|-----------|------|:----:|------|
| id | string (UUID) | ✓ | 一意識別子 |
| email | string | ✓ | メールアドレス(ログインID) |
| password | string | ✓ | ハッシュ化パスワード |
| name | string | ✓ | 表示名 |
| createdAt | datetime | ✓ | 作成日時 |
| updatedAt | datetime | ✓ | 更新日時 |
### Todo
| フィールド | 型 | 必須 | 説明 |
|-----------|------|:----:|------|
| id | string (UUID) | ✓ | 一意識別子 |
| userId | string (UUID) | ✓ | 所有ユーザーID |
| title | string | ✓ | タイトル(最大100文字) |
| description | string | | 説明(最大1000文字) |
| dueDate | datetime | | 期限 |
| priority | enum | ✓ | 優先度: `low` / `medium` / `high` |
| category | string | | カテゴリ(最大50文字) |
| completed | boolean | ✓ | 完了状態(デフォルト: false) |
| createdAt | datetime | ✓ | 作成日時 |
| updatedAt | datetime | ✓ | 更新日時 |
---
## 認証
Basic認証を使用。`Authorization: Basic <Base64(email:password)>` ヘッダーで送信する。
---
## APIエンドポイント
### ユーザーAPI
| メソッド | パス | 説明 |
|---------|------|------|
| POST | /api/users | ユーザー登録 |
### TODO API(要認証)
| メソッド | パス | 説明 |
|---------|------|------|
| GET | /api/todos | TODO一覧取得 |
| GET | /api/todos/:id | TODO詳細取得 |
| POST | /api/todos | TODO作成 |
| PUT | /api/todos/:id | TODO更新 |
| DELETE | /api/todos/:id | TODO削除 |
---
## エラーレスポンス
| ステータスコード | 説明 |
|-----------------|------|
| 400 | バリデーションエラー |
| 401 | 認証エラー |
| 403 | 権限エラー |
| 404 | リソースが存在しない |
| 409 | 競合(メールアドレス重複など) |
| 500 | サーバーエラー |
評価指標と測定ツール
1ファイルあたりのコード行数
1ファイルあたりのコード行数が高いと可読性が悪くなる傾向にあるため、比較を実施します。
使用ツール: cloc
サイクロマチック複雑度(Cyclomatic Complexity)
コードの複雑性(コード分岐の多さ)を比較し、それぞれのコードの保守性を比較します。
使用ツール: typhonjs-escomplex
保守容易性インデックス(Maintainability Index)
保守容易性インデックスの値を比較し、保守性の高さを比較します。
計算式:
Maintainability Index = MAX(0,(171 - 5.2 * ln(Halstead Volume) - 0.23 * (Cyclomatic Complexity) - 16.2 * ln(Lines of Code))*100 / 171)
| インデックス値 | 色 | 意味 |
|---|---|---|
| 0-9 | 🔴 赤 | コードの保守性が低い |
| 10-19 | 🟡 黄色 | コードの中程度の保守容易性 |
| 20-100 | 🟢 緑 | コードの保守性が良好 |
測定結果
| メトリクス | アーキテクチャあり | アーキテクチャなし |
|---|---|---|
| コード行数(平均) | 29.46 | 39.50 |
| サイクロマチック複雑度(平均) | 2.39 | 4.73 |
| サイクロマチック複雑度(最大) | 9 | 22 |
| 保守容易性インデックス(平均) | 133.49 | 125.45 |
- コード行数
アーキテクチャありの方が1ファイルあたりのコード行数が少なく、やや優位 - 循環的複雑度(平均)
アーキテクチャありの方がサイクロマチック複雑度が低くやや優位 - 循環的複雑度(最大)
アーキテクチャなしの方が保守性に欠けているため、アーキテクチャありの方が優位 - 保守容易性インデックス
両方とも高い保守容易性インデックスだが、アーキテクチャありがやや優位
また、今回の検証では、生成AIがファイルを作成する際に以下の傾向が見られました。
アーキテクチャがコンテキストに記載されている場合、
複数ファイルに分けて記載しようとする。
アーキテクチャがコンテキストに記載されていない場合、
1ファイルにまとめて記載しようとする。
まとめ
今回の検証結果から、少なくともアーキテクチャ設計に関する知識を持つことで、AIとのやりとりがより効果的になることが期待できそうです。
もちろん、AIとやりとりをする上で、アーキテクチャの内容を聞かれる可能性はありますが、
アーキテクチャという認識がない状態で、AIとのやりとりで情報が出てこなかった場合、
今回の結果のようなコーディングをしてしまう可能性があるため、人間側で認識しておく必要がありそうです。
エンジニア募集のお知らせ
リテールアプリ共創部マッハチームではエンジニアを大募集しています!
マッハチームでは 0→1 の新規案件の立ち上げを専門に、AI駆動で高速にプロダクトを開発しています。
AI駆動開発がしたい方、モダン技術を用いてフロントエンドもサーバーサイドもインフラもTypeScriptでフルスタックに開発したい方、プリセール・顧客折衝も要件定義も開発も全部やりたい方は、是非以下のブログも読んでみてください。
お気軽にカジュアル面談もお待ちしています!









