Skip to main content

Why DDD — The Limits of the Fat Controller / Fat Model

The historical background of DDD

Domain-Driven Design (DDD) is a design approach proposed by Eric Evans in his 2003 book "Domain-Driven Design: Tackling Complexity in the Heart of Software." This book argues for the importance of putting the domain model at the center when designing software with complex business logic.

note

DDD is a design philosophy with more than 20 years of history, yet its essential value remains undiminished and is still widely adopted in modern software development.

The problems with traditional Laravel

Laravel's standard MVC architecture suits simple CRUD operations. However, as complex business logic increases, the following problems tend to arise.

A concrete example: the Fat Controller problem

// An example of a problematic controller
class OrderController extends Controller
{
public function store(Request $request)
{
// Validation
$validated = $request->validate([...]);

// Business logic is scattered across the controller
$order = new Order($validated);

if ($order->total > 10000) {
$order->discount = $order->total * 0.1; // Discount calculation
}

$order->save();

// Inventory check
foreach ($order->items as $item) {
$inventory = Inventory::find($item->product_id);
if ($inventory->stock < $item->quantity) {
throw new Exception('Insufficient stock');
}
$inventory->stock -= $item->quantity;
$inventory->save();
}

// Sending email
Mail::to($order->user)->send(new OrderConfirmed($order));

return response()->json($order);
}
}

This code has the following problems.

ProblemDescription
Concentration of responsibilityThe controller handles "validation," "business logic," "persistence," and "notification" all at once
Hard to testYou cannot test it without a DB connection or sending email
Not reusableIf the same logic is needed elsewhere, it ends up copy-pasted
Hard to changeWhen the discount rule changes, you have to modify the controller

The Fat Model problem

The approach of "slim down the controller and move the processing into the model" is also common, but it creates new problems.

// An example of a Fat Model
class Order extends Model
{
public function calculateDiscount()
{
if ($this->total > 10000) {
return $this->total * 0.1;
}
return 0;
}

public function checkInventory()
{
foreach ($this->items as $item) {
$inventory = Inventory::find($item->product_id);
if ($inventory->stock < $item->quantity) {
throw new Exception('Insufficient stock');
}
}
}

public function sendConfirmationEmail()
{
Mail::to($this->user)->send(new OrderConfirmed($this));
}

// And more order-related methods keep getting added...
}

This Fat Model approach also has the following problems.

ProblemDescription
Violation of the single responsibility principleThe model handles "domain logic," "persistence," and "integration with external services"
Eloquent dependencyThe business logic strongly depends on Eloquent, making it hard to test and reuse
BloatThousands of lines of code gather in a single model, reducing maintainability

The concrete downsides of scattered business logic

When business logic is scattered across controllers, models, services, helpers, and so on, the following serious problems arise.

1. It is hard to grasp the business rules

To find out "where is the order's discount rule written?", you have to read across multiple files.

2. The risk of missing a change

When a business rule changes, the risk of overlooking a spot that needs updating increases.

Change "10% off for 10,000 yen or more" → "15% off for 15,000 yen or more"

Spots to change:
✓ OrderController.php (updated)
✓ CartService.php (updated)
✗ CheckoutHelper.php (missed!)
✓ ReportGenerator.php (updated)

# One missed spot becomes a bug in production

3. It is hard to ensure test coverage

When the same business rule exists in multiple places, you have to write tests for every implementation.

4. Code duplication

The same business logic gets copy-pasted into multiple places, increasing maintenance cost.

The benefits of adopting DDD

Adopting DDD gives you the following benefits.

1. Clarifying business rules

You can understand how the business works just by reading the code.

// The DDD approach: business rules are collected in domain objects (*)
// * Domain objects are explained in detail in the next chapter
class Order
{
public function confirm(): void
{
if (!$this->status->canBeConfirmed()) {
throw new DomainException('This order cannot be confirmed');
}

if (empty($this->orderLines)) {
throw new DomainException('The order has no line items');
}

$this->status = OrderStatus::CONFIRMED;
}
}

2. Improved resilience to change

You can limit the scope affected by a business rule change, making safe changes possible.

3. Improved testability

Business logic becomes independent, so you can test domain logic even without a database.

// Testable without a DB
public function test_a_confirmed_order_can_be_cancelled(): void
{
$order = Order::create($orderId, $shippingAddress);
$order->addItem($lineId, $productId, 2, new Money(1000, 'JPY'));
$order->confirm();

$order->cancel();

$this->assertTrue($order->status()->isCancelled());
}

4. Improved communication across the team

Developers and business stakeholders can discuss using the same concepts and words.

Business stakeholder: "When confirming an order, I want it to error if the line items are empty"

Developer: "I'll add a check for whether the line items are empty to the Order.confirm() method"

# You can converse in the same words (the ubiquitous language)
# * The ubiquitous language is explained in detail in the next chapter

The essence of DDD

DDD is not "technology for technology's sake." It is a design philosophy for maximizing business value.

In the next chapter, we look at the basic concepts of DDD in detail.

Further reading

If you want to learn more about DDD, see the following resources.

Books

  • Eric Evans, "Domain-Driven Design: Tackling Complexity in the Heart of Software" (2003) - the original text of DDD
  • Vaughn Vernon, "Implementing Domain-Driven Design" - a practical DDD book rich in implementation examples

Online resources