Command

The Command encapsulates the intent to perform an action and carry the necessary data for that action.

A command is implemented a data transfer object with the name of an operation and the data required to perform that operation.

Plan Command

Payload

Name

The Name is used to name the Command and CommandHandler. It also sets the folder and infrastructure name for the Usecase.

For more details, see Naming.

Schema

The properties of the Command Payload are planned with the Codebricks Planner.

These properties of the Payload are Value Objects.

For more details, see Schema.

Value Sources

The Command Schema Property Value Sources define how each property is initialized.

For more details, see Data Flow.

Addtionally Command can use the following Metadata Value Sources:

  • Aggregate Id: uuid - Id of the aggregate of the processed event (Command Policy).
  • Aggregate Version: int - Version of the aggregate of the processed event (Command Policy).
  • Event Occurred At: Datetime - Occurred At Timestamp of the processed event (Command Policy).
  • Authorized UserId: uuid - Id of the authorized User contained in the Authorization Token (Command API).

Implement Command

Command Class

Commands are implemented in the application layer to validate information and transport them to the domain layer. They contain ValueObjects to ensure that information is validated by business rules.

The command file is located at: Task/src/useCases/write/AddTask/application/AddTaskCommand.ts

1import { TaskTitleValueObject } from "shared/domain/valueObjects/TaskTitleValueObject";
2import { TaskDescriptionValueObject } from "shared/domain/valueObjects/TaskDescriptionValueObject";
3import { AssigneeIdValueObject } from "shared/domain/valueObjects/AssigneeIdValueObject";
4
5export class AddTaskCommand {
6 constructor(readonly payload: AddTaskCommandPayload) {
7 }
8}
9
10export interface AddTaskCommandPayload {
11 title: TaskTitleValueObject;
12 description: TaskDescriptionValueObject;
13 assigneeId: AssigneeIdValueObject;
14}

Parameters and Properties

  • Payload: The command's payload contains the necessary data for the operation.
  • ValueObjects: Encapsulate and validate the primitive data types.

Command Handler Class

Commands are processed by their respective command handlers. The command handler is responsible for executing all application logic.

The command handler file is located at: Task/src/useCases/write/AddTask/application/AddTaskCommandHandler.ts

1import { OverwriteProtectionBody, NotFoundError, PreconditionFailedError, UuidGenerator } from "@codebricks/typebricks";
2import { TaskAggregate } from "shared/domain/aggregate/TaskAggregate";
3import { AddTaskCommand } from "./AddTaskCommand";
4import { TaskRepository } from "shared/infrastructure/persistence/aggregate/TaskRepository";
5import { TaskPublisherTrigger } from "shared/infrastructure/publishing/TaskPublisherTrigger";
6
7export class AddTaskCommandHandler {
8 constructor(readonly repository: TaskRepository = new TaskRepository(), readonly publisher: TaskPublisherTrigger = new TaskPublisherTrigger()) {
9 }
10
11 @OverwriteProtectionBody(false)
12 async handleAddTask(command: AddTaskCommand): Promise<TaskAggregate> {
13 const aggregate: TaskAggregate = new TaskAggregate(UuidGenerator.uuid());
14 await aggregate.addTask({
15 title: command.payload.title,
16 description: command.payload.description,
17 assigneeId: command.payload.assigneeId,
18 });
19 await this.repository.save(aggregate);
20 await this.publisher.trigger();
21
22 return aggregate;
23 }
24}

Key Concepts of Command Handler

  • Load or Create Aggregate: Load the aggregate from the database or create a new aggregate with a new UUID.
  • Connect Datasources: Query readmodels to give additional data and context to the aggregate.
  • Invoke Aggregate Method: Call the appropriate method on the aggregate.
  • Persist Aggregate: Save the aggregate and its recorded events to the repository.
  • Trigger Publisher: Trigger the event publisher to publish the event.

Best Practices

  • Validation: Ensure that command payloads are validated using value objects.
  • Immutability: Commands should be immutable once created.
  • Clear Naming: Use clear and descriptive names for commands to reflect their intent.

© 2024 Codebricks | All rights reserved.