Application Develop
project-spec -> architecture-design -> domain-develop -> application-develop -> adapter-develop -> observability-develop -> test-develop
Prerequisites
Section titled “Prerequisites”- Reads
domain/03-implementation-results.mdgenerated by thedomain-developskill to confirm the domain model (Aggregate, VO, Event, Specification). - If prerequisite documents are missing, the user is asked directly.
Background
Section titled “Background”When implementing a CQRS-based Application layer, Command/Query/EventHandler use cases repeat the same nested class structure (Request, Response, Validator, Usecase). The Apply merge pattern for Value Object validation, LINQ-based functional chaining, and guard() condition checks are patterns commonly applied across all use cases.
The /application-develop skill automates this repetition. When you convey use case requirements in natural language, it generates Commands, Queries, EventHandlers, and Validators matching Functorium framework patterns in 4 steps.
Skill Overview
Section titled “Skill Overview”4-Step Process
Section titled “4-Step Process”| Step | Task | Deliverable |
|---|---|---|
| 1 | Use case decomposition | Command/Query/Event identification, Request/Response design |
| 2 | Port identification | Required Port interfaces: Repository, Query Adapter, External API, etc. |
| 3 | Handler implementation | Apply pattern, LINQ chaining, guard condition checks applied |
| 4 | Implementation verification | dotnet build + dotnet test passing |
Supported Patterns
Section titled “Supported Patterns”| Pattern | Request Interface | Handler Interface | Description |
|---|---|---|---|
| Command | ICommandRequest<TSuccess> | ICommandUsecase<TCommand, TSuccess> | State change (write) |
| Query | IQueryRequest<TSuccess> | IQueryUsecase<TQuery, TSuccess> | Data retrieval (read) |
| Event | IDomainEvent | IDomainEventHandler<TEvent> | Domain event handling |
| Validation | AbstractValidator<Request> | — | FluentValidation rules |
Core API Patterns
Section titled “Core API Patterns”| Pattern | Usage |
|---|---|
| LINQ functional chaining | from x in repo.Method() select new Response(...) |
| Apply merge | (v1, v2, v3).Apply((a, b, c) => ...).As().ToFin() |
| guard condition check | from _ in guard(!exists, ApplicationError.For<T>(...)) |
| Execution flow | await usecase.Run().RunAsync() -> .ToFinResponse() |
| Application error | ApplicationError.For<TUsecase>(new AlreadyExists(), value, message) |
ApplyT vs Unwrap Selection Criteria
Section titled “ApplyT vs Unwrap Selection Criteria”There are two ways to merge Value Object validation results into a FinT chain. Choose based on the situation.
| Criterion | ApplyT Pattern | Unwrap (Manual Branch) Pattern |
|---|---|---|
| On VO validation failure | Accumulates errors and returns them all at once | Returns immediately at the first failure point |
| Number of VOs | Effective with 2 or more | When there’s 1 or sequential dependency |
| Code form | (v1, v2).Apply((a, b) => ...).As().ToFin() | if (createData.IsFail) return ...; |
| Use scenario | Create-type (multiple field simultaneous validation) | Update-type (single field change) |
ApplyT Pattern — Parallel validation, error accumulation:
var createData = (ProductName.Validate(request.Name), Money.Validate(request.Price)) .Apply((n, p) => Product.Create( ProductName.Create(n).ThrowIfFail(), Money.Create(p).ThrowIfFail())) .As() .ToFin();Unwrap Pattern — Sequential validation, immediate return:
var name = ProductName.Create(request.Name);if (name.IsFail) return name.Match(Succ: _ => throw new InvalidOperationException(), Fail: FinResponse.Fail<Response>);Basic Invocation
Section titled “Basic Invocation”/application-develop Create a product creation Command Usecase. Include Name, Price in the Request.Interactive Mode
Section titled “Interactive Mode”Invoking /application-develop without arguments starts the skill in interactive mode, collecting requirements through conversation.
Execution Flow
Section titled “Execution Flow”- Use case analysis — Shows Command/Query/Event identification results in a table
- User confirmation — Proceed to code generation after confirming the analysis results
- Code generation — Generates use cases with the nested class pattern
- Build/test verification — Runs
dotnet buildanddotnet testto confirm passing
Example 1: Beginner — Single Product Creation Command
Section titled “Example 1: Beginner — Single Product Creation Command”The most basic Command use case. Shows the full structure of the nested class pattern (Request, Response, Validator, Usecase) and how to merge Value Object validation with the Apply pattern.
Prompt
Section titled “Prompt”/application-develop Create a product creation Command Usecase. Include Name, Price in the Request.Expected Results
Section titled “Expected Results”| Deliverable | Type | Description |
|---|---|---|
| Command | CreateProductCommand | Nested class pattern (Request, Response, Validator, Usecase) |
| Request | Request(string Name, decimal Price) | ICommandRequest<Response> |
| Validator | Validator | FluentValidation + MustSatisfyValidation |
| Usecase | Usecase | ICommandUsecase<Request, Response>, LINQ chaining |
Key Snippets
Section titled “Key Snippets”Nested class pattern — Request, Response, Validator, Usecase cohesively in a single file:
public sealed class CreateProductCommand{ public sealed record Request(string Name, decimal Price) : ICommandRequest<Response>;
public sealed record Response(string ProductId, string Name, decimal Price, DateTime CreatedAt);
public sealed class Validator : AbstractValidator<Request> { public Validator() { RuleFor(x => x.Name).MustSatisfyValidation(ProductName.Validate); RuleFor(x => x.Price).MustSatisfyValidation(Money.Validate); } }
public sealed class Usecase(IProductRepository productRepository) : ICommandUsecase<Request, Response> { private readonly IProductRepository _productRepository = productRepository;
public async ValueTask<FinResponse<Response>> Handle(Request request, CancellationToken cancellationToken) { // 1. Value Object validation (Apply pattern) var createData = CreateProductData(request); if (createData.IsFail) { return createData.Match( Succ: _ => throw new InvalidOperationException(), Fail: error => FinResponse.Fail<Response>(error)); }
var product = (Product)createData;
// 2. LINQ functional chaining FinT<IO, Response> usecase = from created in _productRepository.Create(product) select new Response( created.Id.ToString(), created.Name, created.Price, created.CreatedAt);
Fin<Response> response = await usecase.Run().RunAsync(); return response.ToFinResponse(); }
private static Fin<Product> CreateProductData(Request request) { var name = ProductName.Validate(request.Name); var price = Money.Validate(request.Price);
return (name, price) .Apply((n, p) => Product.Create( ProductName.Create(n).ThrowIfFail(), Money.Create(p).ThrowIfFail())) .As() .ToFin(); } }}Example 2: Intermediate — Command + Query + Validator
Section titled “Example 2: Intermediate — Command + Query + Validator”Adds a Query use case and duplication validation to Example 1. Shows duplication checking with guard() in a Command, retrieval via LINQ chaining in a Query, and the dual validation strategy of FluentValidation and Value Objects.
Prompt
Section titled “Prompt”/application-develop Implement product CRUD. Create/Update Commands, ID lookup/search Queries, name duplication validation included.Expected Results
Section titled “Expected Results”| Deliverable | Type | Description |
|---|---|---|
| Command | CreateProductCommand | Create + name duplication check (guard) |
| Command | UpdateProductCommand | Update + Apply merge |
| Query | GetProductByIdQuery | ID-based single item retrieval |
| Query | SearchProductsQuery | Pagination/sort-supported search |
| Validator | Each Command’s Validator | FluentValidation + MustSatisfyValidation |
Key Snippets
Section titled “Key Snippets”Duplication check with guard — Declarative condition check within a LINQ chain:
using static Functorium.Applications.Errors.ApplicationErrorType;
FinT<IO, Response> usecase = from exists in _productRepository.Exists(new ProductNameUniqueSpec(productName)) from _ in guard(!exists, ApplicationError.For<CreateProductCommand>( new AlreadyExists(), request.Name, $"Product name already exists: '{request.Name}'")) from created in _productRepository.Create(product) select new Response(created.Id.ToString(), created.Name, created.Price, created.CreatedAt);Query use case — Retrieval through Port, DTO mapping via LINQ chaining:
public sealed class GetProductByIdQuery{ public sealed record Request(string ProductId) : IQueryRequest<Response>; public sealed record Response(string ProductId, string Name, decimal Price, DateTime CreatedAt);
public sealed class Usecase(IProductDetailQuery productDetailQuery) : IQueryUsecase<Request, Response> { private readonly IProductDetailQuery _productDetailQuery = productDetailQuery;
public async ValueTask<FinResponse<Response>> Handle(Request request, CancellationToken cancellationToken) { var productId = ProductId.Create(request.ProductId); FinT<IO, Response> usecase = from result in _productDetailQuery.GetById(productId) select new Response(result.ProductId, result.Name, result.Price, result.CreatedAt);
Fin<Response> response = await usecase.Run().RunAsync(); return response.ToFinResponse(); } }}Example 3: Advanced — EventHandler + Domain Service Integration
Section titled “Example 3: Advanced — EventHandler + Domain Service Integration”Adds domain event handlers and Domain Service to Example 2. Implements credit limit validation via Domain Service during order creation, inventory deduction through order created event handler, and inventory restoration on order cancellation — a cross-Aggregate flow.
Prompt
Section titled “Prompt”/application-develop Implement inventory deduction EventHandler on order creation, Domain Service validation when credit limit exceeded,and inventory restoration on order cancellation.Expected Results
Section titled “Expected Results”| Deliverable | Type | Description |
|---|---|---|
| Command | CreateOrderWithCreditCheckCommand | Order creation with Domain Service integration |
| EventHandler | OnOrderCreated | IDomainEventHandler<Order.CreatedEvent>, inventory deduction |
| EventHandler | OnOrderCancelled | IDomainEventHandler<Order.CancelledEvent>, inventory restoration |
| Domain Service | OrderCreditCheckService | Cross-Aggregate credit limit validation |
Key Snippets
Section titled “Key Snippets”Domain Service integration Command — Naturally composing Domain Service in a LINQ chain:
public sealed class Usecase( ICustomerRepository customerRepository, IOrderRepository orderRepository, IProductCatalog productCatalog) : ICommandUsecase<Request, Response>{ private readonly OrderCreditCheckService _creditCheckService = new();
public async ValueTask<FinResponse<Response>> Handle(Request request, CancellationToken cancellationToken) { // ... Value Object creation, OrderLine construction omitted ...
// Composing Domain Service in LINQ chain FinT<IO, Response> usecase = from customer in _customerRepository.GetById(customerId) from _ in _creditCheckService.ValidateCreditLimit(customer, newOrder.TotalAmount) from saved in _orderRepository.Create(newOrder) select new Response( saved.Id.ToString(), Seq(saved.OrderLines.Select(l => new OrderLineResponse(...))), saved.TotalAmount, saved.CreatedAt);
Fin<Response> response = await usecase.Run().RunAsync(); return response.ToFinResponse(); }}Domain event handler — IDomainEventHandler<TEvent> implementation, cross-Aggregate side effects:
public sealed class OnOrderCreated : IDomainEventHandler<Order.CreatedEvent>{ private readonly IInventoryRepository _inventoryRepository;
public OnOrderCreated(IInventoryRepository inventoryRepository) { _inventoryRepository = inventoryRepository; }
public async ValueTask Handle(Order.CreatedEvent notification, CancellationToken cancellationToken) { // Deduct inventory per order line foreach (var line in notification.OrderLines) { var inventory = await _inventoryRepository.GetByProductId(line.ProductId).Run().RunAsync(); if (inventory.IsSucc) { var inv = inventory.ThrowIfFail(); inv.Deduct(line.Quantity, DateTime.UtcNow); await _inventoryRepository.Update(inv).Run().RunAsync(); } } }}References
Section titled “References”Workflow
Section titled “Workflow”- Workflow — 7-step overall flow
- Domain Develop Skill — Previous step: Domain model implementation
- Adapter Develop Skill — Next step: Repository, Endpoint, DI implementation
Framework Guides
Section titled “Framework Guides”- Use Case and CQRS
- DTO Strategy
- Port Definition
- Error System
- Domain Events
- Domain Services
- Unit Testing
Related Skills
Section titled “Related Skills”- Domain Develop Skill — Generate domain building blocks: Aggregate, Value Object, Event, etc.
- Adapter Layer Develop Skill — Generate Repository, Query Adapter, Endpoint, DI registration
- Test Develop Skill — Generate unit/integration/architecture tests