#Open/Closed Principle (OCP) - Abstraction (Chuyên sâu)
#1. Tư duy cốt lõi (Senior → Architect)
Open for Extension, Closed for Modification
Nhưng ở level cao hơn:
🔥 “Không chỉ tránh sửa code — mà phải thiết kế hệ thống cho việc mở rộng trở thành mặc định”
#2. OCP thực sự giải quyết vấn đề gì?
#Nếu không có OCP
- Mỗi feature mới → sửa code cũ
- High risk bug
- Regression liên tục
- Team conflict (merge conflict)
#Nếu có OCP
- Feature mới = thêm class mới
- Không đụng code cũ
- Dễ scale team
- Dễ maintain
#3. Sai lầm phổ biến khi áp dụng OCP
#3.1 if/else hell (classic anti-pattern)
if (type === 'A') {}
else if (type === 'B') {}
else if (type === 'C') {}
👉 Mỗi lần thêm type → sửa code
#3.2 Switch-based architecture
switch (strategy) {
case 'paypal':
case 'stripe':
}
👉 Không scalable
#3.3 Enum-driven logic
enum PaymentType { STRIPE, PAYPAL }
👉 Khi enum thay đổi → code everywhere break
#4. Cách thiết kế đúng (Production-grade)
#4.1 Abstraction-first design
interface PaymentMethod {
pay(amount: number): Promise<void>
}
#4.2 Polymorphism thay vì condition
class StripePayment implements PaymentMethod {}
class PaypalPayment implements PaymentMethod {}
#4.3 Registry pattern
class PaymentRegistry {
private methods = new Map<string, PaymentMethod>()
register(key: string, method: PaymentMethod) {
this.methods.set(key, method)
}
get(key: string) {
return this.methods.get(key)
}
}
👉 Extension = register thêm
#4.4 Plugin Architecture (rất quan trọng)
interface Plugin {
name: string
setup(): void
}
👉 Cho phép hệ thống mở rộng runtime
#5. OCP + DIP = Kiến trúc chuẩn
OCP luôn đi với DIP
class OrderService {
constructor(private payment: PaymentMethod) {}
}
👉 Không phụ thuộc implementation
#6. Case study thực tế (Laravel)
#Sai
if ($paymentType === 'stripe') {
// stripe logic
}
#Đúng
interface PaymentMethod {
public function pay(float $amount);
}
#7. So sánh kiến trúc
| Tiêu chí | Không OCP | Có OCP |
|---|---|---|
| Thêm feature | sửa code | thêm class |
| Risk | cao | thấp |
| Maintain | khó | dễ |
| Scale team | khó | tốt |
#8. Interview Questions (Senior → Staff)
#Q1: OCP khác gì DRY?
Answer:
- DRY → tránh duplicate
- OCP → tránh modify
#Q2: OCP vs Strategy Pattern?
Answer:
Strategy là cách implement OCP
#Q3: Khi nào KHÔNG nên dùng OCP?
Answer:
- YAGNI (chưa cần mở rộng)
- System nhỏ
#Q4: OCP liên quan gì đến Microservices?
Answer:
Service mới = extension
#Q5: OCP + Plugin system?
Answer:
Cho phép third-party extend system
#9. Advanced Tips
#Tip 1: Design for change points
👉 Xác định nơi sẽ thay đổi
#Tip 2: Avoid premature abstraction
👉 Chỉ abstract khi có ≥2 implementation
#Tip 3: Use configuration over condition
config.payment = 'stripe'
#Tip 4: Favor composition
#Tip 5: Use DI container
#10. Checklist áp dụng
- Có if/switch không?
- Có abstraction chưa?
- Có thể thêm feature mà không sửa code không?
- Có phụ thuộc concrete không?
#11. Tổng kết
🔥 OCP = nền tảng của scalable architecture
Nếu không có OCP:
- Code fragile
- Khó scale
Nếu có OCP:
- Code extensible
- System ổn định
👉 Rule cuối:
Nếu thêm feature mà phải sửa code cũ → bạn đang vi phạm OCP