Brownfield với SDD (Legacy code)

Áp SDD vào hệ thống cũ đã tồn tại - đời thật của phần lớn team. SDD giúp được, nhưng KHÔNG phải kiểu viết spec đẹp rồi cho AI rewrite toàn bộ. Minh hoạ qua billing-engine: Spring Boot 1.5, ~320k dòng, calculate() dài 800 dòng với 17 nhánh if/else, dev gốc đã nghỉ.

Hai sai lầm điển hình

  1. Big Bang Rewrite: rewrite khi chưa có baseline. Hệ thống cũ có “tính năng ẩn” khách đang dùng.
  2. “Viết spec từ code rồi coi đó là sự thật”: AI đọc code cho biết code đang làm , không biết code làm đúng hay không. Bug sống 3 năm + khách đã quen workaround → spec sinh từ code biến bug thành feature.

Cả hai đều bỏ qua một bước: kiểm chứng lại với phía nghiệp vụ.

Chiến lược 5 bước

  1. Reverse-engineer Entity Model từ DB - DB schema là nơi rẻ nhất để bắt đầu (danh từ, quan hệ). Ngồi với người vận hành hỏi từng chỗ chưa rõ (flag_v2, flag_v3 nghĩa là gì).
  2. Reverse-engineer Use Case từ code + log + UI - phân loại: rõ / đoán được / bí ẩn (legacy-unverified: thêm analytics, không đụng 4 tuần, không request thì đề xuất deprecate).
  3. Kiểm chứng baseline với nghiệp vụ - workshop 90 phút/context, hỏi “cái này có đúng thực tế không? thiếu case nào? rule nào ‘đương nhiên’ nhưng không trong spec?“. (Phát hiện applyEnterpriseDiscount() giảm 10% từ 2021 mà không ai biết → viết UC-018.)
  4. Bọc Characterization Test quanh hành vi hiện tại - lấy 50 record production (anonymized), input/output hiện tại → lưới an toàn để refactor.
  5. Refactor với spec + test bảo vệ - tách calculate() 800 dòng thành các use case + strategy class; code cũ/mới chạy song song qua feature flag.

Vài nguyên tắc thực dụng

  • Đừng viết spec cho 100% codebase. Chia Module nóng ấm lạnh và đầu tư theo mức độ.
  • Bounded context trước, chi tiết sau.
  • Test trước refactor (refactor không test = đánh bạc).
  • Spec brownfield có quyền xấu (“TODO: kiểm chứng với nghiệp vụ”) - cần spec thật trước khi cần spec đẹp.

SDD trên legacy không phải để trả hết nợ, mà để dừng vay thêm.

Liên quan