Commands

A command is used to dispatch domain model changes. It can be accepted or rejected depending on the domain model invariants.

Communication Guide Table

Triggered by Description
UI It is NOT common practice to send commands directly from the UI. Usually the UI communicates with web APIs
API APIs sit in the middle between UI and Server translating web requests into commands
External System It is NOT common practice to send commands directly from the External System. Usually the External System communicates with web APIs.
Port Ports are a simple way for an aggregate to communicate with other aggregates.
Saga Sagas are a simple way for an aggregate to do complex communication with other aggregates.

Best Practices

{% hint style="success" %} You can/should/must...

  • a command must be immutable
  • a command must clearly state a business intent with a name in imperative form
  • a command can be rejected due to domain validation, error or other reason
  • a command must update only one Aggregate {% endhint %}

Examples

public class DeactivateAccount : ICommand
{
    DeactivateAccount() {}
    public DeactivateAccount(AccountId id, Reason reason)
    {
        Id = id;
        Reason = reason;
    }

    public AccountId Id { get; private set; }
    public Reason ReasonToDeactivate { get; private set; }
}

[DataContract(Name = "24c59143-b95e-4fd6-8bbf-8d5efffe3185")]
public class AccountId : StringTenantId
{
    protected AccountId() { }
    public AccountId(string id, string tenant) : base(id, "account", tenant) { }
    public AccountId(IUrn urn) : base(urn, "account") { }
}

public class Reason : ValueObject<Reason>{...}