Architecture principle:
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.

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.

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.

// 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.

// 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.

// 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.

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.

// 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.

// โœ… 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.

// 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