Debug và refactor code với AI
Tái hiện lỗi trạng thái dùng chung, viết regression test rồi refactor có giới hạn mà không đổi API.
Tổng quan
Dành cho người học muốn tự hoàn thành bài thực hành debug và refactor code với ai, với dữ liệu mẫu có thể kiểm tra.
- Cung cấp lỗi tái hiện tối thiểu cho trợ lý AI.
- Viết test trước khi sửa và giữ API ổn định.
- Tách sửa bug khỏi thay đổi phong cách.
Bạn sẽ hoàn thành: Hàm không còn chia sẻ list mặc định, cùng test bắt lỗi tái phát.
Chuẩn bị
- Python 3.10+ và một trợ lý coding; biết hàm và list.
Toàn bộ ví dụ chạy offline bằng thư viện chuẩn. Công cụ AI dùng để phân tích là tùy chọn, có thể có hạn mức hoặc phí theo tài khoản.
Thực hành từng bước
Bước 1. Tái hiện lỗi trước khi hỏi AI
Lưu code đầu tiên vào bug.py. Chạy nó và quan sát kết quả; không chỉnh ngay để giữ bằng chứng lỗi ban đầu. List mặc định được tạo lúc định nghĩa hàm, không được tạo mới cho mỗi lần gọi.
def add_task(task, tasks=[]):
tasks.append(task)
return tasks
print(add_task("A"))
print(add_task("B"))Bước 2. Đưa bằng chứng và yêu cầu phạm vi nhỏ
Hàm add_task(task, tasks=[]) giữ task cũ giữa hai lần gọi. Tôi muốn mỗi lần không truyền tasks tạo list mới; nếu truyền list thì vẫn thêm vào chính list đó. Viết một regression test thất bại trước khi sửa. Sau đó đề xuất thay đổi tối thiểu, giữ tên hàm và kiểu trả về. Không đổi cấu trúc project.Bước 3. Sửa và xác nhận hai hợp đồng
Thay nội dung bằng ví dụ hoàn chỉnh dưới. Assert đầu kiểm tra các lần gọi độc lập, assert sau giữ hành vi mutate list được truyền vào. Không dùng tasks = tasks or [] vì biểu thức đó làm mất danh tính một list rỗng do caller cung cấp.
def add_task(task, tasks=None):
if tasks is None:
tasks = []
tasks.append(task)
return tasks
assert add_task("A") == ["A"]
assert add_task("B") == ["B"]
existing = []
assert add_task("C", existing) is existing
assert existing == ["C"]
print("regression checks passed")Bước 4. Refactor có kiểm chứng
Sau khi test xanh, chỉ yêu cầu một thay đổi độc lập như thêm docstring mô tả mutate. Chạy lại test và đọc diff để chắc sửa văn bản không làm thay đổi logic. Đặt câu hỏi “trường hợp nào vẫn chưa được kiểm tra?” thay vì yêu cầu AI bảo đảm code không còn bug.
Kiểm tra kết quả
- Bản đầu tái hiện được lỗi; bản sửa chạy đủ bốn assert.
- Danh tính list tường minh được bảo toàn kể cả list rỗng.
Xử lý lỗi thường gặp
Test chỉ kiểm tra một lần gọi
Nguyên nhân: Không có chuỗi thao tác kích hoạt trạng thái dùng chung.
Cách xử lý: Gọi hàm hai lần không truyền tasks và so sánh từng kết quả.
AI đổi luôn API và nhiều module
Nguyên nhân: Yêu cầu refactor không có giới hạn.
Cách xử lý: Khôi phục riêng thay đổi chưa chấp nhận trong bản bài tập, nêu hợp đồng và yêu cầu diff nhỏ hơn.
Bài tập & mở rộng
- Chuyển assert thành unittest và thêm test list có sẵn phần tử.
- Thực hành lại với lỗi xử lý số âm trong bài Copilot.
Ví dụ chỉ minh họa mutable default và regression. Không có một test nhỏ nào chứng minh mọi đường chạy đúng; không dùng assert làm validation đầu vào production.
