Overview
The application layer sits between the domain and infrastructure layers. It orchestrates the application’s business logic by coordinating domain entities and repository interfaces without knowing the implementation details. This layer implements the use cases of your application - the specific tasks users want to accomplish.Purpose of the Application Layer
The application layer:- Orchestrates domain logic and repository calls
- Implements use cases as handlers
- Separates commands (writes) from queries (reads) using CQRS
- Coordinates transactions and business workflows
- Remains framework-aware but infrastructure-agnostic
The application layer can depend on Angular’s dependency injection (
@Injectable) but should not directly depend on HTTP, routing, or UI components.CQRS Pattern: Commands vs Queries
CQRS (Command Query Responsibility Segregation) is a pattern that separates read operations from write operations.- Commands
- Queries
Commands represent actions that change state in the system.
- Create, Update, Delete operations
- Return the created/modified entity or void
- May trigger side effects (emails, events, etc.)
- Example:
RegisterUserCommand,UpdateProfileCommand
Benefits of CQRS
- Clear Intent: Immediately understand if an operation changes data
- Independent Scaling: Optimize reads and writes separately
- Security: Easier to apply different permissions to commands vs queries
- Testing: Simpler to test side effects in commands only
Commands
Commands are simple DTOs (Data Transfer Objects) that carry the data needed to perform an action.RegisterUserCommand
Location:~/workspace/source/src/app/usuario/application/commands/register-user.command.ts:1
register-user.command.ts
Username for the new account
Password for the new account
Commands are immutable (using
readonly) to prevent accidental modification during processing.Queries
Queries are also simple DTOs that carry parameters needed to retrieve data.LoginUserQuery
Location:~/workspace/source/src/app/usuario/application/queries/login-user.query.ts:1
login-user.query.ts
Username to authenticate
Password for authentication
Handlers: Use Case Implementation
Handlers contain the actual business logic for processing commands and queries. They depend on repository interfaces (from the domain layer) and coordinate the workflow.Command Handler Example
Location:~/workspace/source/src/app/usuario/application/usecases/commandHandlers/register-user.handler.ts:1
register-user.handler.ts
- @Injectable(): Makes this class available for Angular’s dependency injection
- Constructor Injection: Receives
UsuarioRepository(the interface, not the implementation) - handle() method: Processes the command and returns an Observable
- Delegates to repository: Doesn’t know how the user is registered, only that it should be
Query Handler Example
Location:~/workspace/source/src/app/usuario/application/usecases/queryHandlers/login-user.handler.ts:1
login-user.handler.ts
- Receives a query object
- Uses the repository interface
- Returns an Observable with the result
- Remains agnostic to implementation details
Observable Pattern (RxJS)
Both handlers returnObservable<Usuario>, which is part of the reactive programming paradigm using RxJS.
- Why Observables?
- Basic Usage
- With Async Pipe
Observables are used because:
- Asynchronous: Handle HTTP requests that take time
- Composable: Can be chained with operators (map, filter, catchError)
- Cancellable: Can cancel pending requests
- Angular Integration: Works seamlessly with Angular’s async pipe
Application Layer Structure
Handler Pattern Benefits
- Single Responsibility
- Testability
- Dependency Inversion
Each handler does one thing.
RegisterUserHandler only handles user registration, nothing else.Adding Business Logic to Handlers
In more complex scenarios, handlers would include validation, business rules, and coordination:Dependency Injection Setup
Handlers must be registered in an Angular module:The key line is
{ provide: UsuarioRepository, useClass: AuthService }, which tells Angular: “When someone asks for UsuarioRepository, give them an instance of AuthService.”Related Documentation
- Domain Layer - Understanding the repository interfaces handlers depend on
- Infrastructure Layer - See how repositories are implemented
- User Authentication Feature - Full authentication flow using these handlers
- Clean Architecture Overview - Understanding the full architecture
