Methodology:
Domain-Driven Design

Ready to get started?

Check out the plugin on GitHub and start using it today.

Domain

Domain-Driven Design — 01

Domain

Core business logic

Entities · Value Objects · Aggregates

Entity Order #123

Value Object Money, Email

Aggregate Order → Items

↓ Click to read more

01 — Entities

Objects with identity. They can change state, but remain the same entity.

Bash
class Order {
  private int $id;        // Order #123
  private Status $status; // changes
  private Money $total;   // changes

  // But Order #123 is always #123
  public function getId(): int {
    return $this->id;
  }
}

02 — Value Objects

Objects without identity. If the values are the same — it is the same object.

Bash
class Money {
  public function __construct(
    private float $amount,
    private string $currency
  ) {}

  public function equals(Money $other): bool {
    return $this->amount === $other->amount
        && $this->currency === $other->currency;
  }
  // Money(100, 'USD') === Money(100, 'USD')
}

03 — Aggregates

A group of objects with one “root”. The outside world only works through the root.

Bash
// Order — Aggregate Root
class Order {
  /** @var OrderItem[] */
  private array $items = [];
  private Payment $payment;
  private Shipment $shipment;

  // Only Order manages items
  public function addItem(Product $p, int $qty): void {
    $this->items[] = new OrderItem($p, $qty);
    $this->recalculateTotal();
  }
}

Driven

Domain-Driven Design — 02

Driven

Model shapes the code

Business model drives the entire architecture

Model-First // domain leads

Business-Focused // not tech-focused

Value-Driven // solve real problems

↓ Click to read more

07 — Model-Driven

The domain model is the foundation. Technology follows the model, not vice versa.

Bash
// BAD:
wp_update_post($id, [...]);
update_user_meta($id, '_status', 1);

// GOOD:
$subscription->activate();
$order->complete();
$article->publish();

08 — Business Language

Code reflects business processes. Developers and stakeholders speak the same language.

Bash
// BAD:
processData($userId);
updateRecord($id, $data);

// GOOD:
activateSubscription($userId);
cancelOrder($orderId);
publishArticle($articleId);

09 — Framework Agnostic

WordPress is infrastructure. Domain logic stays independent and portable.

Bash
class SubscriptionRepository {
  public function save(Subscription $s): void {
    // WordPress is just storage
    update_post_meta(
      $s->getId(),
      '_subscription_data',
      $s->toArray()
    );
  }
}

Design

Domain-Driven Design — 03

Design

Strategic patterns

Different contexts — different models

Billing User → balance

Content User → role

Auth User → credentials

↓ Click to read more

04 — Bounded Context

DDD does not create “one model for everything”. In different contexts the same entity means different things.

Bash
// Billing Context
class User {
  private Balance $balance;
  private Plan $subscriptionPlan;
}

// Content Context
class User {
  private Role $role;
  private Permission[] $permissions;
}

// Auth Context
class User {
  private string $email;
  private string $passwordHash;
}

05 — When DDD is needed

DDD is justified where there is complex business logic. Not for landing pages and blogs.

Bash
// ✅ Use DDD:
- SaaS platforms
- Billing & subscriptions
- E-commerce systems
- Enterprise WordPress

// ❌ Skip DDD:
- Landing pages
- Simple blogs
- Small sites
- CRUD without logic

06 — DDD ≠ folders

DDD is a way of thinking, not a folder structure. Architecture emerges from the domain.

Bash
// NOT what makes DDD:
/Domain
/Application
/Infrastructure

// What makes DDD:
$subscription->activate();   // business language
$subscription->cancel();     // business rules
$subscription->renew();      // business process

// WordPress = infrastructure, not center