© 2026 Laravel

SOLID - Dependency Inversion Principle (DIP) từ cơ bản đến Architect + áp dụng Laravel

3 phút đọc 3 lượt xem
#solid-dip-abstractions

#Dependency Inversion Principle (DIP)

High-level modules should not depend on low-level modules. Both should depend on abstractions.

DIP là nguyên lý quan trọng nhất trong SOLID ở level kiến trúc. Nếu hiểu sai hoặc áp dụng sai → dễ dẫn đến over-engineering.

#1. Bản chất của DIP (hiểu đúng từ gốc)

#1.1 High-level vs Low-level là gì?

  • High-level: business logic (OrderService)
  • Low-level: implementation (MySQL, Redis, Stripe)

👉 Sai lầm phổ biến: nghĩ high-level là “controller”

#1.2 Inversion nghĩa là gì?

Thông thường:

Service → MySQL

DIP:

Service → Interface ← MySQL

👉 Dependency bị đảo chiều

#2. Vấn đề khi không áp dụng DIP

#2.1 Tight coupling

class OrderService {
    private MySQLDatabase $db;
}

👉 Không thể đổi DB

#2.2 Khó test

  • Phải mock DB thật
  • Phải gọi external service

#2.3 Code fragile

  • Đổi Stripe → sửa toàn bộ service

#3. Kiến trúc đúng với DIP

#3.1 Dependency direction

Domain → Abstraction ← Infrastructure

#3.2 Ownership của abstraction

👉 Insight quan trọng:

Interface nên được define bởi high-level module

#4. Ví dụ PHP thuần (production mindset)

#Interface

interface PaymentGateway {
    public function charge(float $amount): string;
}

#Implementation

class StripeGateway implements PaymentGateway {
    public function charge(float $amount): string {
        return 'txn_123';
    }
}

#Service

class OrderService {
    public function __construct(private PaymentGateway $gateway) {}

    public function checkout(float $amount): string {
        return $this->gateway->charge($amount);
    }
}

#5. Áp dụng trong Laravel

#5.1 Service Container (DI container)

app()->bind(PaymentGateway::class, StripeGateway::class);

#5.2 Usage

class OrderService {
    public function __construct(private PaymentGateway $gateway) {}
}

👉 Laravel inject tự động

#5.3 Swap implementation

app()->bind(PaymentGateway::class, PaypalGateway::class);

👉 Không cần sửa code

#6. DIP vs Dependency Injection

DIP DI
Principle Technique
Design rule Implementation

👉 DI giúp implement DIP

#7. DIP vs Interface Overuse (bẫy phổ biến)

#Sai

interface UserServiceInterface {}
class UserService implements UserServiceInterface {}

👉 Không có multiple implementation → vô nghĩa

#Đúng

  • Khi có nhiều implementation
  • Khi cần test isolation
  • Khi có external dependency

#8. Advanced: DIP trong Clean Architecture

#8.1 Layer

  • Domain (Entity)
  • Application (Use case)
  • Interface (Controller)
  • Infrastructure (DB, API)

👉 Infrastructure phụ thuộc vào Domain

#8.2 Boundary

Application → Interface ← Infrastructure

#9. Real-world Case

#9.1 Payment system

  • Stripe
  • PayPal
  • VNPay

👉 DIP giúp plug-in dễ dàng

#9.2 Storage system

  • Local
  • S3
  • GCS

👉 chỉ cần đổi implementation

#10. Trade-off

#Ưu điểm

  • Flexible
  • Testable
  • Decoupled

#Nhược điểm

  • Boilerplate
  • Over-engineering

#11. Khi nào KHÔNG nên dùng DIP

  • Code đơn giản
  • Không có variation
  • YAGNI

#12. Tips & Tricks

  • Interface nên nhỏ (ISP)
  • Không expose implementation detail
  • Naming rõ ràng
  • Combine với Repository

#13. Interview Questions

DIP là gì?

Summary:

  • Depend on abstraction

Deep:

  • Tách business khỏi detail
DIP khác DI như thế nào?

Summary:

  • DIP là principle

Deep:

  • DI là tool implement
Khi nào không nên dùng DIP?

Summary:

  • Khi đơn giản

Deep:

  • Tránh over-engineering

#14. Kết luận

DIP là nền tảng của architecture hiện đại.

  • Dùng đúng → system flexible
  • Dùng sai → system phức tạp

👉 Senior biết dùng 👉 Architect biết dùng đúng chỗ