LLMの責務を最小化する設計 — Claude Codeの中身は50代のベテランエンジニアかもしれない件
TL;DR
本記事は、著者自身の振り返りとClaude Codeの分析を通して得た気づきを共有するものです。要点は下記です:
- Deep Learning時代のEnd-to-End学習の成功体験が、汎用LLM時代では逆に足かせになっているのではないか
- 汎用性が高すぎるLLMには、むしろ古典的な設計原則(SOLID、関心の分離)が必要
- Claude Codeの成功には、LLMの責務を最小化し従来の設計原則を忠実に適用していることが寄与している
- LLMの責務を減らすことで開発者の責務は増えるが、これは「本来あるべき姿」への回帰
- パラダイムは変わっても、ソフトウェアエンジニアリングの基礎原則は普遍的である
0. はじめに
こんにちは、sogabe(@sog4be)です。ここ数年、私はいくつかのLLMを活用したアプリケーションを開発してきました。それらを振り返るなかで、うまくいったプロジェクトとそうでないプロジェクトの間に、ある共通のパターンがあることに気づきました。
GPT-4に代表される汎用LLMが登場した当初は、「ここまでLLMが賢いなら、細かい設計は不要なのでは?」と思うこともありました。しかし、実際にはそうではありませんでした。むしろ、品質が安定し、長期的にメンテナンス可能だったプロジェクトは、LLMの責務を意図的に最小化し、古典的なソフトウェアエンジニアリングの原則を丁寧に適用していたものでした。
この気づきをより深く理解するため、現在最も成功しているAIツールの一つであるClaude Codeの設計を分析してみました。すると、そこには50年以上前から語られてきたソフトウェアエンジニアリングの原則が、かなり忠実に適用されていることがわかりました。
この記事は、そうした過去のプロジェクトの振り返りと、Claude Codeの分析を通じて得た洞察を共有するものです。もしかすると間違っている部分もあるかもしれませんが、同じような経験をされている方や、これからLLMアプリケーションを開発される方の参考になれば幸いです。
1. 前提:ソフトウェアエンジニアリングの古典的原則
まず、議論の前提として、ソフトウェアエンジニアリングにおける古典的な設計原則を簡単に振り返りたいと思います。このセクションは既にご存知の方も多いと思うので、その場合は「2. パラダイムシフト」まで読み飛ばしていただいても構いません。ただし、続く「3. Claude Codeの分析」でこれらの原則を多用するため、ここで共通言語を揃えておくことを目的としています。
1.1 SOLID原則
Robert C. Martinが2000年の論文「Design Principles and Design Patterns」で体系化し、後にMichael Feathersが2004年頃に「SOLID」という頭字語を作ったSOLID原則[1]は、オブジェクト指向設計における5つの基本原則です:
-
Single Responsibility Principle(単一責任の原則)
クラスやモジュールは一つの責任だけを持つべきであり、変更理由も一つであるべきです。これにより、コードの理解とメンテナンスが容易になります。 -
Open/Closed Principle(開放閉鎖の原則)
ソフトウェアエンティティは拡張に対して開いており、修正に対して閉じているべきです。既存のコードを変更せずに、新しい機能を追加できる設計を目指します。 -
Liskov Substitution Principle(リスコフの置換原則)
サブタイプはベースタイプと置換可能であるべきです。継承関係において、親クラスを子クラスで置き換えてもプログラムの正しさが保たれるべきです。 -
Interface Segregation Principle(インターフェース分離の原則)
クライアントは使わないインターフェースに依存すべきではありません。大きなインターフェースを小さく分割し、必要なものだけを公開します。 -
Dependency Inversion Principle(依存性逆転の原則)
高レベルモジュールは低レベルモジュールに依存すべきではなく、両者とも抽象に依存すべきです。具象ではなく抽象に依存することで、柔軟性が高まります。
1.2 関心の分離
Edsger W. Dijkstraが1974年の論文で提唱した「Separation of Concerns(関心の分離)」[2]は、ソフトウェアエンジニアリングにおける最も基本的な原則の一つです。彼は次のように述べています:
"It is what I sometimes have called 'the separation of concerns', which, even if not perfectly possible, is yet the only available technique for effective ordering of one's thoughts."
関心の分離とは、複雑な問題を扱う際に、異なる側面を独立して考えることです。プログラムの正確性を考える時は正確性だけに集中し、効率性を考える時は効率性だけに集中する。これらを同時に扱おうとすると、思考が混乱してしまいます。
この原則は、MVCアーキテクチャ、レイヤードアーキテクチャ、マイクロサービスなど、様々な形で現代のソフトウェア開発に受け継がれています。
1.3 なぜこれらが重要だったか
これらの原則が50年以上にわたって語り継がれてきた理由は明確です:
- デバッグ可能性:問題が発生した箇所を特定しやすい
- テスト可能性:独立したユニットごとにテストができる
- 保守性:変更の影響範囲が限定的で、修正が容易
- 認知負荷の軽減:各コンポーネントを独立して理解できる
- チーム開発:明確な責務分担により、並行開発が可能
- 変更への強さ:要件変更に柔軟に対応できる
これらは「当たり前」として共有されてきた知恵であり、ソフトウェアエンジニアリングの基盤を形成しています。
2. パラダイムシフト:Deep Learning時代の成功体験
2.1 Deep Learning革命とEnd-to-End学習
2012年、Alex Krizhevsky、Ilya Sutskever、Geoffrey Hintonによる「ImageNet Classification with Deep Convolutional Neural Networks」[3]が、AlexNetでImageNetチャレンジにおいて圧倒的な性能を達成しました(top-5 error 15.3%、従来手法を10.9ポイント上回る)。この成功は、新しいパラダイムの始まりを告げるものでした:「データとモデルサイズがあれば、多くの問題が解決できる」。
Deep Learning時代の特徴は「End-to-End学習」でした[4]。従来必要だったFeature Engineeringが不要になり、生データから直接タスクを学習できるようになりました。データさえあれば、細かい作り込みをしなくても動く。これは非常に強力なアプローチで、私自身もGPT-4登場以前はこの方針を多用していました。
2.2 汎用LLMの登場と要件定義の必要性
2022年以降、GPT-4やClaude 3.5といった汎用LLMが登場し、データ収集やモデル訓練すら不要になりました。一見、End-to-Endアプローチのさらなる進化に思えました。しかし実際にLLMアプリケーションを開発すると、予想外の困難に直面しました。
ここで気づいたのは、Deep Learning時代とLLM時代では、「要件の伝え方」が根本的に異なるということです。この洞察は、前職の同僚との議論から得たものですが、実際のプロジェクト経験を振り返ると非常に腹落ちするものでした:
【Deep Learning時代】
- データセット自体が要件を暗黙的に表現
- 例:犬の画像1000枚 = 「犬を認識せよ」という要件
- モデルがデータから要件を学習
- → 要件の明示的な言語化は不要
【汎用LLM時代】
- LLMは事前に膨大な知識を持つ
- データセットで要件を伝えることができない
- → 要件を明示的に言語化する必要がある
この「要件の言語化」が、実は設計の必要性につながります。複雑なタスクの要件を言語化するには、それを構造化する必要があります。構造化とは、つまり責務を分離することです。そして責務の分離こそが、設計の本質なのです。
例えば「良いスライドを作る」という要件を言語化しようとすると:
- 目的は何か(企画提案?営業?)
- 読者は誰か(経営層?技術者?)
- 何を伝えるべきか(課題?解決策?)
- どう構成すべきか(論理構成は?)
このように要件を分解して言語化することが、自然と設計につながります。
2.3 競争軸の変化と見落とされる設計原則
この変化は開発における競争軸も変えました。Deep Learning時代はデータ量、モデルサイズ、計算資源の競争でしたが、汎用LLM時代は要件定義、アーキテクチャ設計、使いこなし方の競争です。GPT-4やClaude 3.5は誰でも使えます。差がつくのは「どう使うか」の設計力です。
それでも設計原則が見落とされがちなのは、「細かいことは考えなくていい」というDeep Learning時代の成功体験が染み付いているためではないかと考えています。パラダイムが変わったことに、まだ多くの人が気づいていないのかもしれません。
3. 検証:Claude Codeで見る古典的原則の復活
注:本節で紹介するClaude Codeの機能や設計は、2025年10月時点の情報に基づいています。Claude Codeは活発に開発が進められているため、将来的に機能や仕様が変更される可能性があります。
3.1 なぜClaude Codeを分析するか
私の仮説を検証するため、実際に成功しているプロダクトを分析してみることにしました。選んだのは、Anthropic社が開発したClaude Code[5]です。
Claude Codeを選んだ理由:
- 現時点で最も成功しているAIコーディングツールの一つ
- Anthropic社内でも実際に使われている実用的なツール
- オープンで、設計思想が透けて見える
- 表面的には「LLMに大きな裁量を与えている」ように見える
最後の点が特に重要です。Claude Codeは一見すると、Claudeに自由にコードを書かせているように見えます。しかし詳しく見ていくと、実は非常に厳密に設計されていることがわかりました。
3.2 SOLID原則との対応関係
3.2.1 S: 単一責任の原則 → Plan Mode
Claude Codeの最も特徴的な機能の一つが「Plan Mode」です[6]。これは、LLMの責務を「計画」と「実行」に明確に分離する仕組みです。
Plan Modeの仕組み:
- 読み取り専用モードで、まず計画を立てる
- コードベースを探索し、アーキテクチャを理解する
- 包括的な戦略を策定する
- その後、ユーザーの承認を得てから実行フェーズに移る
これは、単一責任の原則の適用です。Plan ModeのClaudeは「計画を立てる」という一つの責任だけを持ち、「実行する」という責任は別のフェーズに分離されています。
従来のソフトウェア設計で言えば、MVCパターンにおけるControllerとModelの分離に相当します。「何をすべきか決める」ことと「実際にやる」ことを混ぜてはいけないのです。
3.2.2 O + D: 拡張性と依存性逆転 → MCP Protocol
Claude CodeはModel Context Protocol (MCP)という仕組みを採用しています[7]。これは、決定論的な処理を「Tool」として外部化し、LLMはToolという抽象インターフェースを通じてのみアクセスする設計です。
MCPの特徴:
- ファイルIO、Git操作、API呼び出しなどはすべてToolとして実装
- LLMは「どのToolを呼ぶか」を判断するだけ
- 実際の実行はシステム側で厳密に制御
- LLM側のコードを変更せずに、新しいToolを追加できる
これは開放閉鎖の原則と依存性逆転の原則を同時に満たしています。LLMは具体的な実装(ファイルシステムの操作方法など)には依存せず、Tool抽象に依存している。そして、既存のコードを変更せずに新しいToolを追加できる(拡張に開いている)。
従来の設計で言えば、プラグインアーキテクチャやDependency Injectionのパターンに相当します。
3.2.3 I: インターフェース分離の原則 → allowed_tools
Claude Codeにはallowed_tools
という機能があります[8]。これは、タスクごとに使用可能なToolを明示的に制限する仕組みです。
例えば、issueのトリアージを行うワークフローでは:
-
gh label list
(GitHubのラベル一覧取得) -
mcp__github__get_issue
(issue取得) -
mcp__github__update_issue
(issue更新)
など、そのタスクに必要な最小限のToolだけが許可されます。Claudeが任意のコマンドを実行したり、意図しない変更を行うことを防ぎます。
これはインターフェース分離の原則の直接的な適用です。「使わないインターフェースに依存させない」——まさにその通りです。
従来の設計で言えば、Role-based interfacesや最小権限の原則に相当します。
3.3 その他の古典的原則の適用
3.3.1 関心の分離 → Hooksシステム
Claude CodeのHooksシステム[9]は、Dijkstraの「Separation of Concerns」[2:1]を体現しています:
Hooksの役割:
- ビジネスロジック(LLMの判断)
- 制約チェック(Hooks)
- 実行(Tools)
これらは完全に分離されたレイヤーとして実装されています。Hooksは終了コードを通じて処理の継続/停止を決定し、LLMの動作を決定論的に制御します。
重要なのは、制約を「プロンプトでお願いする」のではなく、「システムで強制する」点です。これはAspect-Oriented Programmingの考え方に通じます。
3.3.2 明示は暗示にまさる → CLAUDE.md
Claude Codeプロジェクトには、CLAUDE.md
という特別なファイルを配置できます[6:1]。このファイルは、セッション開始時に自動的にClaudeのコンテキストに読み込まれます。
CLAUDE.mdの目的:
- プロジェクトの前提を明文化
- コーディング規約の明示
- アーキテクチャの説明
- 既知の問題点の記録
これは「暗黙知を排除する」という原則の実践です。LLMに「推測させる」のではなく、必要な情報を明示的に提供する。Configuration as Codeの考え方そのものです。
3.3.3 最小権限の原則 → 権限管理
Claude Codeは、デフォルトでユーザーに実行の許可を求めます[8:1]。特定のコマンドだけを自動実行するには、明示的に許可を設定する必要があります。
これは、セキュリティの基本である「最小権限の原則」をLLMにも適用したものです。IAMやRBACといった従来のアクセス制御の考え方が、LLMアプリケーションにも適用されています。
3.4 気づいたこと
Claude Codeの設計を詳しく見て気づいたのは、「新しい原則」は一つもないということです。
すべて、50年前からソフトウェアエンジニアリングで語られてきたことばかりです。SOLID原則、関心の分離、最小権限——これらの古典的な原則を、LLMというコンポーネントに対して忠実に適用しているのです。
Claude Codeの成功には、LLMを「特別なもの」として扱わず、他のソフトウェアコンポーネントと同じように確立された設計原則を適用していることが大きく寄与していると感じました。
4. 一般化:LLMアプリケーションへの適用
4.1 対応表:従来の原則 → LLM文脈での適用
Claude Codeの分析から、古典的な設計原則がLLMアプリケーションにどう適用できるかが見えてきました:
従来の原則 | LLM文脈での適用 | Claude Codeの実装 |
---|---|---|
単一責任の原則[1:1] | LLMに一度に一つの責務だけを持たせる | Plan/Execute分離 |
インターフェース分離[1:2] | 必要なToolだけを提供する | allowed_tools |
依存性逆転[1:3] | LLMはTool抽象に依存させる | MCP Protocol |
関心の分離[2:2] | 判断/実行/検証を分離する | Hooks System |
最小権限の原則 | タスクごとに権限を制限する | Permission System |
明示は暗示にまさる | コンテキストを明文化する | CLAUDE.md |
4.2 具体例:スライドライティングAI
これらの原則を、もっと具体的な例で考えてみましょう。例えば、「スライドを自動生成するAI」を作る場合を考えます。
原則を無視した設計例
ひとつのLLMがすべてを担当:
- 目的を推測
- 読者を想定
- 構成を考える
- スライドを生成
- デザインを決める
この設計の問題点:
- LLMの責任が巨大すぎる(単一責任原則違反)
- 制約がプロンプトでしか伝えられない(暗黙的)
- 何が問題かわからない(関心が分離されていない)
- 再現性がない
結果として、品質はバラバラで、デバッグも困難となり、ユーザーの意図と逸れて「使えない」と言われるのがオチでしょう。
原則を適用した設計例
この設計の利点:
- 各段階で検証できる(デバッグ可能)
- 問題箇所を特定しやすい
- 段階的に改善できる
- テストが書ける
- チーム開発が可能
4.3 なぜ従来の原則が有効なのか
LLMも「コンポーネント」である
LLMを特別扱いする必要はありません。入力を受け取り、出力を返すモジュールとして扱えば、他のコンポーネントと同じ設計原則が適用できます。
不確実性があるからこそ
Glasmachersらの研究「Limits of End-to-End Learning」[10]が示すように、複雑なシステムのEnd-to-End学習には限界があります。LLMは非決定的であり、だからこそ、設計で制御可能な部分を増やし、不確実な部分を最小化する必要があります。
人間の認知負荷
複雑すぎるシステムは人間には理解できません。責務を分離することで、各コンポーネントを独立して理解できるようになります。これはLLMでも人間でも変わりません。
チーム開発とメンテナンス
明確な責務分担により、テスト可能な単位ができ、変更に強い構造になります。これは長期的なプロジェクトには不可欠です。
5. 考察:人間の責務は増えるという逆説
5.1 ここまで読んで気づくこと
ここまで読んでいただいた方は、あることに気づかれたかもしれません。
LLMの責務を最小化する = 人間の責務が増える
そうです。LLMにやらせることを減らせば減らすほど、人間がやるべきことは明確に増えていくのです。
5.2 開発者が新たに担うべき責務
具体的には、以下のような責務が開発者に求められます:
- アーキテクチャ設計:タスクの分解、責務の切り分け、インターフェースの定義
- Tool開発:決定論的な処理の実装とメンテナンス、抽象化レベルの設計
- 制約定義:Hooks・バリデーションロジック、セキュリティポリシー、権限管理
- コンテキスト管理:ドキュメント整備、知識の明文化、プロジェクト固有ルールの定義
- 品質基準の設定:テスト戦略、メトリクス、レビュープロセスの確立
- プロセス設計:反復・検証の仕組み、フィードバックループ、継続的改善の文化
5.3 これは「後退」なのか?
一見すると、これは技術の「後退」に思えるかもしれません。せっかく強力なLLMが登場したのに、人間がやることが増えるなんて。しかし、私はこれを「本来あるべき姿」への回帰だと考えています。
ソフトウェアエンジニアリングにおいて、単一責任、関心の分離、最小権限、明示的な契約——これらは従来から重要でした。Deep Learning時代に一時的にその重要性が薄れたように見えましたが、LLMの登場によって再びその価値が浮き彫りになってきました。
Robert C. Martinが『Clean Architecture』[11]で述べているように:
"The rules of software architecture are the rules of ordering and assembling the building blocks of programs."
これらのルールは普遍的であり、LLMという新しいビルディングブロックが加わっても変わりません。むしろ、LLMのような強力で汎用的なコンポーネントを扱うからこそ、これらの原則がより重要になるのです。
5.4 LLMは「魔法の杖」ではない
LLMは確かに強力です。しかし、それは設計の責任から私たちを解放してくれるものではありません。むしろ、より良い設計を要求するツールです。
- LLMは道具であり、その道具をどう使うかは人間が決める
- 人間の設計力が試される
- エンジニアリングの基礎がより重要になる
- プロフェッショナルとしての価値が問われる
5.5 ポジティブな側面
この「人間の責務の増加」には、ポジティブな側面もあります:
品質が予測可能になる
適切な設計により、LLMアプリケーションの品質が安定し、予測可能になります。
デバッグが容易になる
責務が明確に分離されているため、問題が発生した箇所を特定しやすくなります。
チーム開発がしやすくなる
明確な責務分担により、複数人での開発が効率化されます。
長期的なメンテナンスが可能になる
変更に強い構造により、長期的なプロジェクトの継続が容易になります。
プロフェッショナルとしての価値が高まる
設計力が差別化要因となり、エンジニアとしての市場価値が向上します。
6. まとめ:温故知新 — ソフトウェアエンジニアリングの普遍性
6.1 この記事の要点
この記事の要点をまとめると以下のとおりです:
-
LLMアプリケーションでも、古典的な設計原則は有効である
SOLID原則や関心の分離といった50年前からの原則は、今も変わらず重要 -
Deep Learning時代の成功体験が、逆に足かせになっている
End-to-End学習の考え方は、汎用LLMでは必ずしも最適とは限らない -
Claude Codeという成功例がそれを証明している
実際に成功しているプロダクトは、古典的原則を忠実に適用していた -
パラダイムシフトを理解する必要がある
汎用性が高すぎるからこそ、再び設計が重要になっている -
人間の責務は増えるが、それは価値ある仕事である
LLMの登場は、逆説的に設計の重要性を再認識させてくれた
6.2 確信していること
私が確信を持って言えることは:
-
ソフトウェアエンジニアリングの基礎は普遍的である
時代が変わっても、良い設計の原則は変わりません。 -
SOLID原則は50年後も有効だろう
これらの原則が解決している問題は、本質的なものだからです。 -
LLMは道具であり、本質は変わらない
新しい技術が登場しても、ソフトウェアエンジニアリングの基本は変わりません。 -
良い設計は時代を超える
今日の良い設計は、明日も良い設計であり続けます。
6.3 確信していないこと
一方で、以下の点については確信を持っていません:
- これが唯一の正解かどうか
- すべての状況で適用可能かどうか
- もっと良いアプローチがあるかもしれない
7. おわりに
もちろん、スピード重視のプロトタイピング時や、使い捨ての小規模スクリプトにおいて、これらの設計原則を厳密に適用する価値は低いでしょう。重要なのは、プロジェクトの性質(長期 vs 短期、チーム vs 個人、本番 vs 実験)に応じて、適切なバランスを見極めることです。本記事で述べた原則は、特に長期的なメンテナンスが必要で、品質の予測可能性が重要なプロジェクトにおいて、価値を発揮すると思います。
特に、Claude CodeやCursorなどのAIコーディングツールが普及した現在、この視点はより重要性を増していると感じています。これらのツールは初期の開発速度を劇的に向上させますが、近年の研究では、設計原則を無視したままAI生成コードが蓄積されると、技術的負債の増加により長期的な開発速度が低下することが報告されています[12][13][14]。AIツールが強力だからこそ、初期の段階から基礎的な設計原則を意識し、秩序を保つことが、持続可能な開発速度を維持する鍵になるかもしれません。
古い知恵に学び、新しい問題に適用する——LLM時代でも、ソフトウェアエンジニアリングの基礎原則は普遍的です。この記事が、LLMアプリケーションの設計に取り組まれている方々の参考になれば幸いです。
-
Martin, R. C. (2000). "Design Principles and Design Patterns." Object Mentor. Retrieved from https://staff.cs.utu.fi/~jounsmed/doos_06/material/DesignPrinciplesAndPatterns.pdf ↩︎ ↩︎ ↩︎ ↩︎
-
Dijkstra, E. W. (1974). "On the role of scientific thought." In Selected Writings on Computing: A Personal Perspective (pp. 60-66). Springer-Verlag, 1982. ↩︎ ↩︎ ↩︎
-
Krizhevsky, A., Sutskever, I., & Hinton, G. E. (2012). "ImageNet Classification with Deep Convolutional Neural Networks." In Advances in Neural Information Processing Systems 25 (NIPS 2012), 1097-1105. ↩︎
-
Glasmachers, T. (2017). "Limits of End-to-End Learning." In Proceedings of Machine Learning Research 77, 1-14. Retrieved from https://proceedings.mlr.press/v77/glasmachers17a/glasmachers17a.pdf ↩︎
-
Anthropic. (2025). "Claude Code Documentation: Overview." Retrieved from https://docs.anthropic.com/en/docs/claude-code/overview ↩︎
-
Anthropic. (2025). "Claude Code Best Practices." Retrieved from https://www.anthropic.com/engineering/claude-code-best-practices ↩︎ ↩︎
-
Anthropic. (2025). "Connect Claude Code to tools via MCP." Retrieved from https://docs.claude.com/en/docs/claude-code/mcp ↩︎
-
Anthropic. (2025). "Claude Code settings." Retrieved from https://docs.claude.com/en/docs/claude-code/settings ↩︎ ↩︎
-
Anthropic. (2025). "Get started with Claude Code hooks." Retrieved from https://docs.claude.com/en/docs/claude-code/hooks-guide ↩︎
-
Glasmachers, T. (2017). "Limits of End-to-End Learning." arXiv preprint arXiv:1704.08305. ↩︎
-
Martin, R. C. (2017). Clean Architecture: A Craftsman's Guide to Software Structure and Design. Prentice Hall. ISBN: 978-0134494166. ↩︎
-
Anderson, E., Parker, G., & Tan, B. (2025). "The Hidden Costs of Coding With Generative AI." MIT Sloan Management Review. https://sloanreview.mit.edu/article/the-hidden-costs-of-coding-with-generative-ai/ ↩︎
-
GitClear (2025). "AI Copilot Code Quality Research 2025." http://gitclear.com/ai_assistant_code_quality_2025_research ↩︎
-
Forsgren, N., et al. (2024). "Accelerate State of DevOps Report (DORA 2024)." Google Cloud. https://cloud.google.com/blog/products/devops-sre/announcing-the-2024-dora-report ↩︎
Discussion