#Nguyên tắc cốt lõi
👉 High-level module không được phụ thuộc vào low-level module
👉 Cả hai phải phụ thuộc vào abstraction (interface)
#Bad Example (Anti-pattern)
class OrderService
{
private MySqlDatabase $db;
public function __construct()
{
$this->db = new MySqlDatabase();
}
}
Vấn đề
- Tight coupling
- Không test được
- Không thay đổi implementation được
#Good Example (Best Practice)
#1. Define abstraction
interface OrderRepository
{
public function save(Order $order): void;
}
#2. Inject dependency
class OrderService
{
public function __construct(private OrderRepository $repo) {}
}
#3. Implementation
class MySqlOrderRepository implements OrderRepository {}
#4. DI Container
$container->bind(OrderRepository::class, MySqlOrderRepository::class);
#Giải thích sâu (Senior mindset)
#1. Abstraction là gì?
👉 Interface định nghĩa hành vi, không quan tâm implementation
#2. Dependency direction
❌ Sai:
High-level → Low-level
✅ Đúng:
High-level → Interface ← Low-level
#3. DIP vs DI
- DIP: principle
- DI: technique
👉 DI giúp implement DIP
#4. Testability
👉 Mock dễ dàng
$mock = $this->createMock(OrderRepository::class);
#5. Clean Architecture
👉 Domain không phụ thuộc framework
#Tips & Tricks (Senior level)
#1. Không inject concrete class
#2. Interface đặt ở domain layer
#3. Không over-engineer
👉 Chỉ abstraction khi cần
#4. Laravel binding
$this->app->bind(Interface::class, Impl::class);
#5. Null object pattern
👉 Tránh if null trong code
#Interview Questions
1. DIP là gì?
Summary:
- Phụ thuộc abstraction
Deep: Tách business logic khỏi implementation
2. DIP khác DI như thế nào?
Summary:
- DIP là nguyên lý
- DI là cách implement
3. Tại sao DIP giúp test tốt hơn?
Summary:
- Có thể mock
Deep: Không phụ thuộc implementation thật
4. Khi nào không nên dùng DIP?
Summary:
- Khi đơn giản
Deep: Over-engineering
5. DIP có liên quan Clean Architecture không?
Summary:
- Có
Deep: Core rule của Clean Architecture
#Kết luận
👉 DIP giúp code:
- Dễ test
- Dễ maintain
- Dễ mở rộng
👉 Nhưng:
- Không lạm dụng abstraction