Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】.NET Folder Structure: A to Z

2026年10月09日に「Dev.to」が公開したITニュース「.NET Folder Structure: A to Z」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

.NETプロジェクトが複雑になった際、Clean Architectureは「Domain」「Application」「Infrastructure」「Presentation」の4層に役割を分担し、コードを整理する。これにより、各機能が独立し変更やテストが容易になり、大規模な開発でも効率的に進められる。

出典: .NET Folder Structure: A to Z | Dev.to公開日:

ITニュース解説

システム開発において、プロジェクトが大きくなるにつれて扱うファイルやコードの量は指数関数的に増えていく。最初は数個だったファイルが数ヶ月後には数百個にもなることは珍しくない。このような状況で、特定の機能に不具合が見つかった場合、それがどのファイル、どのフォルダにあるのかをすぐに見つけ出すのは至難の業だ。ファイルを探すだけで何分も無駄にしてしまったり、チームに新しく加わったメンバーがプロジェクト全体を理解するのに途方もない時間がかかったりすることは、開発効率を著しく低下させる。適切なフォルダ構造は、このような混乱を防ぎ、プロジェクト全体を円滑に進めるための「地図」のようなものだと言える。この地図が正しく整備されていれば、どんなに複雑なプロジェクトでも、必要な場所に迷わずたどり着くことができる。

Clean Architecture(クリーンアーキテクチャ)は、大規模なソフトウェアプロジェクトを整理し、保守性と拡張性を高めるための設計思想の一つである。このアーキテクチャでは、プロジェクトを主に四つの層に分割する。それぞれの層は特定の役割を持ち、外側の層は内側の層の存在を知っているが、内側の層は外側の層について何も知らないという厳格な依存関係のルールが存在する。この構造の狙いは、ビジネスの中核となるロジックを、データベースやユーザーインターフェース(UI)といった外部の変化の影響から隔離することにある。例えば、データベースの種類が変わったり、UIがウェブからモバイルに変わったりしても、ビジネスロジックはそのまま再利用できる設計を目指す。

具体的には、最も内側にあるのが「Domain(ドメイン)」層、その外側に「Application(アプリケーション)」層、さらに外側に「Infrastructure(インフラストラクチャ)」層、そして最も外側に「Presentation(プレゼンテーション)」層が配置される。

それでは、各層の具体的な役割を見ていこう。

「Domain」層は、プロジェクトの心臓部であり、ビジネスにおける最も基本的な概念やルールを定義する。ここには、システムが扱う「モノ」を表すエンティティ(例:学生、コース、登録情報)、独立した識別子を持たないが重要な値オブジェクト(例:金額、住所)、状態を表す列挙型(例:登録ステータス、支払いステータス)、そして特定のイベントを示すドメインイベント(例:学生が登録された、支払いが完了した)などが含まれる。この層は、データベースへの接続方法やWeb APIの記述方法など、特定の技術に関する知識を一切持たない。外部のライブラリへの依存も極力避けることで、ビジネスロジックが純粋に保たれる。

次に「Application」層は、「何を行うか」と「どのように行うか」というビジネスプロセスを定義する場所だ。ここでは、ユーザーからの要求を処理するためのサービス(例:登録サービス、支払いサービス)や、外部システムとの連携の抽象的な定義としてのインターフェース(例:登録リポジトリのインターフェース、メール送信者のインターフェース)、データ転送オブジェクト(DTOs、例:登録リクエストDTO、支払いレスポンスDTO)などが配置される。また、入力値の検証ルールや、オブジェクト間のデータ変換ルールもこの層に書かれることが多い。この層も、具体的なデータベース接続やHTTP通信の実装方法については何も知らない。具体的な実装は他の層に委ねることで、Application層は純粋なビジネスロジックに集中できる。

「Infrastructure」層は、Application層で定義されたインターフェースの具体的な実装や、データベース、外部決済サービス、メール送信サービスなど、外部システムとのあらゆる通信を扱う。ここには、データベースコンテキスト(データベース接続の管理)、リポジトリインターフェースの具体的な実装、外部の決済サービスやメール送信サービスとの連携コード、データベースのスキーマ変更履歴(マイグレーション)などが含まれる。この層のコードは、データベースの種類や使用する外部サービスが変更された際に修正が必要になる部分だが、Application層はインターフェースを介してこの層とやり取りするため、Infrastructure層が変更されてもApplication層はほとんど影響を受けない設計が可能になる。

最後に「Presentation」層は、ユーザーからのHTTPリクエストを受け取り、適切なApplication層のサービスを呼び出す役割を担う。ウェブAPIプロジェクトでは、コントローラ、ミドルウェア(リクエスト処理の途中で追加の処理を行う機能)、フィルター、そしてアプリケーションの起動設定を行うファイル(Program.csなど)がここに配置される。Presentation層のコントローラは、ビジネスロジックを直接記述するのではなく、Application層のサービスを呼び出すことに専念するべきだ。これにより、コントローラはHTTPリクエストの処理とレスポンスの返却という、その本来の役割に集中できる。

実際のプロジェクトでは、例えば「SchoolApp」というアプリケーションの場合、各層が独立したプロジェクトとして配置され、それぞれが詳細なフォルダを持つ構造になる。ユーザーからのHTTPリクエストは、まず「Presentation (API)」層のコントローラで受け取られる。コントローラは、そのリクエストを処理するために必要な「Application」層のサービスを呼び出す。サービスは、ビジネスロジックを実行する過程で、データの取得や保存が必要になった場合、「Application」層で定義されたリポジトリのインターフェースを介してデータアクセスを要求する。このインターフェースの具体的な実装は「Infrastructure」層にあり、そこからデータベースコンテキストを通じて実際にデータベースとやり取りが行われる。処理結果は、逆の経路をたどってユーザーに返却される。このように、各層は直接隣接する層とのみやり取りし、層を飛び越えて通信することはない。

具体的なコードの例を挙げると、学生の登録処理を考えてみよう。「Presentation (API)」層のコントローラは、HTTPリクエストを受け取り、リクエストDTOを使って「Application」層の登録サービスを呼び出す。「Application」層の登録サービスは、コースの空席状況を確認したり、登録エンティティを生成したりといったビジネスルールを実行する。この際、コースや学生の情報を取得するために、「Application」層で定義されたリポジトリのインターフェースを呼び出す。例えば「コースリポジトリからIDでコースを取得する」といったコードは書くが、どのようなデータベースから取得するかは気にしない。「Infrastructure」層のリポジトリ実装は、そのインターフェースに従って、データベースコンテキストを利用して実際にデータベースからコース情報を取得する。このように、登録サービスは「空席があるか」というビジネスルールに集中し、リポジトリは「データベースからデータを取得する」というデータアクセスに集中することで、それぞれの役割が明確に分離される。

システムエンジニアを目指す初心者が見落としがちな点はいくつかある。まず、最もよくあるのが「Presentation」層のコントローラに直接ビジネスロジックを書き込んでしまうことだ。コントローラはHTTPリクエストを処理する場所であり、ビジネスロジックは「Application」層のサービスに委ねるべきである。次に、「Domain」層でデータベースコンテキストなどのデータベース固有のコードを使用すること。これは「Domain」層が外部技術に依存しないという原則に反する。また、「Application」層でインターフェースではなく、具体的な実装クラスを直接参照してしまうことも間違いだ。これでは依存関係の逆転(Dependency Inversion)という原則が破られ、インフラストラクチャ層の変更がアプリケーション層に影響を与えてしまう。さらに、リポジトリにビジネスロジックを詰め込んでしまうケースや、全てのコードをたった一つのプロジェクトやフォルダにまとめてしまうことも避けるべきである。最後に、データベースのエンティティをDTOに変換せず、そのまま外部に返してしまうこともセキュリティやデータ隠蔽の観点から推奨されない。

しかし、Clean Architectureのような厳格な構造が常に必要かというと、そうではない。プロジェクトの規模が非常に小さい場合、例えばWeb APIのエンドポイントが5〜10個程度のプロジェクトであれば、このアーキテクチャは過剰な複雑さをもたらす可能性がある。このようなケースでは、シンプルなフォルダ分けでも十分なことが多い。プロジェクトのコードベースが肥大化し、開発者が複数人になったり、50以上のエンドポイントを持つような大規模プロジェクトになったりしたときにこそ、Clean Architectureのメリットが最大限に活かされる。この設計パターンを採用するかどうかは、それがもたらすメリットが、その複雑さを維持するコストを上回るかどうかで判断すべきだ。

適切なフォルダ構造とは、結局のところ、プロジェクト内の各要素にその役割と責任を明確に割り当てることに他ならない。データベースに関わるコードはデータベースの仕事を、ビジネスロジックはビジネスの仕事を、そしてユーザーインターフェースに関わるコードはUIの仕事をそれぞれが担当する。このように各クラスやモジュールが自身の役割に集中することで、プロジェクト全体の理解が容易になり、特定の機能をテストしやすくなり、将来の変更にも柔軟に対応できるようになる。これは特別なルールというよりは、効率的で持続可能なソフトウェア開発のための、実践的な共通認識なのである。

関連コンテンツ

関連IT用語