クリーンアーキテクチャについてClaudeに解説してもらう

技術的備忘録

「プログラミング設計開発技法のリンクリスト」へ戻る

いつもは「吹き出し」で質問と回答を記述していますが、今回はClaudeの出力する図を簡単にブログに記述するため、吹き出しは使いません。 「吹き出し」はClaudeが複雑なフォーマットを出力したとき、吹き出しに載せ替えるのがかなり面倒で、以前から少し困っていた部分です。 今回のようにHxタグで「問」と「回答」を区別した方が見やすいかも知れないとも、思っています。

まだ、いろいろ試行錯誤している最中なので、また別の書き方を試すかも知れません。 ご了承ください。 なお、この記事も自分用の備忘録としてブログに掲載します。特に主張したいことはありません。

質問1

クリーンアーキテクチャについて、分かりやすく解説してください。 解説にコンピュータ言語が必要なら C# を使用してくれると助かります。

Claude回答

クリーンアーキテクチャについて、実践的な例を交えながら説明させていただきます。

 

クリーンアーキテクチャの主な目的は、以下の4つです:

  1. フレームワークに依存しない

  2. テスト可能

  3. UIに依存しない

  4. データベースに依存しない

これを実現するために、アプリケーションを以下の4つの層に分けます:

  • Entities (エンティティ層):ビジネスロジックの中核となるオブジェクト

  • Use Cases (ユースケース層):アプリケーション固有のビジネスルール

  • Interface Adapters (インターフェースアダプター層):外部とのやり取りを変換する層

  • Frameworks & Drivers (フレームワーク層):データベースやWeb APIなどの外部要素

では、具体的な実装例を見ていきましょう。ここでは簡単なユーザー管理システムを例に説明します。

この実装例の特徴を説明します:

  1. 依存関係の方向

    • 内側の層(Entities, Use Cases)は外側の層を知りません

    • 依存関係は常に内側に向かいます

  2. 依存性の注入

    • インターフェース(IUserRepository)を使用して、具体的な実装から抽象化しています

    • これにより、データベースの実装を変更しても、ビジネスロジックに影響を与えません

  3. 境界の明確化

    • 各層は明確に分かれており、それぞれの責務が明確です

    • DTOを使用してデータの受け渡しを行い、層間の結合を緩めています

この設計の利点:

  • テストが容易(モックオブジェクトを使用可能)

  • 機能の追加や変更が容易

  • フレームワークやデータベースの変更が容易

  • コードの見通しが良く、保守性が高い

実際の開発では、プロジェクトの規模や要件に応じて、この構造をカスタマイズすることができます。

ご質問やより詳しく知りたい部分がありましたら、お気軽にお申し付けください。

質問2

4つの「層」は、TCP/IPやビルの階層構造ではなく、円形の内側から皮で包まれるように、同心円状の多重円形構造で表されるのですか。 もし、そうならなぜ階層構造ではなく円形構造なのでしょぅか。

Claude回答

はい、その通りです。クリーンアーキテクチャは、通常「クリーンアーキテクチャの同心円」として図示されます。これには重要な理由があります。

 

Entities
Use Cases
Interface Adapters
Frameworks & Drivers
依存
依存
依存
Enterprise Business Rules
Application Business Rules
Controllers, Presenters, Gateways
Web, UI, DB, Devices, etc

円形構造が採用されている理由は以下の通りです:

  1. 依存関係の方向性の視覚化

    • 依存関係が「内側に向かう」という重要な原則を直感的に表現できます

    • 外側の層は内側の層に依存できますが、その逆は許されません

    • TCP/IPのような階層構造では、上下の層同士が相互に依存する可能性があります

  2. 保護レベルの表現

    • 最も重要なビジネスルール(Entities)が中心にあり、外部の変更から「保護」されているイメージを表現できます

    • まるで玉ねぎの層のように、外側の層が内側の層を保護する構造を視覚的に示せます

  3. 柔軟性と安定性の関係

    • 中心に近いほど安定していて変更が少なく、外側に行くほど柔軟で変更が多いという性質を表現できます

    • 例えば、最も外側のUIやデータベースは頻繁に変更される可能性がありますが、中心のビジネスルールは比較的安定しています

  4. 独立性の強調

    • 各層が完全な円として描かれることで、それぞれの層が独立して存在できることを示します

    • 内側の層は外側の層の存在を知らなくても機能できます

  5. プラグイン・アーキテクチャの実現

    • 外側の層は「プラグイン」として扱うことができ、必要に応じて差し替え可能であることを示します

    • 例えば、データベースをSQLServerからMongoDBに変更しても、内側の層には影響を与えません

これは階層構造との重要な違いです:

  • 階層構造:上下の層が相互に依存する可能性がある

  • 円形構造:依存関係が常に内側にのみ向かう

この円形構造により、ソフトウェアの:

  • 保守性

  • テスト容易性

  • 変更への耐性

  • スケーラビリティ

が向上します。各層が明確に分離され、依存関係が一方向に制限されることで、システム全体の堅牢性が高まるのです。

質問3

依存関係は、Entities (エンティティ層)のような「人間の業務」が中心で、Interface Adapters や Frameworks & Drivers のような、デバイス系の処理が変更可能な外部の存在と考えるのですか。 従来のソフトウェアだとデバイスの方に、業務処理が依存する考え方になっていたと思うのですが、これと逆の考え方をするということでしょうか。 これは設計思想の革新なのでしょうか。

Claude回答

はい、その理解が正確です。これは実際、ソフトウェア設計における重要なパラダイムシフトといえます。

従来のアプローチと比較してみましょう:

従来のアプローチ(デバイス中心):

  • データベースの構造が先にあり、それに業務ロジックを合わせる

  • フレームワークの制約に業務ロジックを適応させる

  • UIの要件がビジネスロジックの実装を左右する

データベース/フレームワーク
アプリケーション層
ビジネスロジック

クリーンアーキテクチャ(ビジネス中心):

  • ビジネスルール(業務の本質)が中心

  • 技術的な実装の詳細は外側に位置する「実装の詳細」として扱う

  • データベースやUIは「取り替え可能なプラグイン」として扱う

技術的な詳細
ビジネスの本質
Interface Adapters
※データ変換層
Frameworks & Drivers
※DB/UI/デバイス
Use Cases
※業務フロー
Entities
※業務モデル・ルール

この設計思想の革新的な点は:

  1. 本質と実装の分離

    • ビジネスロジック(本質)とテクニカルな実装(詳細)を明確に分離

    • これにより、ビジネスロジックの純粋性が保たれる

  2. 技術的負債の軽減

    • フレームワークやデータベースの変更が、核となるビジネスロジックに影響を与えない

    • 新技術への移行がスムーズに

  3. ドメイン駆動設計との親和性

  4. テスタビリティの向上

これは確かに革新的な考え方の転換です:

  • 従来: システムの技術的制約に業務を合わせる

  • クリーン: 業務の本質を中心に据え、技術はそれに奉仕する

この変化の背景には:

  1. ソフトウェアの長期保守の重要性の認識

  2. 技術の急速な変化への対応の必要性

  3. ビジネスロジックの価値の再認識

があります。

特に重要なのは、この設計により:

  • ビジネスロジックが技術的な実装の詳細から保護される

  • システムの寿命が延びる

  • 新技術への適応が容易になる

という点です。これは単なる技術的な改善ではなく、ソフトウェア開発の本質的な価値の再定義といえるでしょう。

質問4

革新的すぎて、4つの層の設計の順序が想像できないのですが、 従来のデバイス系へビジネス系が依存する設計では、先にデバイス系のクラスライブラリの設計を行ってから、ビジネス系を設計していくやり方になったと思います。 クリーンアーキテクチャでは、ビジネス系クラスライブラリを先に設計してから、デバイス系を設計していくのでしょうか。 設計におけるトップダウン・ボトムアップといった「考える順番」が想像できないのです。 設計開発において、トップダウン・ボトムアップは相互に行き来する事は、分かっていますが、基本的方向性のようなものを知りたいです。

Claude回答

クリーンアーキテクチャにおける設計の進め方について、実践的な例で説明させていただきます。

基本的な方向性は「内側から外側へ」(ビジネス中心のトップダウン)ですが、実際の設計プロセスを見てみましょう。

例として、「注文管理システム」の設計プロセスを段階的に示します:

この設計プロセスの特徴は:

  1. 設計の出発点:ドメインモデリング

    • ビジネスの専門家との対話から始まる

    • データベースやUIを考える前に、業務の本質を理解し形式化

  2. インターフェースの定義による境界の確立

  3. 外側の層は内側の要求に応える形で実装

実際の設計プロセスでは:

  1. 初期フェーズ

    • ドメインエキスパートとの対話

    • ユースケースの洗い出し

    • 中心となるビジネスルールの特定

  2. 反復的な設計プロセス

    • 内側から外側へと設計を進める

    • 必要に応じて内側の層を見直す

    • テストを書きながら設計を検証

  3. 技術的な実装の決定

    • ビジネスロジックが固まってから

    • 外部インターフェースの具体的な実装を決定

この方式のメリット:

  • ビジネスロジックが技術的な制約に影響されない

  • 要件の変更に強い

  • テストが書きやすい

  • 技術の変更が容易

ただし、注意点として:

  1. 完全な一方向の設計は現実的ではない

    • ある程度の行き来は必要

    • プロトタイプを作りながら検証も重要

  2. チームの習熟が必要

    • 従来の設計手法とは異なるアプローチ

    • 移行には学習期間が必要

  3. プロジェクトの特性による適用度の調整

    • 小規模プロジェクトでは簡略化も可能

    • ビジネスロジックの複雑さに応じて調整

このように、基本的な方向性は「内側から外側へ」ですが、実践では反復的かつ柔軟なアプローチが求められます。

質問5

従来手法であれば、まずデータ設計やアーキテクチャ設計などデバイスの「扱い安さ」やデバイスの性能を最大化する事を念頭に設計していました。 クリーンアーキテクチャの設計をするときに、4つの層を区別する「基準」や「概念」を教えてください。 概念的に何を「拠り所」にして考えれば良いのか想像できません。

Claude回答

クリーンアーキテクチャにおける4つの層を区別する基準について、具体例を交えて説明させていただきます。

各層を区別する主な「拠り所」は、「変更の理由」です。つまり、「なぜその部分が変更されるのか」という変更の動機に基づいて層を分けます。

 

各層の区別の基準は:

  1. Entities層(最内層)

    • 「ビジネスそのものの規則」を表現

    • 変更の理由:ビジネスの本質的なルールが変わる時のみ

  2. Use Cases層

    • 「特定のユースケースにおける業務フロー」を表現

    • 変更の理由:業務の進め方や手順が変わる時

  3. Interface Adapters層

    • 「外部とのデータのやり取りの方法」を表現

    • 変更の理由:データの表現形式やUIが変わる時

  4. Frameworks & Drivers層(最外層)

    • 「技術的な実装の詳細」を表現

    • 変更の理由:使用する技術やフレームワークが変わる時

層を分ける際の重要な考え方

  1. 変更の波及効果を考える

    • 内側の層の変更は外側に影響する

    • 外側の層の変更は内側に影響しない

  2. 依存関係の方向を意識する

    • 内側の層は外側の層を知らない

    • 外側の層は内側の層に依存する

  3. 境界での型変換を意識する

    • 層をまたぐときはデータ形式を変換する

    • 各層は自身の型を持つ

この「変更の理由」という視点を持つことで:

  • 各コードがどの層に属するべきかが明確になる

  • 適切な抽象化のレベルを決定できる

  • 変更の影響範囲を予測しやすくなる

これにより、ソフトウェアの保守性と拡張性が向上します。

質問6

Interface Adapters層の視点で見ると、DBMSもOS等のAPIも、外部のWeb-APIも皆「外部」という解釈になるのですか。 Frameworks & Drivers層の対象は、具体的なDBMSやネットワークライブラリやフレームワークを対象に設計するということですか。 Frameworks & Drivers層で具体的なOSやネットワークやミドルウェアやフレームワークに対応し、Interface Adapters層は、そういった具体的な「実体」の存在を抽象化して、意識しなくて良いようにする役割の層という認識で良いでしょうか。

Claude回答

はい、その理解は正確です! 具体例を用いて、Interface Adapters層とFrameworks & Drivers層の関係性をより詳しく説明させていただきます。