C# Web API - デレク・コマーティンのアプローチによるAPIの構造化の完全な考察
C# Web API プロジェクトを開始するとき、開発者はコードをどのように構成するか、圧倒的な数の選択肢に直面することがよくあります。 .NET Core Web APIのレイヤーパターンに従うべきか? Visual Studioのデフォルトテンプレートのcontrollersフォルダにこだわるべきでしょうか? それとも、Minimal APIsのようなモダンなスタイルを試すべきでしょうか?
Keep Your Project Structure Simple!"というビデオで、CodeOpinion.com の Derek Comartin 氏は、意見を述べながらも、爽やかで実用的なスタンスをとっています。 彼は、実際のソフトウェア・システムで機能する方法でウェブAPIを構築し、組織化するためのアイデアを、実際に重要なこと、つまりシンプルさに焦点を当てながら説明している。
この記事では、Derek氏のビデオに沿って、ASP.NET Core Web APIプロジェクトを分かりやすく、保守しやすく、実世界のスケーラビリティを確保できるように構成する方法を順を追って説明します。
一般的な API 構造を見る
Derek は、Visual Studio で新しい Web API プロジェクトを作成するときに、ほとんどの開発者がぶつかる質問から始めます:
HTTP APIをどのように構成すべきか?
彼はすぐに、Web APIプロジェクトはさまざまな方法で編成できることを認めている。 Derek がよく目にするフォルダ構造には、次のようなものがあります:
モデルをModelsフォルダに、コントローラをControllersフォルダに、サービスをServicesフォルダに入れるなど、技術的な関心ごとにグループ化すること。
クリーンアーキテクチャまたはオニオンアーキテクチャの使用 - プロジェクトをレイヤー(API、アプリケーション、ドメイン、インフラストラクチャ)ごとに分割し、依存関係をガイドします。
- ドメイン駆動設計(DDD)と垂直スライスアーキテクチャの組み合わせ - 機能ごとにエンドポイントをグループ化しつつ、ドメインが豊富なオブジェクトを持つ。
Derekは、これらのパターンのそれぞれが、リソースを扱うために期待されるHTTPメソッド(GET、POST、PUT、DELETE)を使用するRESTful APIを作成できることを強調している。 しかし、フォルダー構造だけを読みすぎないよう、彼は警告している:
エンティティ、アグリゲート、ドメインサービスが表示されるかもしれませんが、そのコードが本当にドメイン駆動設計を行っているわけではありません。
複雑さではなく、シンプルさから始める
デレク氏は、目標は簡単だと言います:
この構成で実現したかったことのひとつは、シンプルさです。
デレクは、.NET Frameworkスタイルの重いアーキテクチャに飛び込んだり、教科書のパターンを再現したりするのではなく、ASP.NET Core Minimal APIを選択しました。なぜですか? なぜなら、これらのツールは、コントローラや定型コードのオーバーヘッドなしにAPIを簡単に作成できるからです。
Visual StudioやVisual Studio Codeで新しいWeb APIプロジェクトを構築する場合、新規プロジェクトダイアログからASP.NET Core Web APIを選択します。 デフォルトでは、コントローラ、フォルダ、多くの足場が用意されています。 デレクは、シンプルですっきりとした構成で、小規模なものから始めたほうがよい場合が多いと主張する。
デレクのウェブAPIのコア構造
デレクは、.NET Coreを使用したWebアプリケーションの構造を紹介しています。 一般的なHTTPサービスとRESTful APIをサポートするように構築されており、さまざまなソフトウェアアプリケーションが通信できるようになっています。
彼のウェブAPIプロジェクトの構成は以下の通りです:
エンドポイントファイル - APIで利用可能なすべてのルートを確認するための単一のファイルです。 Derekは、複数のコントローラを調べ上げる代わりに、APIがサポートするすべてのgetメソッド、postメソッド、putリクエスト、deleteリクエストの概要を簡単に説明したいと考えています。
共通フォルダ - 異なるソフトウェアシステム間で使用されるフィルタや拡張機能などの共有コードを保持します。
機能フォルダ - 垂直スライスの哲学に従って、新しいリソースや既存のリソースは、それぞれ独自のフォルダを取得します。 例えば、Postsフォルダは、GET /posts/{id}、POST /posts、PUT /posts/{id}、DELETE /posts/{id}に必要なすべてを含むかもしれません。
- Data Folder - データモデルとエンティティマッピングを含みます。 ここでは、シームレスなデータベース統合のためにEntity Framework Coreが使用されています。
機能ごとにエンドポイントをグループ化することで、Derekは複数の無関係なフォルダにロジックが分散するのを避けることができます。
なぜ彼はドメイン駆動設計を強制しないのか
Derekはこれまでもドメイン駆動設計を使用してきましたが、このC# Web API構造では重要な選択をしています:
ドメイン駆動設計を使用するつもりはありません。
その代わり、彼は"データをデータとして扱う"。彼のデータ・モデルは、次のような単純なプロパティを持つプレーンなクラスである:
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
}public class Post
{
public int Id { get; set; }
public string Title { get; set; }
}不必要な動作を詰め込むことはありません。 新しいリソースを作成するためにPOSTリクエストを送信すると、APIは単にそれを保存します。 id パラメータを指定して DELETE リクエストを送信すると、そのリソースが削除されます。
このアプローチでは、APIエンドポイントをPost、User、Commentなどのリソースに作用する動詞(getメソッド、postメソッド、putメソッド、deleteメソッド)として扱うことで、Representational State Transfer(REST)のアーキテクチャスタイルを採用しています。
Visual Studio でのソリューションの説明
この時点で、DerekはVisual Studioのソリューションを開き、私たちに案内してくれました:
Endpointsファイルには、データを取得するGETリクエスト、新しいリソースを追加するPOSTリクエスト、データを更新するPUTリクエスト、既存のリソースを削除するDELETEメソッドなど、すべてのルートがリストされています。
Dataフォルダには、Entity Frameworkを介してデータベースに接続されたPost、User、Commentなどのエンティティのマッピングが格納されています。
Common フォルダには、検証フィルタや拡張機能などの HTTP サービスの共有ロジックが含まれています。
- 各機能フォルダ(投稿、コメント、認証)には、そのリソースに必要なすべてのコードがあります。
このすっきりとしたプロジェクトフォルダレイアウトは、複雑すぎるプロジェクトダイアログや散らばったコントローラフォルダを探し回る混乱を回避します。
エンドポイントを分解する
デレクは、ASP.NET Core Web APIの各エンドポイントは、3つの明確なステップを持つ自己完結型の作業単位であると説明しています:
1.マッピング - HTTPメソッドとルートを定義します。 例えば、削除リクエストは、DELETE /posts/{id}をハンドラメソッドにマップするかもしれません。
2.リクエストとレスポンスのコントラクト - 各エンドポイントには、独自のリクエストボディとレスポンスタイプがあります。 これにより、HTTPサービスが明確になり、重複したDTOのレイヤーを作成することがなくなります。
3.ロジック - 実際のハンドラーメソッドで、APIがデータベースから取得したり、データモデルを更新したり、return CreatedAtActionやreturn NoContentのようなステータスコードを返したりします。
DerekはMinimal APIを使用しているため、これらのハンドラは静的メソッドです。 .NET Coreでは、依存関係を直接注入できるため、かさばるコントローラクラスは必要ありません。
なぜ最小限の API がしっくりくるのか
デレクは、Minimal APIsのシンプルさを称賛しています。 .NET Coreの最小限のテンプレートを使用すると、Program.csのわずか数行でWeb APIプロジェクトを開始できます:
var app = WebApplication.CreateBuilder(args).Build();var app = WebApplication.CreateBuilder(args).Build();そこから、getメソッド、postメソッド、putリクエストをわかりやすく追加します。
このシンプルさは、開発者がやみくもにNuGetパッケージのテンプレートをコピーしたり、マイナーなエンドポイントごとに新しいコントローラクラスを強制したりするときに、Derekがよく目にする過剰なエンジニアリングを避けるのに役立ちます。
複雑さは時間とともにどのように進化するか
デレクは実際の例として、"投稿にいいね!"機能を挙げています。
最初は、"いいね!"があるかどうかをチェックし、なければ追加するというシンプルな作業です。
しかしその後、ソフトウェア・アプリケーションは、ウェブページやモバイル・デバイス向けに、瞬時に同種のカウントを返す必要が出てくるかもしれません。
- スケールするために、Post データモデルに LikeCount プロパティを追加して、データを非正規化することがあります。
これは新たな課題です:
いいね!"に影響を与えるすべてのputメソッドまたはdeleteメソッドは、カウントを正しく更新する必要があります。
- 誰かがAPIを呼び出すことなく同じようなレコードを追加した場合、カウントが間違っています。
デレクは、複雑さが増すにつれて、次のようなパターンを追加する可能性があることを示しています:
データアクセスをカプセル化するためのリポジトリパターン。
(LikeCountのインクリメントのような)ビヘイビアを処理するための集約ルート。
- イベント("PostLiked "など)の公開を保証するOutboxパターン。
しかし、彼の重要なポイントは明確だ:
ここから始めないでください。 シンプルなものから始め、必要な場合のみ進化させてください。"
デレクのまとめ
Derek は最後に、C# Web API 開発者のための主要なレッスンに戻ります:
"Start with simple."(シンプルに始めよう)。
Visual StudioでASP.NET Core Web APIやASP.NET Web APIを使用する場合、初日からあらゆるフォルダ、パターン、NuGetパッケージを追加して、過剰なエンジニアリングを行いがちです。
しかし、デレクは警告する。"やみくもにソリューションを適用しないでください。 必要なHTTPメソッド、扱うデータ、通信を可能にするソフトウェアシステムを理解してください。 ステップ・バイ・ステップでRESTful APIを構築してください。
Visual Studio Codeやその他の統合開発環境を使用している人にとって、彼のアドバイスは真実です:新しいプロジェクトであれ、既存のリソースであれ、プロジェクトの構造はできるだけシンプルに保ち、現実世界の複雑さが必要とする場合にのみパターンを追加すること。
結論
Derek Comartin 氏の video は、C# Web API を構築するための単なるガイドではありません。 Visual Studioで実際にASP.NET Core Web APIのセットアップを行いながら、設計を複雑にしすぎることなく、異なるソフトウェアアプリケーション間のシームレスな通信を可能にするRESTful APIの基盤を、最小限のAPI、機能フォルダ、およびわかりやすいデータモデルでどのように形成できるかを示しています。
このアプローチを実際に見たり、デレクの見解を直接聞いたりしたい場合は、彼のビデオは優れたリソースです。 チャンネルには、ソフトウェアシステム、Web サービス、.NET Core 開発に関する同じく洞察に満ちた議論が満載されており、技術を向上させ、プロジェクトをクリーンで実用的、かつ将来的に使いやすいものに保ちたいと考えている開発者にとっては必見です。

