# `DDD.Command`
[🔗](https://github.com/blackuprise/vicander/blob/v0.1.1/lib/ddd/use_cases/command.ex#L1)

A command is the input of one use case, and it carries its own handler.

The command declares its fields (validated on construction) and implements `execute/1`:
load aggregates through repositories, call domain operations, save. It holds no business
logic itself; the rules live in entities, aggregates and specifications.

## Usage

    defmodule MyApp.Commands.PlaceOrder do
      use DDD.Command

      command do
        field :customer_id, :string, required: true
        field :items,       :list,   required: true
        field :notes,       :string, default: nil
      end

      @impl DDD.Command
      def execute(%__MODULE__{customer_id: customer_id, items: items}) do
        with {:ok, order} <- MyApp.Order.place(%{customer_id: customer_id}),
             {:ok, order} <- MyApp.Order.add_items(order, items) do
          MyApp.Infrastructure.OrderRepository.save(order)
        end
      end
    end

    MyApp.Commands.PlaceOrder.call(%{customer_id: "c1", items: [...]})

## Running a command

  * `new/1` builds and validates the command: `{:ok, command}` or `{:error, %DDD.Error{}}`.
  * `call/1` takes a command struct or plain attrs (built with `new/1` first), runs
    `execute/1`, and returns its result. Any error comes back as a `DDD.Error` whose
    `context` has `:command` set to the command module.
  * `call!/1` is `call/1` that raises on failure.

## Transactions

`execute/1` runs in its own database transaction by default: `{:ok, _}` commits,
`{:error, _}` rolls back everything the handler did (every aggregate it saved, and their
outbox events), and an exception rolls back and propagates. The repositories' own
transactions join it.

    use DDD.Command                              # default: transaction on the configured repo
    use DDD.Command, repo: MyApp.Repo            # another repo
    use DDD.Command, transaction: false          # no transaction (e.g. in-memory repositories)

Validation in `new/1` happens before the transaction starts.

## Retrying version conflicts

Aggregates are saved with optimistic locking: a save that lost against a concurrent one fails
with `:stale_aggregate` (an infrastructure error). `retry_on_conflict: n` re-runs the whole
command, on freshly loaded data, up to `n` more times before giving up:

    use DDD.Command, retry_on_conflict: 3

A command called from inside an open transaction is never retried (the outer transaction is
already doomed), and neither is any other error.

## Telemetry

Every run is a `[:ddd, :command]` span; see `DDD.Telemetry`.

# `execute`

```elixir
@callback execute(command :: struct()) :: {:ok, any()} | {:error, any()}
```

# `command`
*macro* 

---

*Consult [api-reference.md](api-reference.md) for complete listing*
