Tâm lý: đừng muốn rewrite ngay
Phản ứng tự nhiên: “Code này quá tệ, phải viết lại từ đầu!” SAI. Netscape rewrite Navigator từ đầu → mất 3 năm → mất thị phần → chết. Code cũ dù xấu nhưng ĐÃ CHẠY, đã xử lý 1000 edge case bạn không biết.
| Phản ứng | Kết quả |
|---|---|
| ❌ “Rewrite toàn bộ!” | Mất 6-12 tháng, miss deadline, tạo bug mới, mất business |
| ❌ “Tôi không đụng vào, sợ vỡ” | Code tiếp tục thối, càng ngày càng khó sửa |
| ✅ “Refactor dần, từng phần nhỏ” | Boy Scout Rule: mỗi lần đụng file → để sạch hơn lúc tìm thấy |
Strangler Fig Pattern: thay thế dần dần
// File: strangler.md
## Strangler Fig: thay legacy từ từ
1. Viết test cho code cũ (characterization test)
→ Không phải "test đúng/sai" mà "test hành vi hiện tại"
→ Nếu code cũ return 42, test phải assert 42
2. Viết code mới SONG SONG code cũ
→ Feature mới dùng code mới
→ Feature cũ vẫn chạy code cũ
3. Route traffic dần sang code mới
→ Feature flags: 10% → 50% → 100%
4. Khi code mới stable → xoá code cũ
## Ví dụ thực tế:
Shopify chuyển từ Ruby on Rails monolith → microservices
trong 10 NĂM, không phải 1 sprint.
Amazon chuyển từ monolith → services mất 7 năm.
Mẹo sống sót với legacy code
| Mẹo | Cách làm |
|---|---|
| Viết test trước khi sửa | Characterization test: ghi nhận hành vi hiện tại. Sửa code → test vẫn xanh = an toàn |
| Boy Scout Rule | Mỗi lần đụng file: rename 1 biến, extract 1 function, thêm 1 comment. Nhỏ nhưng tích luỹ |
| Seam = điểm nối | Tìm chỗ có thể “cắt” dependency: interface, function boundary. Inject mock → test được |
| Đọc Git log | git log —oneline file.js → hiểu lịch sử thay đổi, vì sao code viết như vậy |
| Hỏi đúng người | Tìm người đã ở lâu nhất: “File này có trap gì không?” — kinh nghiệm > đọc code |
Code cũ xấu vì: deadline gấp, team nhỏ, requirements thay đổi, best practice chưa tồn tại. Đừng blame người viết. Code bạn viết hôm nay, 3 năm sau ai đó cũng sẽ thấy “xấu”. Empathy > judgment.
❓ Cách tốt nhất để xử lý legacy codebase?
- Viết 3 characterization tests cho code cũ
- Áp dụng Boy Scout Rule trong 1 tuần
- Dùng git log + git blame để hiểu lịch sử code
- Không rewrite — strangler fig pattern