TROISINH
Ứng dụng nâng caoTự động hoá workflow chuyên sâu

Di chuyển Legacy Code với Claude Code: Strangler Fig Pattern

Cách dùng Claude Code tái cấu trúc hệ thống cũ bằng Strangler Fig Pattern — tự động phân tích code legacy, chuyển đổi từng phần và xóa code cũ an toàn không cần downtime.

Định nghĩa

Strangler Fig Pattern với Claude là phương pháp thay thế dần hệ thống legacy bằng cách triển khai một lớp định tuyến (facade) chuyển luồng dữ liệu từ code cũ sang code mới theo từng "lát cắt dọc" (vertical slice), sử dụng Claude Code như một "kỹ sư migration" tự động — với khả năng nạp toàn bộ codebase cũ vào context window để hiểu logic kinh doanh ẩn, sinh code hiện đại tương đương, và thực thi song song qua subagents để rút ngắn thời gian migration từ năm xuống còn tháng.

Giải thích chi tiết

Bài toán "Big Bang" và tại sao thất bại

Cách tiếp cận truyền thống — viết lại toàn bộ hệ thống rồi chuyển đổi một lần (big bang) — thường chết vì ba lý do:

  1. Yêu cầu ngầm (tacit knowledge): Code legacy chứa logic kinh doanh được "mã hóa" trong tên biến khó hiểu, comment cũ, và nhánh điều kiện không ai nhớ tại sao lại có.
  2. Context switching: Developer phải liên tục chuyển đổi giữa đọc hiểu code COBOL/Java cũ và viết React/Go mới, mất 15-30 phút mỗi lần để "load lại mental model".
  3. Risk concentration: Lỗi ở bất kỳ module nào trong hệ thống mới đều có thể sập toàn bộ sản phẩm.

Strangler Fig Pattern — lấy tên từ loài cây sung (fig) bao quanh cây chủ cho đến khi cây chủ chết đi — giải quyết bằng cách thay thế từng bộ phận đang sống (live migration).

Kiến trúc ba lớp trong migration

Facade/Router Layer Lớp mỏng ngồi giữa client và hệ thống cũ/mới, quyết định request đi đâu dựa trên feature flag hoặc URL pattern (ví dụ: /api/v2/payments → microservice mới, /api/v1/* → monolith cũ). Claude có thể tự sinh code adapter này bằng /plan mode, đảm bảo contract không đổi.

Vertical Slice Migration Thay vì chia theo layer (database → backend → frontend), ta chia theo năng lực kinh doanh (business capability): một slice là "tính năng thanh toán", một slice là "báo cáo tồn kho". Mỗi slice là đơn vị độc lập có database, API và UI riêng.

Claude Code xử lý slice qua subagents: mỗi agent chịu trách nhiệm một slice, chạy song song trong worktree riêng (worktrees), tránh "context pollution" — khi agent A đang debug database, agent B không bị ảnh hưởng bởi log lỗi của A.

Anti-Corruption Layer (ACL) Lớp dịch giữa model dữ liệu cũ và mới. Ví dụ: legacy dùng VARCHAR(20) cho số điện thoại, modern dùng PhoneNumber object. Claude tự sinh mapper class bằng cách đọc schema cũ qua MCP Database và so sánh với entity mới.

Vai trò của Claude Code trong vòng đời migration

Phase 1: Discovery & Comprehension (Khám phá) Dùng context window 200K tokens của Claude 3.5 Sonnet để nạp toàn bộ module legacy (ví dụ: 10.000 dòng COBOL hoặc Java Servlet) cùng lúc. Claude trace luồng dữ liệu, vẽ sơ đồ dependency, và trích xuất "tribal knowledge" thành tài liệu trong CLAUDE.md.

Phase 2: Shadow Mode (Song song) Chạy implementation mới song song với cũ, so sánh output nhưng không ảnh hưởng user. Claude viết differential tests và property-based tests để verify behavioral parity — đảm bảo "tái cấu trúc" không làm thay đổi kết quả kinh doanh.

Phase 3: Strangle & Cleanup (Siết và dọn dẹp) Khi một slice đã verify, Claude:

  1. Chuyển traffic qua facade (dùng hooks để auto-update routing table)
  2. Tìm và xóa "dead code" trong legacy bằng static analysis
  3. Tạo PR xóa code cũ qua lệnh /simplify hoặc /batch

Phase 4: State Persistence (Bộ nhớ migration) File CLAUDE.md trong thư mục .claude/ lưu trạng thái migration: slice nào đã xong, contract nào đang pending, và các quyết định kiến trúc (ví dụ: "giữ nguyên bảng legacy_orders trong 6 tháng trước khi archive"). Khi resume session sau reboot, Claude đọc lại file này để tiếp tục đúng chỗ.

Ví dụ thực tế

Chuyển đổi module thanh toán PHP sang Node.js

Tình huống: Một sàn TMĐT Việt Nam có monolith PHP (Laravel 5.2) từ 2016, muốn chuyển payment gateway sang NestJS để dùng gRPC với microservice ngân hàng.

Quy trình với Claude:

  1. Planning: claude /plan "Migrate PaymentController.php to NestJS microservice, keep same API contract"
  2. Subagent delegation:
    • Agent A: "Đọc PaymentController.php, Invoice.php, và database schema, viết lại thành TypeScript với strict typing"
    • Agent B: "Tạo Prisma schema tương đương với bảng transactions cũ"
    • Agent C: "Viết adapter chuyển từ Laravel Eloquent sang Prisma queries"
  3. Shadow testing: Claude viết script so sánh response JSON từ /api/v1/pay (cũ) và /api/v2/pay (mới) trong 24h, báo cáo mismatch qua Slack MCP.
  4. Cleanup: Sau khi verify, dùng /simplify để xóa PaymentController.php cũ và các helper functions liên quan trong app/Helpers/Payment.php.

Kết quả: Migration hoàn tất trong 2 tuần thay vì 3 tháng estimate ban đầu, zero downtime.

Từ COBOL mainframe sang Python cho ngân hàng

Tính huống: Hệ thống tính lãi suất tiết kiệm bằng COBOL trên mainframe IBM, cần chuyển sang Python để chạy trên cloud AWS.

Cách Claude xử lý:

  • Context ingestion: Nạp 5.000 dòng COBOL vào context, Claude nhận diện: "Đoạn này tính lãi kép theo quy tắc ngày công ty (365 ngày/năm) nhưng năm nhuận xử lý đặc biệt qua subroutine LEAP-YEAR-CHECK".
  • ACL creation: Sinh Python decorator @cobol_date_adapter để chuyển đổi giữa YYYYMMDD (COBOL) và datetime (Python).
  • Verification: Dùng /loop để chạy batch test: lấy 10.000 giao dịch lịch sử, tính lại bằng Python, so sánh với kết quả COBOL. Nếu mismatch, Claude tự debug và fix logic.

Dọn dẹp code legacy sau migration

Sau khi đã chuyển 80% traffic sang hệ thống mới, codebase cũ còn lại "zombie code" — không ai dùng nhưng sợ xóa. Claude chạy ở Auto Mode để:

  1. Static analysis tìm hàm không được import
  2. Tạo PR xóa từng file, kèm lý do: "Function calculateTaxV1 không được gọi bởi module nào sau commit a3f2d1e"
  3. Dùng CI/CD integration để chạy test suite trên từng PR xóa, đảm bảo không break gì.

Ứng dụng

Cho CTO/Technical Lead

  • Đánh giá technical debt bằng cách nhờ Claude phân tích codebase và đề xuất thứ tự ưu tiên migration dựa trên "heat map" — những module thay đổi nhiều nhất nên migrate trước để giảm maintenance cost.

Cho đội phát triển doanh nghiệp

  • Dùng Agent Teams để chạy song song 5-6 module cùng lúc, mỗi developer oversee một subagent, tăng velocity gấp 3-4 lần so với cách làm tuần tự.

Cho freelancer/consultant

  • Làm dự án modernization cho khách hàng có legacy Java/COBOL. Dùng Claude để generate boilerplate và test cases, bán kết quả là "migration package" hoàn chỉnh thay vì chỉ tư vấn.

Cho startup "vibe coding"

  • Khi pivot sản phẩm, thay vì sửa code cũ, dùng Strangler Fig để "bóp nghẹt" tính năng cũ — xây tính năng mới trong microservice riêng, dần dần chuyển user qua, cuối cùng xóa monolith cũ đi.

So sánh

Tiêu chíStrangler Fig với ClaudeBig Bang RewriteBranch by Abstraction
RiskThấp — lỗi chỉ ảnh hưởng 1 sliceCao — toàn bộ hệ thống có thể sậpTrung bình — abstraction layer phức tạp
Thời gianIncremental (từng phần)6-18 tháng "đóng cửa"3-6 tháng
Cost (với AI)Thấp — dùng subagents song songCao — phải hiểu toàn bộ hệ thống cùng lúcTrung bình — chi phí abstraction
DowntimeKhông có (zero downtime)Có thể cần downtime windowKhông có
Phù hợp khiHệ thống lớn, không thể dừng hoạt độngStartup nhỏ, code ít, cần pivot nhanhThay đổi underlying implementation (VD: đổi database)
Công cụ ClaudeSubagents, MCP, /loop cho shadow testingPlanning Mode để viết lại toàn bộHooks để switch implementation

Kết luận: Strangler Fig là lựa chọn an toàn cho hệ thống đang chạy production, đặc biệt khi kết hợp với Claude để tự động hóa phần "nhàm chán" (sinh boilerplate, viết test, cleanup code). Big Bang chỉ nên dùng khi codebase nhỏ hơn ~10.000 dòng và không có user active.

Bài viết liên quan

Cùng cụm (pro-automation)

Đọc tiếp

On this page