Skip to content
Phero Lang
Menu

.ddd

Application design

Services, repositories and aggregate roots

Validated

No in-tree backend — the artifact is validated and committed, not consumed.

Sculptor-style designs: applications, modules, services, repositories, searches, entity state machines, and executable operation bodies.

Why it exists

What .ddd is for

The .mox domain says what the data is. The .ddd design says what the application makes of it: the application, its modules, the services and their use-case operations, and per-class design decisions — stereotype, flags, repository, state machine, search projection, delegation.

A design never declares classes or features; it references the classes the imported domains declare. Design references and operation signatures type-check against those domains, so a misspelt class or a mismatched parameter is a compile error rather than a mismatch that surfaces in generated code. Resolution is validation-only: the artifact keeps every name exactly as authored.

Vocabulary

What it models

The concepts .ddd declares, and what each one means to the compiler.

application
One per file, after the imports; base names the domain package when present.
module
A label grouping services and designs inside the application.
service
Application services with use-case operations; inject declares the dependencies, and an operation may carry capability, invokes, emits and transition clauses.
design
entity, value, dto and abstract, with flags such as scaffold, cache and auditable.
repository
A per-entity repository block: built-in operations are named, and a declared one may be protected.
search
An intent-only search projection — text fields with boosts, filters, sorts, ranking, pagination and document projections. The backend chooses the engine.
machine
An entity state machine, closed over its enum: every state is a literal of the machine’s enum type.
operation body
A declared service or repository operation may carry an executable statement body (let, guard, return) that the driver checks at compile time.

Source

A working example

Quoted from the example this page's artifact was compiled from — not a snippet written for the website.

Lines 12–36 of examples/support/support.ddd, reproduced byte for byte, read from the file at build time:

examples/support/support.ddd · lines 12–36
        service TicketService {
            inject TicketRepository;
            inject TicketSearch;
            Ticket raise(String title, boolean internal) emits TicketRaised;
            boolean raiseRefund(String ticketNo, int cents) capability RaiseRefund emits RefundRequested;
            boolean approveRefund(String ticketNo, int cents, User approver) capability ApproveRefund emits RefundApproved;
            Ticket[] listTickets();
            Ticket getTicket(String ticketNo);
            boolean claimTicket(String ticketNo, User helper);
            boolean refundTicket(String ticketNo, int cents);
            boolean markRead(String ticketNo) capability ReadTicket;
            boolean assign(String ticketNo, User assignee) capability UpdateTicket;
            boolean approve(String ticketNo) capability ResolveTicket;
            boolean reject(String ticketNo) capability UpdateTicket;
            boolean updateTicket(String ticketNo) capability UpdateTicket => TicketRepository {
                let ticket = self.findById(ticketNo) else error NotFound("Ticket", ticketNo);
                guard ticket.state != TicketState.Resolved else error Conflict("already resolved");
                ticket.internal = false;
                let saved = self.save(ticket);
                return true;
            }
            boolean resolveTicket(String ticketNo) capability ResolveTicket emits TicketResolved;
            protected close => TicketRepository.delete;
            findTickets => TicketSearch.search;
        }

One service: injected dependencies, operations that name capabilities and emissions, an operation with a checked statement body, and two delegations — `close` to the repository, `findTickets` to the search projection.

The whole file is CI-tested: pherolang check examples/ checks every surface in the tree, and the example harness compiles each one on every run. What you see above is the input to the artifact below.

Neighbours

How it relates to the other surfaces

The design is the hinge between the domain and everything built on it: it reads .mox, names .actor capabilities from its service operations, links an operation to a .dmn decision service (invokes, or inject decision on the module), and its operation emissions are checked against .evt names. .uc realizes its service operations, .cmmn executes them, and .deploy binds a component to one of its modules by path.

Read alongside

Commands

How to compile and validate

Three commands, one file. They run from the repository root against the example on this page.

bash
pherolang check examples/support/support.ddd
pherolang ir examples/support/support.ddd -o site/data/artifacts/ddd.json
pherolang artifact check site/data/artifacts/ddd.json

check parses, resolves, validates and type-checks the file and printsOK examples/support/support.ddd. ir writes the artifact and prints nothing on success. artifact check then validates the serialized JSON on its own — no model, no import resolution, no compiler — and prints OK site/data/artifacts/ddd.json.

Directories work too: pherolang check examples/ enters project mode and checks every supported surface under the tree, each file's imports resolving from the snapshot.

Artifact

What it produces

One versioned JSON artifact, emitted by the compiler and consumed by whatever reads this surface.

One DddModel: the application, and per module the services, designs, repositories, searches and machines.

The artifact is site/data/artifacts/ddd.json, and it is committed here exactly as the released pherolang binary emits it. Its top-level shape:

  • applicationname, base
  • modules2 entries

Jump to the compiled artifact

Provenance

formatVersion = 2
The compatibility gate. A reader accepts this number or refuses the file.
pheroVersion — not present
This standalone surface artifact is versioned on its ownformatVersion; only the domain model artifact carries the compiler-version stamp.
12,946 bytes
477 lines, two-space indented, in the file's own key order.

The compiled artifact

The first 43 of 477 lines, verbatim — the exact bytes pherolang ir writes, not a hand-written sample. The slice stops at a JSON boundary; the ellipsis marker is outside the JSON, and the full file is site/data/artifacts/ddd.json.

artifacts/ddd.json · lines 1–43
{
  "formatVersion": 2,
  "application": {
    "name": "SupportDesk",
    "base": "nz.example.support"
  },
  "modules": [
    {
      "name": "desk",
      "services": [
        {
          "name": "TicketService",
          "description": "Triages and resolves support tickets.",
          "operations": [
            {
              "name": "raise",
              "returnType": {
                "type": "class",
                "value": {
                  "package": "nz.example.support",
                  "name": "Ticket"
                }
              },
              "params": [
                {
                  "name": "title",
                  "type": {
                    "type": "primitive",
                    "value": "string"
                  }
                },
                {
                  "name": "internal",
                  "type": {
                    "type": "primitive",
                    "value": "boolean"
                  }
                }
              ],
              "emits": [
                "TicketRaised"
              ]
            },

… 434 more lines in site/data/artifacts/ddd.json

Regenerate it from the repository root — the second command validates the serialized bytes with no compiler in the loop:

bash
pherolang ir examples/support/support.ddd -o site/data/artifacts/ddd.json
pherolang artifact check site/data/artifacts/ddd.json

The whole data directory is regenerated by node scripts/sync-model.mjs (run from site/) with the released binary; CI fails on a one-byte difference.

Reference

Documentation

The normative reference for this surface, rendered from the repository's own documentation.