クリーンアーキテクチャについて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層の関係性をより詳しく説明させていただきます。

この構造の重要なポイントは:

  1. Interface Adapters層の役割

    • すべての外部システムを抽象化したインターフェースを定義

    • 具体的な技術の選択を隠蔽

    • ビジネスロジックに必要な操作のみを定義

  2. Frameworks & Drivers層の役割

    • 具体的な技術やフレームワークに依存する実装を提供

    • 実際のAPI呼び出しやデータベース操作を行う

    • 外部システム固有のエラーハンドリングを行う

  3. 境界での変換

  1. 外部システムの種類による分類

Interface Adapters層で抽象化される主な外部システム:

  • データベース

  • Web API(自社・他社問わず)

  • メッセージキュー

  • ファイルストレージ

  • キャッシュシステム

  • メール送信サービス

  • 認証サービス

  • 等…

Frameworks & Drivers層での具体的な実装例:

  • データベース: SQL Server, PostgreSQL, MongoDB

  • ストレージ: AWS S3, Azure Blob Storage, GCS

  • メッセージキュー: Kafka, RabbitMQ, Azure Service Bus

  • Web API: REST, gRPC, GraphQL

  • 認証: OAuth, OIDC, Active Directory

  1. 利点

    • 外部システムの変更が容易

    • テストが容易(モック化が簡単)

    • ビジネスロジックの純粋性を保持

    • 新しい技術への対応が容易

  2. 実装の考え方

このように、Interface Adapters層は「何をするか」を定義し、Frameworks & Drivers層は「どのように実現するか」を実装する、という明確な役割分担があります。

質問7

Entities層は「ビジネスそのものの規則」を表現し、 Use Cases層は「特定のユースケースにおける業務フロー」を表現するということですが、 両者を区別する基準がイマイチよく分かりません。 例えば、在庫管理システムの場合、倉庫・物品・物品数・棚・輸送担当者・トラックなどのオブジェクトと、入庫・出庫・在庫問い合わせ・輸送などの操作があります。 これらは、Entities層とUse Cases層に設計するとき、それぞれどのように分類すれば良いのですか。

Claude回答

なるほど、Entities層とUse Cases層の区別について、在庫管理システムを例に具体的に説明させていただきます。

基本的な区別の基準は:

  • Entities層:「それ自体の規則」(不変の業務規則)

  • Use Cases層:「それらを組み合わせた操作の流れ」(具体的なビジネスケース)

この例から、区別のポイントを整理すると:

  1. Entities層に含めるもの

    • 「もの」自体が持つべき性質や規則

  2. Use Cases層に含めるもの

    • 複数のEntitiesを組み合わせた操作の流れ

    • 特定のビジネスケースにおける手順

  3. 重要な区別のポイント

    a. 変更の理由が異なる

    • Entities層:ビジネスの基本ルールが変わる時

    • Use Cases層:業務の進め方が変わる時

    b. スコープが異なる

    • Entities層:単一のオブジェクトの範囲

    • Use Cases層:複数のオブジェクトを跨ぐ処理

    c. 依存関係

    • Entities層:他のオブジェクトをほとんど知らない

    • Use Cases層:必要なEntitiesを組み合わせて利用

  4. 実装上の違い

    Entities層:

    Use Cases層:

  5. 判断に迷う場合のガイドライン

    • その規則は単一のオブジェクトで完結するか? → Entities層

    • 複数のオブジェクトの協調が必要か? → Use Cases層

    • その操作は常に同じ方法で行われるか? → Entities層

    • 状況によって手順が変わる可能性があるか? → Use Cases層

このように、「個々のオブジェクトの本質的な規則」と「それらを組み合わせた具体的な業務フロー」という視点で区別することで、より明確な設計が可能になります。

質問8

クリーンアーキテクチャの概要は、理解できた気がします。 説明を聞く限り、クリーンアーキテクチャを採用するのに相応しいソフトウェアは、業務システムになると思います。 逆に、人間の業務が特に定まっていない、汎用ソフトウェアにはクリーンアーキテクチャによる設計は相応しくないように思えますが、この認識は妥当でしょうか。

Claude回答

はい、その認識は的確です。クリーンアーキテクチャの適性について、具体例を交えて分析してみましょう。

クリーンアーキテクチャに適したシステム:

  1. 業務システム

  1. 金融システム

  1. 在庫管理システム

クリーンアーキテクチャが相対的に適さないシステム:

  1. 汎用ツール

  1. システムユーティリティ

  1. ゲーム

適性を判断する基準:

  1. ビジネスルールの存在

    • 適している:明確な業務規則がある

    • 適さない:技術的な処理が主体

  2. 変更の性質

    • 適している:ビジネスルールの変更が主

    • 適さない:技術要件の変更が主

  3. アーキテクチャの複雑さと利点のバランス

適している場合:

適さない場合:

結論として:

  • クリーンアーキテクチャは、ビジネスロジックが中心で、長期的な保守が必要なシステムに適しています

  • 一方、技術的な処理が主体で、ビジネスルールがないまたは単純なシステムでは、過剰な設計になる可能性があります

  • 適用を検討する際は、システムの性質保守の必要性のバランスを考慮することが重要です

このように、クリーンアーキテクチャの採用は、システムの性質や要件に応じて慎重に判断する必要があります。

質問9

汎用ソフトウェアを開発するときは、このクリーンアーキテクチャのFrameworks & Drivers層に組み込みやすいように作ると良いと思います。 そのような考え方は、存在するのでしょうか。 それともクリーンアーキテクチャ設計と汎用ソフトウェア設計の設計手法は、完全に分離しているのでしょうか。

Claude回答

はい、その考え方は非常に重要で価値のある視点です! 実際、多くの有名な汎用ソフトウェアライブラリやフレームワークは、クリーンアーキテクチャのような階層化されたシステムに統合しやすいように設計されています。

このアプローチを具体的に見てみましょう:

このアプローチには以下のような特徴があります:

  1. 設計原則の共有

    • SOLID原則の適用

    • 依存性の逆転

    • インターフェースによる抽象化

  2. 統合しやすい設計パターンの採用

  1. 柔軟な構成オプション

  1. 明確な境界の定義

このように、両者の設計は実際には密接に関連しており、以下のような利点があります:

  1. 再利用性の向上

    • クリーンアーキテクチャへの統合が容易

    • 様々なコンテキストでの使用が可能

  2. 保守性の向上

    • 明確な責任の分離

    • テストの容易さ

  3. 拡張性の確保

    • 新機能の追加が容易

    • 既存機能の修正が局所化

具体的な設計のガイドライン:

  1. インターフェースの設計

    • 汎用的で明確な契約

    • 最小限の依存性

  2. 実装の分離

    • 具体的な実装の詳細を隠蔽

    • 設定可能な振る舞い

  3. 拡張ポイントの提供

    • プラグイン機構

    • カスタマイズ可能なコンポーネント

このように、汎用ソフトウェアとクリーンアーキテクチャは、相互に補完し合う関係にあると考えられます。適切に設計された汎用ソフトウェアは、クリーンアーキテクチャの実装をより容易にし、より堅牢なシステムの構築を可能にします。

質問10

クリーンアーキテクチャに合わせる為に、汎用ソフトウェア設計に必要な制約やルールや方法論などが、ありましたら教えてください。 無ければ、「無い」ということで良いです。

Claude回答

クリーンアーキテクチャとの統合を念頭に置いた汎用ソフトウェア設計には、いくつかの重要な設計原則や推奨事項があります:

  1. 抽象化レベルの分離

  1. 依存性の方向制御

  1. 設定の分離

  1. 拡張ポイントの提供

  1. 副作用の制御

  1. ライフサイクルの管理

これらの原則は、クリーンアーキテクチャとの親和性を高めますが、厳密な「制約」や「ルール」というよりは、「推奨事項」として捉えるべきです。

プロジェクトの性質や要件に応じて、これらの原則の適用度合いを調整することが重要です。また、これらの原則を過度に適用すると、不必要な複雑さを招く可能性があることにも注意が必要です。

したがって、「クリーンアーキテクチャのために必ず従うべき厳格なルール」は特にありませんが、上記のような設計原則を意識することで、より統合しやすい汎用ソフトウェアを設計することが可能になります。

 

 

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

タイトルとURLをコピーしました