К основному содержанию
скилл CX Codex

vertical-slice · codewithmukesh — скилл для Claude Code: что делает и как установить

Скилл помогает проектировать и писать .NET-приложения по принципам Vertical Slice Architecture вместо слоистой структуры. Пригодится при переносе логики в папки фич и настройке хэндлеров.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add codewithmukesh/dotnet-claude-kit --skill vertical-slice -a claude-code
Открыть на GitHub

Что делает vertical-slice

Скилл организует код фичи в один вертикальный срез вместо раскидывания по папкам Controllers, Services и Repositories. Вся логика отдельного эндпоинта — запрос, валидация через AbstractValidator, хэндлер и ответ — может лежать в одном файле. Это снижает связность между модулями, потому что фичи не обращаются друг к другу напрямую, а общий код уходит в Common/ или Shared/.

Внутри заложены три шаблона реализации. По умолчанию предлагается генератор Mediator на базе пакетов Mediator.Abstractions и Mediator.SourceGenerator без рефлексии с поддержкой Native AOT. Второй вариант опирается на конвенции библиотеки Wolverine со статическим методом Handle. Третий подход использует прямые классы без внешних библиотек через метод ExecuteAsync.

Если проект разрастается, скилл предлагает выносить границы модулей в отдельные библиотеки классов со своими DbContext. Отказ от сторонних библиотек в пользу чистых хэндлеров оправдан только в небольших проектах, где ручной контроль важнее готового пайплайна валидации.

Какие задачи решает

  • организовать структуру проекта .NET по папкам фич
  • собрать хэндлер эндпоинта на базе генератора Mediator
  • настроить обработку запросов через конвенции Wolverine
  • изолировать код фичи без использования сторонних библиотек посредников

Примеры запросов агенту

  • Помоги организовать эндпоинт CreateOrder по принципам Vertical Slice Architecture с валидацией через AbstractValidator.
  • Перепиши обработчик заказа на генератор Mediator с Native AOT для .NET.
  • Как структурировать папки Features и Common для нового API заказов без внешних библиотек?

Как установить vertical-slice

1Через Skills CLI (Vercel)

npx skills add codewithmukesh/dotnet-claude-kit --skill vertical-slice -a claude-code

2Вручную: положить файлы

~/.claude/skills/vertical-slice/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/vertical-slice/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Вопросы о vertical-slice

Как установить vertical-slice в Claude Code?

Выполните команду npx skills add codewithmukesh/dotnet-claude-kit --skill vertical-slice -a claude-code в терминале.

Что делает скилл vertical-slice?

Он задаёт правила вертикальной архитектуры для .NET: объединяет эндпоинты, хэндлеры и валидацию по отдельным фичам вместо деления на слои контроллеров и репозиториев.

Какие варианты хэндлеров поддерживает скилл?

В скилле описаны три варианта: source-generated Mediator для высокой скорости без рефлексии, конвенции Wolverine со статическими методами и прямые классы хэндлеров без сторонних зависимостей.

Исходный текст

SKILL.md · MIT
---
name: vertical-slice
description: >
  Vertical Slice Architecture (VSA) for .NET applications — one of several
  supported architectures in dotnet-claude-kit. Covers feature folders, endpoint
  grouping, and handler patterns for Mediator, Wolverine, and raw handler classes.
  Load this skill when the architecture-advisor recommends VSA, when working in
  an existing VSA codebase, when adding features to a feature-folder project,
  or when discussing vertical slice patterns, feature folders, or handler patterns.
---

# Vertical Slice Architecture (VSA)

## Core Principles

1. **Organize by feature, not by layer** — Each feature is a self-contained vertical slice containing its endpoint, handler, request/response types, and validation. No more jumping between Controllers/, Services/, Repositories/ folders.
2. **Minimize cross-feature coupling** — Features should not reference each other directly. Shared concerns go in a `Common/` or `Shared/` directory.
3. **One file per feature is fine** — A simple CRUD endpoint doesn't need 5 files spread across layers. Start with everything in one file, extract only when complexity demands it.
4. **The handler is the unit of work** — Each handler does one thing. No god-services with 20 methods.

## Patterns

### Feature Folder Structure

```
src/
  MyApp.Api/
    Features/
      Orders/
        CreateOrder.cs          # Request, Handler, Response, Endpoint — all in one file
        GetOrder.cs
        ListOrders.cs
        CancelOrder.cs
        Shared/
          OrderMapper.cs        # Shared within the Orders feature only
      Products/
        CreateProduct.cs
        GetProduct.cs
    Common/
      Behaviors/
        ValidationBehavior.cs   # Cross-cutting Mediator pipeline behavior
      Persistence/
        AppDbContext.cs
      Extensions/
        ServiceCollectionExtensions.cs
    Program.cs
```

### Pattern A: Mediator Handlers (Recommended Default)

Source-generated mediator — MIT licensed, no reflection, Native AOT compatible. Uses `IRequest<T>` / `IRequestHandler<TRequest, TResponse>` with pipeline behaviors. Near-identical API to MediatR but faster and free. Package: `Mediator.Abstractions` + `Mediator.SourceGenerator`.

```csharp
// Features/Orders/CreateOrder.cs

public static class CreateOrder
{
    public record Command(string CustomerId, List<OrderItemDto> Items) : IRequest<Result<OrderResponse>>;

    public record OrderItemDto(string ProductId, int Quantity);

    public record OrderResponse(Guid Id, decimal Total, DateTime CreatedAt);

    public class Validator : AbstractValidator<Command>
    {
        public Validator()
        {
            RuleFor(x => x.CustomerId).NotEmpty();
            RuleFor(x => x.Items).NotEmpty();
            RuleForEach(x => x.Items).ChildRules(item =>
            {
                item.RuleFor(x => x.ProductId).NotEmpty();
                item.RuleFor(x => x.Quantity).GreaterThan(0);
            });
        }
    }

    internal sealed class Handler(AppDbContext db, TimeProvider clock) : IRequestHandler<Command, Result<OrderResponse>>
    {
        public async ValueTask<Result<OrderResponse>> Handle(Command request, CancellationToken ct)
        {
            var order = Order.Create(request.CustomerId, request.Items, clock.GetUtcNow());
            db.Orders.Add(order);
            await db.SaveChangesAsync(ct);

            return Result.Success(new OrderResponse(order.Id, order.Total, order.CreatedAt));
        }
    }
}

// Registration in Program.cs or module DI
builder.Services.AddMediator();

// Features/Orders/OrderEndpoints.cs — auto-discovered via IEndpointGroup
public sealed class OrderEndpoints : IEndpointGroup
{
    public void Map(IEndpointRouteBuilder app)
    {
        var group = app.MapGroup("/api/orders").WithTags("Orders");

        group.MapPost("/", async (CreateOrder.Command command, ISender sender, CancellationToken ct) =>
        {
            var result = await sender.Send(command, ct);
            return result.IsSuccess
                ? TypedResults.Created($"/api/orders/{result.Value.Id}", result.Value)
                : result.ToProblemDetails();
        })
        .WithName("CreateOrder").Produces<CreateOrder.OrderResponse>(201)
        .ProducesValidationProblem()
        .AddEndpointFilter<ValidationFilter<CreateOrder.Command>>();
    }
}
```

### Pattern B: Wolverine Handlers

Convention-based — no interfaces to implement. Wolverine discovers handlers by method signature.

```csharp
// Features/Orders/CreateOrder.cs

public static class CreateOrder
{
    public record Command(string CustomerId, List<OrderItemDto> Items);

    public record OrderItemDto(string ProductId, int Quantity);

    public record OrderResponse(Guid Id, decimal Total, DateTime CreatedAt);

    // Wolverine discovers this by convention (static Handle method)
    public static async Task<Result<OrderResponse>> Handle(
        Command command,
        AppDbContext db,
        TimeProvider clock,
        CancellationToken ct)
    {
        var order = Order.Create(command.CustomerId, command.Items, clock.GetUtcNow());
        db.Orders.Add(order);
        await db.SaveChangesAsync(ct);
        return Result.Success(new OrderResponse(order.Id, order.Total, order.CreatedAt));
    }
}
```

### Pattern C: Raw Handler Classes (No Library)

Direct handler classes with no external dependency. Good for small projects or teams that want full control.

```csharp
// Features/Orders/CreateOrder.cs

public static class CreateOrder
{
    public record Command(string CustomerId, List<OrderItemDto> Items);

    public record OrderItemDto(string ProductId, int Quantity);

    public record OrderResponse(Guid Id, decimal Total, DateTime CreatedAt);

    internal class Handler(AppDbContext db, TimeProvider clock)
    {
        public async Task<Result<OrderResponse>> ExecuteAsync(Command command, CancellationToken ct)
        {
            var order = Order.Create(command.CustomerId, command.Items, clock.GetUtcNow());
            db.Orders.Add(order);
            await db.SaveChangesAsync(ct);

            return Result.Success(new OrderResponse(order.Id, order.Total, order.CreatedAt));
        }
    }
}

// Endpoint wiring — Result maps to HTTP response
group.MapPost("/", async (CreateOrder.Command command, CreateOrder.Handler handler, CancellationToken ct) =>
{
    var result = await handler.ExecuteAsync(command, ct);
    return result.IsSuccess
        ? TypedResults.Created($"/api/orders/{result.Value.Id}", result.Value)
        : result.ToProblemDetails();
});
```

### Adding Module Boundaries (Optional)

For larger applications that grow beyond a single project, introduce module boundaries. Each module is a separate class library with its own features and DbContext.

```
src/
  MyApp.Api/                      # Host — wires modules together
    Program.cs
    Modules/
      ModuleExtensions.cs         # app.MapOrderModule(), app.MapCatalogModule()
  MyApp.Orders/                   # Module — own features, own DbContext
    Features/
      CreateOrder.cs
    Persistence/
      OrdersDbContext.cs
    OrdersModule.cs               # IServiceCollection + IEndpointRouteBuilder extensions
  MyApp.Catalog/                  # Module
    Features/
      CreateProduct.cs
    Persistence/
      CatalogDbContext.cs
    CatalogModule.cs
```

Modules communicate via:
- **Integration events** (preferred) — async, decoupled via Wolverine or MassTransit
- **Shared contracts** — a `MyApp.Contracts` project with DTOs/interfaces (use sparingly)

### Shared Concerns

Cross-cutting concerns live outside feature folders:

```csharp
// Common/Behaviors/ValidationBehavior.cs (Mediator pipeline)
public sealed class ValidationBehavior<TRequest, TResponse>(IEnumerable<IValidator<TRequest>> validators)
    : IPipelineBehavior<TRequest, TResponse>
    where TRequest : IMessage
{
    public async ValueTask<TResponse> Handle(
        TRequest request,
        MessageHandlerDelegate<TRequest, TResponse> next,
        CancellationToken ct)
    {
        var context = new ValidationContext<TRequest>(request);
        var failures = validators
            .Select(v => v.Validate(context))
            .SelectMany(r => r.Errors)
            .Where(f => f is not null)
            .ToList();

        if (failures.Count > 0)
            throw new ValidationException(failures);

        return await next(request, ct);
    }
}
```

## Anti-patterns

### Don't Create Layered Abstractions Within a Slice

```csharp
// BAD — a feature folder with its own service layer and repository
Features/
  Orders/
    CreateOrder.cs
    IOrderService.cs         # unnecessary abstraction
    OrderService.cs          # unnecessary abstraction
    IOrderRepository.cs      # unnecessary abstraction
    OrderRepository.cs       # unnecessary abstraction

// GOOD — handler talks directly to DbContext
Features/
  Orders/
    CreateOrder.cs           # handler uses AppDbContext directly
```

### Don't Cross-reference Features Directly

```csharp
// BAD — CreateOrder directly calls GetProduct handler
var product = await _getProductHandler.Handle(new GetProduct.Query(productId));

// GOOD — query the database directly or use a shared read model
var product = await db.Products.FindAsync(productId, ct);
```

### Don't Put Everything in One God Feature File

```csharp
// BAD — 500-line file with CRUD + business logic + mapping
public static class Orders
{
    // Create, Read, Update, Delete, Cancel, Refund, Export...
}

// GOOD — one file per operation
Features/Orders/CreateOrder.cs
Features/Orders/GetOrder.cs
Features/Orders/CancelOrder.cs
```

## Decision Guide

| Scenario | Recommendation |
|----------|---------------|
| New project (default) | Pattern A — Mediator (source-generated, MIT, fast) |
| Need mediator + messaging in one lib | Pattern B — Wolverine (also handles events/queues) |
| Want full control, no dependencies | Pattern C — Raw handler classes |
| Existing MediatR codebase with license | Keep MediatR if licensed; otherwise migrate to Mediator (near-identical API) |
| Monolith growing complex | Add module boundaries, keep VSA within each module |
| Simple CRUD feature | Single file: request + handler + endpoint |
| Complex feature (saga, events) | Multiple files in feature folder, still colocated |
| Sharing logic between features | Extract to `Common/` — not to another feature |

© codewithmukesh · MIT · codewithmukesh/dotnet-claude-kit

Похожие скиллы

Всё по теме «Бэкенд и API» →

Сначала — vertical-slice от других авторов.

vertical-slice Donchitos Собирает вертикальный срез игры до старта продакшена: один полный цикл от старта до развязки, чтобы проверить, реально ли это сделать в срок. CX Codex +1 388установок dotnet Mindrally Задаёт агенту правила C#, ASP.NET Core и Entity Framework Core: структура проекта, async/await, DI, кэш, тесты. CX Codex +1 724установок api-design Aaronontheweb Скилл для проектирования публичных API по принципу «только расширять»: помогает не ломать совместимость при выпуске новых версий. CX Codex +1 660установок dotnet-backend-patterns Seth Hobson Скилл для разработки на C# и .NET: паттерны асинхронного кода, внедрение зависимостей, Entity Framework Core, кэширование и тестирование. Нужен, если вы пишете backend API, MCP-серверы или рецензируете код на C#. CX Codex 19 076установок api-breaking-change-detector официальный github Сверяет контроллеры и DTO на C# с клиентами на TypeScript или JavaScript прямо по исходному коду. Находит несовпадения контрактов API перед коммитом или релизом. 23установок dotnet-design-pattern-review официальный github Проверяет выбранный C#/.NET-код на применение паттернов проектирования и предлагает правки без изменения файлов. Подходит для ревью архитектуры проекта. 11 609установок analyzing-dotnet-performance dotnet Ищет около 50 антипаттернов производительности в коде на C# и .NET — от лишних аллокаций в строках до блокировок в async. Пригодится при аудите горячих путей перед релизом. CX Codex +1 4 900установок

Из того же набора46

error-handling Задаёт стратегию обработки ошибок в .NET 10: Result, ProblemDetails, валидация и глобальный перехват исключений. Нужен при проектировании контрактов API. CX Codex +1 2 800установок architecture-advisor Задаёт вопросы про домен, команду и срок жизни системы, а потом советует архитектуру для .NET-проекта. Пригодится до того, как разложить решение по папкам. CX Codex +1 2 800установок docker Скилл настраивает контейнеризацию приложений на .NET 10: многоэтапную сборку, запуск под непривилегированным пользователем и проверку работоспособности. CX Codex +1 2 900установок serilog Скилл помогает настроить структурированное логирование Serilog в приложении .NET 10: уровни, приёмники, свойства событий и журналы HTTP-запросов. CX Codex +1 2 900установок modern-csharp Подсказывает агенту синтаксис C# 14: первичные конструкторы, коллекционные выражения, ключевое слово field, блоки расширений. Пригодится, когда пишете новый код на C# или чистите старый. CX Codex +1 2 900установок outdated Собирает отчёт о здоровье зависимостей .NET: устаревшие NuGet-пакеты, уязвимые версии и ловушки с коммерческими лицензиями. CX Codex +1 2 800установок arch-check Сверяет кодовую базу с заявленной архитектурой: направление зависимостей, нарушения слоёв, утечки между модулями и циклы. Пригодится перед релизом или после крупной фичи. CX Codex +1 2 800установок migrate Скилл ведёт разработчика через миграции схемы EF Core, смену версии .NET и обновление NuGet. На каждом шаге он готовит план отката и запускает тесты. CX Codex +1 2 800установок

Спонсоры проекта

Компании, которые помогают держать аналитику открытой