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.
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.
| Problem | Description |
|---|---|
| Concentration of responsibility | The controller handles "validation," "business logic," "persistence," and "notification" all at once |
| Hard to test | You cannot test it without a DB connection or sending email |
| Not reusable | If the same logic is needed elsewhere, it ends up copy-pasted |
| Hard to change | When 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.
| Problem | Description |
|---|---|
| Violation of the single responsibility principle | The model handles "domain logic," "persistence," and "integration with external services" |
| Eloquent dependency | The business logic strongly depends on Eloquent, making it hard to test and reuse |
| Bloat | Thousands 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
- Martin Fowler's explanation of DDD - a concise explanation of the DDD overview
- DDD Reference (Eric Evans' free PDF) - a reference that summarizes the key concepts of DDD