mcpField
D
dotnet-core

dotnet-core

github.com/alexander-danilenko開発1779 回インストール5 日前に更新
リポジトリ

dotnet-core について

.NET 8 バックエンドサービスの設計・保守に向けたアーキテクチャ指針です。レイヤー構成、ドメインモデル、検証、可観測性、テストを扱い、CQRSやAOTを採用する判断材料も示します。

主な機能

  1. 01内向き依存のレイヤー構成
  2. 02ファクトリーによる不変条件の維持
  3. 03CQRSとパイプラインビヘイビアの指針
  4. 04機能別にまとめるMinimal APIs
  5. 05ヘルスチェックと構造化ログ
  6. 06統合テストとコンテナの指針

活用シーン

  1. 01.NET 8サービスの構成設計
  2. 02ドメイン層とインフラ層の境界確認
  3. 03検証と横断的関心事の標準化
  4. 04ヘルスチェックと統合テストの設計

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/alexander-danilenko/cortex-ai-skills --skill dotnet-core

インストール後、Claude Code で/dotnet-coreを入力して読み込まれたか確認します。

詳細

.NET Core アーキテクチャ

.NET 8 バックエンドサービスのアーキテクチャ規約です。ここではサービスの 構造 を扱います。言語レベルの規約については、csharp スキルを参照してください。

レイヤー構成

依存関係は内側にのみ向けます。Domain はほかの何も知りません。データベースや SDK を参照できるのは Infrastructure レイヤーだけです。そのため、内側のレイヤーはどちらにも依存せずにテストできます。

Domain          entities, value objects, domain events, interfaces  → no dependencies
Application     use cases, CQRS handlers, DTOs, validators          → Domain
Infrastructure  EF Core, external APIs, implementations of Domain interfaces → Domain + Application
Api             endpoints, DI wiring, middleware                    → all of the above

この原則が守られていることを確認するテストは、Domain が BCL 以外のパッケージ参照なしでコンパイルできるかどうかです。コンパイルできれば、境界は保たれています。

エンティティは自身の不変条件を守ります。セッターは private にし、EF Core のマテリアライザー用に引数なしの private コンストラクターを用意し、検証を行う static ファクトリを使います。public セッターがあると、どのレイヤーからでもエンティティを無効な状態にできてしまいます。そうなると、「ドメインが X を保証する」というのは単なるコメントにすぎません。

public class Product
{
    public string Name { get; private set; } = string.Empty;
    public decimal Price { get; private set; }

    private Product() { } // EF Core materialisation only

    public static Product Create(string name, decimal price) =>
        price <= 0
            ? throw new DomainException("Price must be greater than zero")
            : new Product { Name = name, Price = price };
}

規約

  • 読み取りと書き込みが実際に異なる場合は、MediatR による CQRS を採用します — モデル、整合性、スケーリングが異なる場合です。CRUD サービスでは形式的な手続きになるため、デフォルトではなく、ドメインが必要とする場合に採用してください。
  • 横断的関心事はハンドラーではなく、パイプラインビヘイビアに置きます。 検証、ロギング、トランザクションをビヘイビアとして一度実装すれば、すべてのハンドラーに適用され、新しいハンドラーで適用し忘れることもありません。
  • Minimal API は MapGroup でグループ化し、機能領域ごとにファイルを分けます。 すべてのエンドポイントを単一の Program.cs に置くと、ルートが二十個ほどになった時点で読みづらくなります。
  • 検証は Application 境界で行います(ビヘイビア内の FluentValidation)。これにより、どのエントリーポイントからユースケースが呼び出されても同じルールが適用されます。エンドポイントでの検証では、HTTP 経由の場合しか保護できません。
  • DbContext は Infrastructure に置き、Application レイヤーが所有するインターフェイスの背後に隠します。 DbContext をハンドラーに漏らすと、ユースケースが EF に結び付き、プロバイダーなしではテストできなくなります。
  • シークレットを appsettings.json に入れてはいけません — ローカルではユーザーシークレット、本番環境では環境変数または Vault を使います。コミットされた情報は漏えいしたものと見なされ、ローテーションには再デプロイが必要になります。
  • ヘルスチェック(/health/live、/health/ready)と、相関 ID を使った構造化ログを最初から導入します。 インシデント発生中に可観測性を後付けしようとするのは、何もないことに気付くタイミングとして最悪です。二つのプローブは明確に異なるものにしてください。readiness ではデータベースや下流の API を確認してもかまいませんが、liveness ではプロセス自体が生存しているかだけを確認します。liveness プローブがデータベースに ping を送ると、短時間のデータベース障害ですべての Pod が再起動され、回復可能な依存先の障害が全面停止につながります。
  • コンテナーは非 root ユーザーで実行します。 USER 行を追加してください。デフォルトの root コンテナーでは、プロセスレベルの侵害がホストレベルにまで及びます。これを防ぐのに必要なのは 1 行だけです。
  • 実際のデータベース(Testcontainers)を使い、WebApplicationFactory 経由で統合テストを行います。 DI グラフ、ルーティング、シリアル化、EF マッピングをテストできます。これらは、モックを使った単体テストではサービスが壊れていても成功と報告されるレイヤーです。
  • 起動時間やフットプリントに見合う場合に限り、AOT を採用します。 AOT ではランタイムリフレクションが使えなくなり、一部のシリアライザーや DI のパターンが気付かないうちに壊れることがあります。採用を決める前に、スタック全体が AOT に対応できることを確認してください。

コメント