# Architecture Understand the design principles, patterns, and extensibility of Svrnty.CQRS. ## Overview Svrnty.CQRS is built on solid architectural principles that make it: - ✅ **Metadata-driven** - Runtime discovery through compile-time registration - ✅ **Modular** - Clear separation between abstractions and implementations - ✅ **Extensible** - Multiple extension points for customization - ✅ **Convention-based** - Minimal configuration with sensible defaults - ✅ **Type-safe** - Compile-time type checking with runtime flexibility ## Architecture Topics ### [CQRS Pattern](cqrs-pattern.md) Deep dive into the Command Query Responsibility Segregation pattern: - Separation of reads and writes - Benefits and trade-offs - When to use CQRS - Common anti-patterns - Implementation patterns ### [Metadata Discovery](metadata-discovery.md) How Svrnty.CQRS uses metadata for automatic endpoint generation: - Metadata registration pattern - Discovery services (ICommandDiscovery, IQueryDiscovery) - Runtime enumeration - Endpoint generation process - Type safety with generics ### [Modular Solution Structure](modular-solution-structure.md) Best practices for organizing your solution into layers: - Multi-project solution structure - Api → CQRS → Domain → DAL dependencies - Separation of concerns - Project references - Real-world example ### [Dependency Injection](dependency-injection.md) DI patterns and handler registration: - Service registration patterns - Handler lifetime management - Scoped vs Transient vs Singleton - Constructor injection - Service resolution ### [Extensibility Points](extensibility-points.md) Framework extension mechanisms: - Custom authorization services - Query alteration services - Dynamic query interceptors - Custom attributes - Middleware integration ## Key Architectural Concepts ### 1. Abstractions vs Implementations Svrnty.CQRS separates interfaces from implementations: ``` Svrnty.CQRS.Abstractions (interfaces only) ↓ depends on Svrnty.CQRS (core implementation) ↓ depends on Svrnty.CQRS.MinimalApi (HTTP integration) Svrnty.CQRS.Grpc (gRPC integration) ``` **Benefits:** - Consumer projects reference only abstractions - Minimal dependencies - Easy to swap implementations - Clear contracts ### 2. Metadata-Driven Discovery Instead of scanning assemblies at runtime, Svrnty.CQRS uses explicit metadata: ```csharp // Registration creates metadata services.AddCommand(); // Metadata stored as singleton services.AddSingleton(new CommandMeta()); // Discovery queries metadata public class CommandDiscovery : ICommandDiscovery { private readonly IEnumerable _metas; public IEnumerable GetCommands() => _metas; } ``` **Benefits:** - No reflection-heavy assembly scanning - Faster startup - AOT-compatible - Explicit control ### 3. Convention Over Configuration Minimal configuration with smart defaults: ```csharp // Default naming convention CreateUserCommand → POST /api/command/createUser // Custom naming [CommandName("register")] CreateUserCommand → POST /api/command/register // Default route prefix /api/command/* and /api/query/* ``` ### 4. Type Safety Compile-time type safety with generic constraints: ```csharp // Type-safe registration services.AddCommand() where THandler : ICommandHandler; // Compile error if types don't match services.AddCommand(); // ❌ Compile error ``` ## Architectural Layers ### Typical Application Structure ``` ┌─────────────────────────────────────────┐ │ Presentation Layer │ │ (HTTP Endpoints, gRPC Services) │ │ - Svrnty.CQRS.MinimalApi │ │ - Svrnty.CQRS.Grpc │ └──────────────┬──────────────────────────┘ │ ┌──────────────▼──────────────────────────┐ │ Application Layer │ │ (Commands, Queries, Handlers) │ │ - Command/Query definitions │ │ - Handler implementations │ │ - Validators │ └──────────────┬──────────────────────────┘ │ ┌──────────────▼──────────────────────────┐ │ Domain Layer │ │ (Business logic, Entities, Events) │ │ - Domain models │ │ - Business rules │ │ - Domain events │ └──────────────┬──────────────────────────┘ │ ┌──────────────▼──────────────────────────┐ │ Infrastructure Layer │ │ (Data access, External services) │ │ - Repositories │ │ - Database context │ │ - External API clients │ └─────────────────────────────────────────┘ ``` ### Multi-Project Solution For larger applications, use multiple projects: ``` MySolution/ ├── MySolution.Api/ # HTTP/gRPC endpoints ├── MySolution.CQRS/ # Commands, queries, handlers ├── MySolution.Domain/ # Domain models, events ├── MySolution.Infrastructure/ # EF Core, repositories └── MySolution.Tests/ # Unit and integration tests ``` ## Design Patterns Used ### 1. Command Pattern Commands encapsulate requests as objects: ```csharp // Command (request object) public record CreateUserCommand { public string Name { get; init; } = string.Empty; } // Handler (executes the request) public class CreateUserCommandHandler : ICommandHandler { public Task HandleAsync(CreateUserCommand command, CancellationToken cancellationToken) { // Execute logic } } ``` ### 2. Mediator Pattern CQRS acts as a mediator between API and business logic: ``` Client → Endpoint → Handler → Business Logic ``` No direct dependencies between client and business logic. ### 3. Strategy Pattern Multiple implementations of same interface: ```csharp ICommandHandler → CreateUserCommandHandler → CreateUserWithEmailCommandHandler → CreateUserWithSSOCommandHandler ``` ### 4. Decorator Pattern Validators, authorization, logging wrap handlers: ``` Client → Validation → Authorization → Handler → Business Logic ``` ## Extensibility Architecture ### Extension Points 1. **Authorization** - `ICommandAuthorizationService` - `IQueryAuthorizationService` 2. **Query Alteration** - `IAlterQueryableService` 3. **Dynamic Query Interceptors** - `IDynamicQueryInterceptorProvider` 4. **Attributes** - `[CommandName]`, `[QueryName]` - `[IgnoreCommand]`, `[IgnoreQuery]` 5. **Middleware** - ASP.NET Core pipeline integration - Custom filters ## Performance Considerations ### Startup Performance - **Fast startup** - Metadata pattern avoids assembly scanning - **Minimal reflection** - Type information captured at registration - **AOT-friendly** - No runtime type discovery ### Runtime Performance - **Direct handler invocation** - No mediator overhead - **DI container resolution** - Standard ASP.NET Core performance - **Endpoint routing** - Uses built-in routing (HTTP) or gRPC runtime ### Memory Efficiency - **Singleton metadata** - One instance per command/query type - **Scoped handlers** - Created per request, disposed after - **No caching layer** - Direct execution ## Security Architecture ### Defense in Depth ``` 1. Network Layer (HTTPS, firewall) 2. Authentication (JWT, API keys) 3. Authorization (IAuthorizationService) 4. Validation (FluentValidation) 5. Business Rules (in handlers) 6. Data Access (parameterized queries) ``` ### Built-in Security Features - ✅ Validation before execution (FluentValidation) - ✅ Authorization services (per command/query) - ✅ Attribute-based endpoint control ([Ignore]) - ✅ Integration with ASP.NET Core auth ## What's Next? Explore specific architectural topics: - **[CQRS Pattern](cqrs-pattern.md)** - Deep dive into CQRS - **[Metadata Discovery](metadata-discovery.md)** - How discovery works - **[Modular Solution Structure](modular-solution-structure.md)** - Best practices for organization - **[Dependency Injection](dependency-injection.md)** - DI patterns - **[Extensibility Points](extensibility-points.md)** - Customization mechanisms ## See Also - [Getting Started](../getting-started/README.md) - Build your first application - [Best Practices](../best-practices/README.md) - Production-ready patterns - [Tutorials: Modular Solution](../tutorials/modular-solution/README.md) - Step-by-step guide