Skip to main content

clean-architecture-guide

Modular Monolith + Clean Architecture の設計ガイド。新しいモジュールの作成、画面の実装、機能追加を行う際には、必ずこのスキルを参照して従ってください。

Quellinformationen

Repository
runceel/github-copilot-excel-document-to-code
Letzte Quellaktivität
24. Februar 2026 um 13:28
Erkannte Sprache von SKILL.md
Japanisch
Sterne
1
Forks
0

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
clean-architecture-guide
description
Modular Monolith + Clean Architecture の設計ガイド。新しいモジュールの作成、画面の実装、機能追加を行う際には、必ずこのスキルを参照して従ってください。
# Clean Architecture 設計ガイド このスキルは、本プロジェクトにおける Modular Monolith + Clean Architecture の具体的な設計パターンとルールを定義します。 > **重要:** このスキルに基づいてコード編集・生成を行う際には、対応する言語・プラットフォームのスキル(例: `dotnet10`、`aspnetcore-blazor10` 等)を必ず併せて参照してください。最新の言語機能や API を正しく使用するために必要です。 ## 1. モジュール構成 新しいモジュールは以下の 3 プロジェクトで構成します。 ``` src/Modules/<ModuleName>/ <ModuleName>.Domain/ # エンティティ、値オブジェクト(依存なし) <ModuleName>.Application/ # UseCase、DTO、リポジトリインターフェース(Domain のみ依存) <ModuleName>.Infrastructure/ # リポジトリ実装、外部サービス連携、DI 登録(Application に依存) ``` ### プロジェクト作成手順 ```bash # 1. プロジェクト作成 dotnet new classlib -n <ModuleName>.Domain -o src/Modules/<ModuleName>/<ModuleName>.Domain --framework net10.0 dotnet new classlib -n <ModuleName>.Application -o src/Modules/<ModuleName>/<ModuleName>.Application --framework net10.0 dotnet new classlib -n <ModuleName>.Infrastructure -o src/Modules/<ModuleName>/<ModuleName>.Infrastructure --framework net10.0 # 2. ソリューションに追加 dotnet sln add src/Modules/<ModuleName>/<ModuleName>.Domain dotnet sln add src/Modules/<ModuleName>/<ModuleName>.Application dotnet sln add src/Modules/<ModuleName>/<ModuleName>.Infrastructure # 3. プロジェクト参照設定 dotnet add src/Modules/<ModuleName>/<ModuleName>.Application reference src/Modules/<ModuleName>/<ModuleName>.Domain dotnet add src/Modules/<ModuleName>/<ModuleName>.Infrastructure reference src/Modules/<ModuleName>/<ModuleName>.Application # 4. Infrastructure に DI パッケージ追加 dotnet add src/Modules/<ModuleName>/<ModuleName>.Infrastructure package Microsoft.Extensions.DependencyInjection.Abstractions # 5. Infrastructure に EF Core パッケージ追加 dotnet add src/Modules/<ModuleName>/<ModuleName>.Infrastructure package Microsoft.EntityFrameworkCore # DB プロバイダーパッケージも追加(例: SqlServer, Sqlite, Npgsql 等) # ⚠️ プロバイダーが不明な場合はユーザーに確認すること dotnet add src/Modules/<ModuleName>/<ModuleName>.Infrastructure package Microsoft.EntityFrameworkCore.<Provider> # 6. Web からの参照追加 dotnet add src/Web reference src/Modules/<ModuleName>/<ModuleName>.Application dotnet add src/Web reference src/Modules/<ModuleName>/<ModuleName>.Infrastructure # 7. 自動生成された Class1.cs を各プロジェクトから削除 ``` --- ## 2. 依存関係ルール ``` Web ──→ Application (UseCase インターフェース、DTO のみ) Web ──→ Infrastructure (DI 登録の拡張メソッド呼び出しのためのみ) Infrastructure ──→ Application (リポジトリインターフェースの実装) Application ──→ Domain (エンティティの利用) Domain ──→ (依存なし) ``` ### 禁止事項 | ルール | 説明 | |--------|------| | **Web から Domain エンティティを直接参照しない** | Web 層は Application 層の DTO のみを使用する | | **Web から Repository を直接注入しない** | Web 層は UseCase インターフェース経由でのみデータにアクセスする | | **ビジネスロジックを Web / Infrastructure に書かない** | ビジネスロジックは Domain と Application のみに配置する | | **Application 層から Infrastructure を参照しない** | Application 層はインターフェースを定義し、実装は Infrastructure 層が行う | | **リポジトリ内で SaveChangesAsync を呼ばない** | SaveChangesAsync は UseCase が IUnitOfWork 経由で呼ぶ。1 UseCase = 1 トランザクション単位とする | --- ## 3. 各層の実装パターン ### 3.1 Domain 層 — エンティティ ビジネスの中核となるデータ構造を定義します。 ```csharp namespace <ModuleName>.Domain; public class <EntityName> { public int ID { get; set; } public string Name { get; set; } = ""; // ビジネスルールに関わるメソッドもここに配置可能 } ``` ### 3.2 Application 層 — DTO Web 層に公開するデータ転送オブジェクトです。Domain エンティティの代わりにこれを使います。 ```csharp namespace <ModuleName>.Application; public record <EntityName>Dto(int ID, string Name); ``` ### 3.3 Application 層 — リポジトリインターフェース データアクセスの抽象を定義します。UseCase 内部から使用され、Web 層には公開しません。 ```csharp namespace <ModuleName>.Application; public interface I<EntityName>Repository { Task<IReadOnlyList<Domain.<EntityName>>> GetAllAsync(); Task UpdateAsync(int id, ...); } ``` ### 3.4 Application 層 — IUnitOfWork インターフェース Unit of Work の抽象を定義します。UseCase がトランザクションの完了(`SaveChangesAsync`)を制御するために使用します。 ```csharp namespace <ModuleName>.Application; public interface IUnitOfWork { Task<int> SaveChangesAsync(CancellationToken cancellationToken = default); } ``` > **ポイント:** `IUnitOfWork` を Application 層に置くことで、UseCase は Infrastructure 層(DbContext)に直接依存せずにトランザクション管理を行えます。 ### 3.5 Application 層 — UseCase **Web 層が唯一依存する操作インターフェース** です。1 つの操作 = 1 つの UseCase とし、`ExecuteAsync` メソッドを持ちます。 ```csharp namespace <ModuleName>.Application.UseCases; // インターフェース public interface IGet<EntityName>sUseCase { Task<IReadOnlyList<<EntityName>Dto>> ExecuteAsync(string? searchText = null); } // 実装(Application 層内に配置) public class Get<EntityName>sUseCase(I<EntityName>Repository repository) : IGet<EntityName>sUseCase { public async Task<IReadOnlyList<<EntityName>Dto>> ExecuteAsync(string? searchText = null) { var entities = await repository.GetAllAsync(); // フィルタリングなどのビジネスロジックはここで行う var filtered = string.IsNullOrEmpty(searchText) ? entities : entities.Where(e => e.Name.Contains(searchText, StringComparison.OrdinalIgnoreCase)).ToList(); // Domain → DTO 変換 return filtered.Select(e => new <EntityName>Dto(e.ID, e.Name)).ToList(); } } ``` ```csharp namespace <ModuleName>.Application.UseCases; public interface IUpdate<EntityName>UseCase { Task ExecuteAsync(int id, ...); } public class Update<EntityName>UseCase(I<EntityName>Repository repository, IUnitOfWork unitOfWork) : IUpdate<EntityName>UseCase { public async Task ExecuteAsync(int id, ...) { await repository.UpdateAsync(id, ...); // Unit of Work: UseCase の最後で変更を永続化 await unitOfWork.SaveChangesAsync(); } } ``` ### 3.6 Infrastructure 層 — DbContext(Unit of Work 実装) データアクセスには **Entity Framework Core** を使用します。`DbContext` が Application 層の `IUnitOfWork` を実装し、**Unit of Work** パターンの役割を担います。トランザクション管理と変更追跡を一括して行います。 ```csharp using <ModuleName>.Application; using <ModuleName>.Domain; using Microsoft.EntityFrameworkCore; namespace <ModuleName>.Infrastructure; public class <ModuleName>DbContext(DbContextOptions<<ModuleName>DbContext> options) : DbContext(options), IUnitOfWork { public DbSet<<EntityName>> <EntityName>s => Set<<EntityName>>(); protected override void OnModelCreating(ModelBuilder modelBuilder) { // エンティティの設定(テーブル名、キー、制約など) modelBuilder.Entity<<EntityName>>(entity => { entity.HasKey(e => e.ID); // 必要に応じてプロパティの設定を追加 }); } // SaveChangesAsync は DbContext に既に定義されているため、 // IUnitOfWork.SaveChangesAsync として自動的に公開される } ``` ### 3.7 Infrastructure 層 — リポジトリ実装 リポジトリは `DbContext` を注入し、EF Core を使ってデータアクセスを行います。`SaveChangesAsync()` はリポジトリでは呼び出さず、UseCase 側で制御します。 ```csharp using <ModuleName>.Domain; using Microsoft.EntityFrameworkCore; namespace <ModuleName>.Infrastructure; public class <EntityName>Repository(<ModuleName>DbContext dbContext) : Application.I<EntityName>Repository { public async Task<IReadOnlyList<<EntityName>>> GetAllAsync() { return await dbContext.<EntityName>s.ToListAsync(); } public async Task UpdateAsync(int id, ...) { var item = await dbContext.<EntityName>s.FindAsync(id); if (item is not null) { // プロパティの更新(変更追跡により自動で検出される) } // SaveChangesAsync は UseCase 側で呼ぶ } } ``` ### 3.8 Infrastructure 層 — DI 登録 モジュール単位で `Add<ModuleName>Module()` 拡張メソッドを提供します。 ```csharp using <ModuleName>.Application; using <ModuleName>.Application.UseCases; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; namespace <ModuleName>.Infrastructure; public static class <ModuleName>ServiceCollectionExtensions { public static IServiceCollection Add<ModuleName>Module(this IServiceCollection services, string connectionString) { // EF Core DbContext(Unit of Work) services.AddDbContext<<ModuleName>DbContext>(options => options.UseSqlServer(connectionString)); // プロバイダーはプロジェクトに応じて変更 services.AddScoped<IUnitOfWork>(sp => sp.GetRequiredService<<ModuleName>DbContext>()); // Infrastructure(リポジトリ実装) services.AddScoped<I<EntityName>Repository, <EntityName>Repository>(); // Application(UseCase) services.AddScoped<IGet<EntityName>sUseCase, Get<EntityName>sUseCase>(); services.AddScoped<IUpdate<EntityName>UseCase, Update<EntityName>UseCase>(); return services; } } ``` --- ## 4. Web 層(Blazor ページ)の実装パターン Web 層は **UseCase インターフェースと DTO のみ** を使用します。 ```razor @page "/<route>" @using <ModuleName>.Application @using <ModuleName>.Application.UseCases @rendermode InteractiveServer <PageTitle>ページタイトル</PageTitle> <h1>ページタイトル</h1> @* UI コンポーネント *@ @code { [Inject] private IGet<EntityName>sUseCase Get<EntityName>sUseCase { get; set; } = default!; [Inject] private IUpdate<EntityName>UseCase Update<EntityName>UseCase { get; set; } = default!; private IReadOnlyList<<EntityName>Dto> items = []; protected override async Task OnInitializedAsync() { items = await Get<EntityName>sUseCase.ExecuteAsync(); } } ``` ### Program.cs での登録 ```csharp using <ModuleName>.Infrastructure; builder.Services.Add<ModuleName>Module(builder.Configuration.GetConnectionString("<ModuleName>")!); ``` --- ## 5. チェックリスト 新しいモジュールや機能を実装する際に確認してください。 - [ ] Domain 層にエンティティを定義したか - [ ] Application 層に DTO を定義したか - [ ] Application 層にリポジトリインターフェースを定義したか - [ ] Application 層に IUnitOfWork インターフェースを定義したか - [ ] Application 層に UseCase(インターフェース + 実装)を定義したか - [ ] Infrastructure 層に DbContext(Unit of Work)を定義したか - [ ] Infrastructure 層にリポジトリ実装を配置したか(DbContext を注入し、SaveChangesAsync はリポジトリで呼ばない) - [ ] UseCase で SaveChangesAsync を呼んで変更を永続化しているか - [ ] Infrastructure 層に DI 登録用の拡張メソッドを作成したか - [ ] Web 層は UseCase と DTO のみを参照しているか(Domain エンティティを直接参照していないか) - [ ] Program.cs に `Add<ModuleName>Module()` を追加したか - [ ] `dotnet build` が成功するか
Auf GitHub ansehen