Clean Architecture không phải là đích đến — đó là kỷ luật bạn duy trì mỗi ngày
Tại sao hầu hết các hệ thống đều bắt đầu clean và kết thúc là một mớ hỗn độn
Và những nguyên tắc thực sự giúp bạn xây dựng phần mềm bền vững theo thời gian
Mở đầu: Nghịch lý của phần mềm "tốt"
Có một nghịch lý kỳ lạ trong ngành phần mềm: hầu hết mọi hệ thống đều được viết bởi những developer có năng lực, với ý định tốt, nhưng vẫn trở nên khó bảo trì sau một vài năm.
Không phải vì họ không biết Clean Architecture. Không phải vì họ không đọc sách của Uncle Bob.
Mà vì architecture không phải là thứ bạn thiết kế một lần rồi xong — nó là thứ bạn phải chủ động bảo vệ mỗi ngày.
Bài viết này không phải là tutorial. Không có diagram, không có giải thích layer.
Câu hỏi chính:
Tại sao architecture tốt lại khó duy trì?
Và điều gì thực sự giúp phần mềm bền vững theo thời gian?
1. Entropy là kẻ thù thực sự, không phải bad developer
Trong vật lý, entropy là xu hướng mọi hệ thống tiến về hỗn loạn.
Phần mềm cũng vậy.
Ban đầu:
- Code clean
- Boundaries rõ
- Dependency ít
Theo thời gian:
- “Tạm gọi DB trực tiếp, sau refactor”
- “Thêm flag cho nhanh”
- “Copy logic cho kịp deadline”
Mỗi quyết định đều hợp lý tại thời điểm đó.
Nhưng tích lũy lại → technical debt + architectural erosion.
“The only way to go fast is to go well.” — Robert C. Martin
2. Dependency là nguồn gốc của mọi vấn đề
Tất cả vấn đề maintainability đều quay về dependency:
- Khó test → phụ thuộc DB/external
- Khó thay đổi → coupling chặt
- Khó đọc → dependency chồng chéo
- Khó onboard → không có boundary rõ
Dependency Rule
Dependency chỉ đi từ ngoài vào trong
- Domain không biết database/framework/UI
- Nhưng ngược lại thì được
Ví dụ
❌ Sai
class OrderService {
async createOrder(data: CreateOrderDTO) {
return prisma.order.create({ data });
}
}
✅ Đúng
interface OrderRepository {
save(order: Order): Promise<void>;
}
class OrderService {
constructor(private orderRepo: OrderRepository) {}
async createOrder(command: CreateOrderCommand) {
const order = Order.create(command);
await this.orderRepo.save(order);
return order;
}
}
3. Domain Model — trái tim của hệ thống
❌ Anemic Domain Model
class Order {
id: string;
status: string;
}
Logic nằm ở service → bị phân tán.
✅ Rich Domain Model
class Order {
private status: OrderStatus;
confirm() {
if (this.status === 'cancelled') {
throw new Error('Cannot confirm');
}
this.status = 'confirmed';
}
}
Lợi ích
- Business rule = executable documentation
- Invariants luôn được bảo vệ
- Test dễ và meaningful
4. Anti-Corruption Layer (ACL)
Domain không nên bị “ô nhiễm” bởi external system.
Ví dụ
- Stripe:
amount= cents, status phức tạp - Domain: Money, PaymentStatus đơn giản
ACL sẽ:
- Map data external → domain
- Cô lập dependency
5. Tại sao architecture vẫn bị phá vỡ?
5.1 Pragmatism Trap
- “Dự án nhỏ thôi”
- “Tạm thời”
- “Chỉ dùng 1 lần”
→ Temporary trở thành permanent
5.2 Knowledge Gradient
Người thiết kế hiểu hệ thống.
Người sau không có context → phá rule.
Giải pháp: ADR
# ADR-007: Use Repository Pattern
## Context
Service đang gọi Prisma trực tiếp
## Decision
Introduce Repository interface
## Consequences
- Test dễ hơn
- Code phức tạp hơn chút
5.3 Consistency Illusion
Dev sẽ follow code gần nhất, không phải code đúng.
Consistency > Perfection
6. Cơ chế bảo vệ architecture
6.1 ESLint rules
'import/no-restricted-paths': [
'error',
{
zones: [
{
target: './domain',
from: './infrastructure'
}
]
}
]
6.2 Fitness Functions
it('Domain should not depend on infra', () => {
expect(illegalDeps).toEqual([]);
});
6.3 Test structure phản ánh architecture
src/
domain/
application/
infrastructure/
test/
unit/
integration/
e2e/
7. Khi nào KHÔNG nên dùng Clean Architecture
Phù hợp khi:
- Domain phức tạp
- System dài hạn
- Team lớn
- Có khả năng đổi infra
Overkill khi:
- CRUD đơn giản
- Prototype
- Team nhỏ
Bắt đầu simple, nhưng design để scale
Kết luận
Architecture là kỷ luật, không phải kiến thức
- Biết ≠ áp dụng
- Clean architecture phải được bảo vệ mỗi ngày
Entropy luôn thắng nếu bạn không chống lại nó
📌 Key Takeaways
- Dependency là gốc rễ → kiểm soát direction
- Rich domain model = đúng nơi cho business logic
- Enforcement > Convention
- ADR giữ lại “why”
- Consistency > Perfection
Tags:
#cleanarchitecture #systemdesign #ddd #backend #typescript
All rights reserved