AILapTrinh.comAI Lập Trình
Đọc hiểu và cải tạo mã cũ

Refactor mã cũ với AI: tái cấu trúc từng bước nhỏ mà không làm hỏng hệ thống

Quy trình refactor mã cũ cùng trợ lý AI: chọn đúng chỗ, giữ kiểm thử làm lưng, giao AI từng phép biến đổi nhỏ, commit riêng từng bước, đo trước và sau.

Developer working late at a home desk in Hai Phong, desk lamp glow, laptop and second monitor both blank, sticky notes without writing on the wall, seen from behind

Refactor mã cũ với AI an toàn khi mỗi lần bạn chỉ giao một phép biến đổi nhỏ có tên rõ ràng, như tách hàm, đổi tên, gom điều kiện, rồi chạy kiểm thử và commit ngay trước khi sang bước kế tiếp. Giao cho AI câu "làm sạch tệp này" là cách nhanh nhất để nhận về một khối thay đổi hàng trăm dòng, trông gọn hơn hẳn, và không ai trả lời được nó có làm khác đi hành vi hay không.

Tái cấu trúc, theo nghĩa Martin Fowler dùng trong cuốn Refactoring xuất bản lần đầu năm 1999, là thay đổi cấu trúc bên trong của mã mà không thay đổi hành vi bên ngoài. Định nghĩa đó chính là thước đo khi làm việc với AI: mọi bước AI làm phải giữ nguyên hành vi, và bạn phải có cách chứng minh điều đó. Bài này đi qua quy trình, các phép biến đổi nên giao cho AI, và những thứ không nên giao.

Chọn chỗ refactor: không phải chỗ xấu nhất, mà là chỗ sắp phải sửa

Mã cũ nào cũng có chỗ xấu, và cám dỗ lớn nhất khi có AI là dọn hết một lượt. Đó là cách tạo rủi ro mà không tạo giá trị: vùng mã xấu nhưng chạy ổn suốt năm năm, không ai cần đụng tới, thì làm đẹp nó chỉ mang thêm khả năng hỏng. Nguyên tắc thực dụng là refactor chỗ bạn sắp phải thêm tính năng hoặc sửa lỗi. Dọn đường trước, rồi mới đi.

Kent Beck có một câu thường được trích dẫn theo tinh thần: trước hết làm cho thay đổi trở nên dễ, rồi mới thực hiện thay đổi dễ đó. Với AI, câu này thành một quy trình hai pha rõ ràng. Pha một là các bước refactor chuẩn bị, mỗi bước giữ nguyên hành vi. Pha hai là thay đổi tính năng thật, giờ đã nhỏ và dễ đọc. Hai pha nằm ở các commit tách biệt, để người rà mã nhìn pha một chỉ cần trả lời một câu: hành vi có giữ nguyên không.

Lịch sử git giúp chọn chỗ: tệp được sửa thường xuyên và hay có lỗi là ứng viên tốt. Bạn có thể đưa danh sách các tệp sửa nhiều nhất cùng danh sách phiếu lỗi gần đây cho AI, hỏi vùng nào xuất hiện ở cả hai. Kết quả là một danh sách ngắn, đủ để bàn với trưởng nhóm.

Điều kiện bắt buộc trước khi cho AI đụng vào mã

Có kiểm thử giữ lưng. Vùng sắp refactor phải có kiểm thử chạy được, dù là kiểm thử thô ghi lại hành vi hiện tại. Nếu chưa có, viết trước. Danh mục này có bài riêng về kiểm thử đặc tả hành vi cho mã cũ.

Nhánh git riêng và cây làm việc sạch. Bắt đầu từ trạng thái không có thay đổi dở dang, để mỗi bước AI làm đều xem được bằng lệnh so sánh khác biệt và quay lại được bằng một lệnh.

Chạy được trên máy cá nhân. Không refactor thứ bạn không chạy thử được. Nếu dự án chỉ chạy được trên máy chủ, việc đầu tiên là dựng môi trường chạy cục bộ.

Thống nhất định dạng mã trước. Nếu dự án chưa có công cụ định dạng tự động, chạy nó một lần trong commit riêng. Không thì mỗi bước refactor kéo theo hàng trăm dòng đổi khoảng trắng, che mất thay đổi thật.

Biết phạm vi được phép. Nói rõ với AI những tệp nào được sửa. Tác tử AI tự sửa nhiều tệp rất tiện nhưng cũng rất dễ lan rộng hơn bạn muốn.

Các phép biến đổi nên giao cho AI, từng cái một

Mỗi dòng dưới đây là một bước refactor có tên trong tài liệu kinh điển. Giao cho AI theo đúng tên, kèm phạm vi, thay vì mô tả mơ hồ "làm cho gọn".

Phép biến đổiVí dụ câu giao việcRủi ro cần kiểm
Tách hàmTách khối dòng 40 tới 75 của hàm tính phí thành hàm riêng, tên do bạn đề xuất, giữ nguyên hành viBiến dùng chung giữa khối tách và phần còn lại
Đổi tênĐổi tên biến tmp2 thành tên mô tả đúng ý nghĩa trong hàm nàyTên trùng với biến khác, tên được dùng qua chuỗi
Thay số ma thuật bằng hằngĐặt tên hằng cho các con số trong hàm, chưa đổi giá trịCùng một con số mang hai nghĩa khác nhau
Gom điều kiệnGom các điều kiện if lồng nhau thành hàm kiểm tra có tênThứ tự đánh giá và tác dụng phụ trong điều kiện
Thoát sớmĐổi các khối if lồng sâu thành kiểm tra và trả về sớmNhánh else bị bỏ quên
Tách tham sốGom năm tham số cùng loại thành một đối tượngMọi nơi gọi phải đổi theo, dễ sót

Bảng này có chủ ý bỏ ra ngoài những thay đổi lớn như "chuyển sang kiến trúc mới" hay "viết lại theo hướng đối tượng". Những việc đó không phải một bước refactor mà là một dự án, cần kế hoạch riêng và chia thành nhiều chục bước nhỏ như trên.

Một vòng refactor cùng AI

Mỗi vòng thường mất năm tới mười lăm phút. Một buổi làm việc có thể đi được mười vòng, và đó là tiến độ rất tốt với mã cũ.

  1. Chạy toàn bộ kiểm thử của vùng, xác nhận tất cả đang qua. Nếu có kiểm thử đang hỏng sẵn, ghi lại, không đổ lỗi cho bước refactor sau đó.
  2. Giao cho AI đúng một phép biến đổi, kèm câu: Chỉ thực hiện phép biến đổi này, không sửa gì khác, không đổi định dạng các dòng không liên quan. Nếu thấy cần đổi thêm, liệt kê ra thay vì tự làm.
  3. Đọc phần khác biệt. Thay đổi phải nhỏ và đúng với tên phép biến đổi. Có dòng nào lạ, như đổi một điều kiện, thêm xử lý ngoại lệ, sửa thông báo lỗi, thì từ chối toàn bộ và giao lại.
  4. Chạy kiểm thử. Qua thì commit với lời nhắn ghi đúng tên phép biến đổi. Hỏng thì quay về commit trước, không cố sửa tiếp trên nền đã hỏng.
  5. Ghi những gì AI liệt kê là "cần đổi thêm" vào danh sách việc, chọn bước kế tiếp từ đó.

Bước 3 là chỗ quyết định. AI có thói quen "tiện tay" cải thiện thêm, ví dụ sửa luôn một lỗi nó thấy, hay thêm kiểm tra giá trị rỗng. Những cải thiện đó có thể đúng, nhưng chúng thay đổi hành vi, nên phải đi ở commit riêng, có người duyệt riêng.

Ví dụ giả định: một hàm tính phí qua bốn vòng

Hình dung một hàm PHP tên tinh_phi dài khoảng một trăm hai mươi dòng, nhận bảy tham số, trong đó có ba khối if lồng nhau bốn tầng để xử lý phí theo vùng, theo khối lượng và theo loại khách. Bạn cần thêm một loại phí cho hàng cồng kềnh. Thay vì nhét thêm một tầng if thứ năm, bạn dành một buổi sáng cho bốn vòng refactor trước.

Vòng một: nhờ AI đặt tên hằng cho các con số rải rác trong hàm, như ngưỡng khối lượng và hệ số vùng xa. Kiểm thử qua, commit. Vòng hai: tách khối tính phí theo vùng thành hàm riêng, AI đề xuất tên phi_theo_vung, bạn đọc phần khác biệt thấy một biến tạm vẫn được dùng ở cuối hàm cũ, yêu cầu AI trả nó về qua giá trị trả về thay vì biến toàn cục. Kiểm thử qua, commit. Vòng ba: đổi các khối if lồng nhau của phần loại khách thành kiểm tra và trả về sớm. Lần đầu AI vô tình bỏ một nhánh else, một kiểm thử đỏ ngay, bạn quay lại và giao lại với câu dặn giữ đủ mọi nhánh. Vòng bốn: gom bảy tham số thành một mảng thông tin đơn hàng, đổi theo ở ba nơi gọi.

Sau bốn vòng, việc thêm phí hàng cồng kềnh chỉ còn là một hàm nhỏ mới cộng vào cuối, kèm hai kiểm thử. Người rà mã đọc bốn commit refactor, mỗi cái vài chục dòng, và một commit tính năng ngắn. So với một yêu cầu gộp mã duy nhất ba trăm dòng trộn lẫn mọi thứ, cách này dễ duyệt hơn hẳn và có lỗi thì biết ngay nằm ở bước nào.

Những thứ không nên giao cho AI refactor

Có những vùng mà một bước tưởng như vô hại vẫn đổi hành vi. Đoạn xử lý tiền và làm tròn số: đổi thứ tự phép tính hay đổi kiểu dữ liệu có thể làm lệch một đồng, đủ để đối soát cuối tháng không khớp. Đoạn xử lý ngày giờ và múi giờ: AI hay "chuẩn hoá" sang cách viết hiện đại mà bỏ qua giả định ngầm về múi giờ máy chủ. Đoạn xử lý đồng thời, khoá bản ghi, giao dịch cơ sở dữ liệu: đổi thứ tự hai câu lệnh có thể sinh lỗi chỉ xuất hiện khi có tải thật.

Với các vùng đó, AI vẫn hữu ích ở vai trò người đọc: giải thích, chỉ ra rủi ro, đề xuất kiểm thử. Còn tay sửa nên là người hiểu nghiệp vụ, đi chậm và có người rà thứ hai. Tương tự, đừng để AI refactor mã liên quan xác thực, phân quyền, mã hoá; một thay đổi "cho gọn" trong hàm kiểm quyền có thể mở cửa cho người không được phép. Danh mục an toàn mã nguồn của trang có bài riêng về rủi ro này.

Đo xem refactor có đáng công không

Refactor tốn thời gian, nên trưởng nhóm có quyền hỏi nó mang lại gì. Đừng đo bằng số dòng mã giảm, càng không đo bằng số dòng AI viết. Thước đo hợp lý hơn là những thứ cảm nhận được trong công việc: tính năng kế tiếp ở vùng đó mất bao lâu so với lần trước, số lỗi phát sinh từ vùng đó trong vài tháng sau, người mới cần bao lâu để sửa được một lỗi ở đó.

Một số chỉ số tự động có ích như độ phức tạp của hàm, độ dài hàm, số tham số; nhiều công cụ phân tích tĩnh tính được và AI giúp đọc báo cáo. Nhưng chúng chỉ là tín hiệu phụ. Một hàm dài nhưng đọc tuần tự rõ ràng có thể dễ bảo trì hơn năm hàm ngắn nhảy qua lại. Mục tiêu cuối cùng là người kế tiếp đọc hiểu và sửa được nhanh hơn, không phải con số đẹp hơn.

Câu hỏi thường gặp

Có nên để tác tử AI refactor cả dự án trong một lần không?

Không nên. Thay đổi lớn trong một lần không thể rà mã nghiêm túc, và khi có lỗi bạn không biết bước nào gây ra. Chia thành nhiều phép biến đổi nhỏ, mỗi phép một commit, chạy kiểm thử sau mỗi bước.

Mã cũ không có kiểm thử nào thì refactor thế nào?

Viết kiểm thử ghi lại hành vi hiện tại trước, kể cả hành vi trông như sai. Nếu thật sự không viết được, chỉ làm các phép biến đổi an toàn nhất như đổi tên biến cục bộ bằng chức năng đổi tên của trình soạn thảo, và kiểm tay kỹ.

Chức năng refactor của trình soạn thảo khác gì nhờ AI?

Chức năng có sẵn như đổi tên, tách hàm trong nhiều trình soạn thảo dựa trên phân tích cú pháp nên rất chính xác trong phạm vi nó hiểu. AI linh hoạt hơn, làm được việc không có nút sẵn, nhưng có thể sai. Có nút sẵn thì ưu tiên dùng nút.

Làm sao biết AI có lén thay đổi hành vi không?

Đọc kỹ phần khác biệt và chạy kiểm thử. Dấu hiệu đáng ngờ là điều kiện bị đổi, giá trị mặc định bị thêm, xử lý ngoại lệ mới xuất hiện, thông báo lỗi bị viết lại. Mỗi thứ đó là thay đổi hành vi, phải tách ra.

Refactor xong có cần người khác rà mã không?

Có, nhưng việc rà sẽ nhanh nếu mỗi commit chỉ chứa một phép biến đổi có tên. Người rà chỉ cần xác nhận thay đổi đúng như tên gọi và kiểm thử vẫn qua. Ghi rõ trong mô tả yêu cầu gộp mã rằng đây là refactor không đổi hành vi.

Khi nào nên dừng refactor?

Khi vùng đó đã đủ dễ để làm thay đổi bạn cần làm. Refactor là chuẩn bị cho việc thật, không phải mục tiêu riêng. Phần còn xấu nhưng không cản đường thì ghi vào danh sách, để dành cho lần sau có lý do đụng tới.

Cần tư vấn cụ thể cho trường hợp của bạn?

Chúng tôi sẽ liên hệ trong vòng 24 giờ.

Đăng ký tư vấn ngay

Bài viết liên quan

Bạn cần hỗ trợ thêm?

Để lại thông tin, chúng tôi sẽ liên hệ trong 24 giờ.

hoặc
Gọi ngay 0926 138 138