Nhờ AI viết nguyên một tính năng trong một câu lệnh thường cho ra vài trăm dòng mã trông đầy đủ nhưng hỏng ở chỗ khó thấy; chia tính năng thành những lát nhỏ, mỗi lát có kết quả chạy thử được, thì bạn kiểm được từng bước và biết chính xác chỗ nào sai. Kích thước hợp lý của một lát là thứ bạn đọc hiểu hết trong vài phút và kiểm được bằng một hai thao tác.
Bài này hướng dẫn cách cắt, thứ tự giao các lát, mẫu câu lệnh cho lát đầu và các lát tiếp theo, và dấu hiệu cho thấy lát đang quá to. Ví dụ xuyên suốt là một tính năng giả định: cho khách của một tiệm sửa xe ở Cần Thơ đặt lịch hẹn qua trang web.
Vì sao một yêu cầu to cho ra mã khó kiểm
Khi nhận yêu cầu "làm chức năng đặt lịch hẹn gồm form, lưu cơ sở dữ liệu, gửi email xác nhận và trang quản trị", trợ lý phải ra hàng loạt quyết định cùng lúc: cấu trúc bảng, cách kiểm dữ liệu nhập, cách chống đặt trùng giờ, định dạng thư, phân quyền trang quản trị. Mỗi quyết định có thể hợp lý riêng lẻ nhưng không khớp với nhau hoặc không khớp với dự án.
Vấn đề lớn hơn nằm ở phía người kiểm. Đọc ba trăm dòng mới viết, phân tán qua năm tệp, là việc nặng; người ta thường đọc lướt, chạy thử đường đi chính thấy được rồi chấp nhận. Lỗi ở nhánh phụ — hai khách đặt cùng giờ, email không gửi được, ngày nghỉ lễ — nằm im cho tới khi khách thật gặp. Khi đó việc lần ngược xem lỗi nằm ở lớp nào cũng khó, vì mọi thứ được viết cùng lúc.
Chia nhỏ không làm trợ lý thông minh hơn, nhưng làm bạn kiểm tốt hơn. Mỗi lát nhỏ có một câu hỏi duy nhất: lát này đã đúng chưa. Nếu sai, phạm vi tìm lỗi chỉ là vài chục dòng vừa thêm.
Cắt theo lát dọc, không cắt theo tầng
Cắt theo tầng là gì. Làm hết cơ sở dữ liệu, rồi hết phần xử lý, rồi mới tới giao diện. Cách này nghe gọn nhưng tới cuối mới chạy thử được trọn vẹn, nên lỗi ghép nối dồn lại một lúc.
Cắt theo lát dọc là gì. Mỗi lát đi xuyên qua mọi tầng nhưng chỉ cho một trường hợp hẹp. Lát đầu của ví dụ đặt lịch: một form chỉ có tên và giờ hẹn, lưu vào một bảng tối giản, hiện lại danh sách lịch đã đặt. Chưa có email, chưa chống trùng, chưa có trang quản trị. Nhưng nó chạy được từ đầu tới cuối.
Lát tiếp theo thêm một hành vi. Lát hai thêm kiểm tra giờ trùng. Lát ba thêm trường số điện thoại và kiểm định dạng. Lát bốn gửi email xác nhận. Mỗi lát có một câu mô tả hành vi mới và một cách kiểm riêng.
Lợi ích khi dừng giữa chừng. Nếu dự án bị gọi đi làm việc khác sau lát ba, bạn vẫn có một chức năng chạy được, thiếu tính năng nhưng không hỏng. Cắt theo tầng mà dừng giữa chừng thì chỉ có một bảng dữ liệu không ai dùng.
Một bản chia lát cho ví dụ đặt lịch hẹn
Bảng sau là cách chia gợi ý cho tính năng đặt lịch của tiệm sửa xe, ví dụ giả định. Cột cuối là thứ bạn tự làm để kiểm, trước khi giao lát kế tiếp.
| Lát | Hành vi mới | Cách kiểm trước khi đi tiếp |
|---|---|---|
| 1 | Form tên và giờ hẹn, lưu bảng, hiện danh sách | Đặt hai lịch, tải lại trang thấy đủ hai dòng |
| 2 | Chặn đặt trùng khung giờ | Đặt hai lịch cùng giờ, lịch thứ hai bị từ chối với thông báo rõ |
| 3 | Thêm số điện thoại, kiểm định dạng | Nhập chuỗi chữ cái, nhập thiếu số, nhập đúng; xem phản hồi từng ca |
| 4 | Chặn ngày tiệm nghỉ và giờ ngoài ca | Chọn chủ nhật và chọn giờ khuya, cả hai bị từ chối |
| 5 | Gửi email xác nhận | Dùng hộp thư thử, kiểm tiêu đề, nội dung, và khi máy chủ thư lỗi thì lịch vẫn được lưu |
| 6 | Trang quản trị xem và huỷ lịch | Đăng nhập tài khoản thường không vào được; tài khoản quản trị huỷ được một lịch |
Thứ tự trong bảng không phải duy nhất đúng. Nguyên tắc là đưa phần có rủi ro sai cao, như chống trùng giờ, lên sớm, và để phần phụ thuộc dịch vụ ngoài, như gửi thư, sau khi lõi đã chắc.
Mẫu câu lệnh cho lát đầu tiên
Lát đầu cần nhiều bối cảnh nhất vì trợ lý chưa biết gì về dự án. Một mẫu dùng được, viết bằng tiếng Việt: "Dự án PHP 7.4, không dùng framework, kết nối MySQL qua PDO trong tệp db.php. Đang làm tính năng đặt lịch hẹn, sẽ làm nhiều bước. Bước này CHỈ làm: một trang dat-lich.php có form gồm tên khách và giờ hẹn; lưu vào bảng lich_hen với các cột id, ten_khach, gio_hen, tao_luc; hiện danh sách lịch đã đặt bên dưới form. CHƯA làm chống trùng, email hay phân quyền. Đưa câu tạo bảng và mã trang. Dùng câu truy vấn có tham số, không ghép chuỗi."
Ba điểm đáng chú ý trong mẫu. Thứ nhất, câu "sẽ làm nhiều bước" báo trước cho trợ lý để nó không tự nhồi thêm. Thứ hai, câu "CHƯA làm" liệt kê đích danh những gì để sau — nếu không nói, trợ lý hay tự thêm cho "đầy đủ". Thứ ba, yêu cầu truy vấn có tham số được đặt ngay từ lát đầu, vì sửa thói quen ghép chuỗi về sau tốn công hơn.
Khi nhận kết quả, đọc và chạy thử như cột cuối của bảng. Nếu ổn, lưu một bản (bằng git hoặc ít nhất sao một bản), rồi mới sang lát hai. Có điểm lưu sau mỗi lát nghĩa là lát sau hỏng thì bạn quay lại được, không phải gỡ từng dòng.
Mẫu câu lệnh cho các lát tiếp theo
Từ lát hai trở đi, câu lệnh ngắn hơn nhưng phải dán lại mã hiện tại của phần liên quan, vì trợ lý trong chatbot không nhớ chắc phiên bản cuối. Một khuôn gồm bốn dòng:
- Trạng thái hiện tại: "Đây là mã dat-lich.php đang chạy đúng" kèm mã. Với tác tử hoặc trợ lý trong trình soạn thảo, chỉ cần chỉ tên tệp.
- Hành vi mới duy nhất: "Thêm: nếu khung giờ đã có người đặt thì không lưu, hiện thông báo Giờ này đã kín, mời chọn giờ khác."
- Giữ nguyên: "Không đổi cấu trúc bảng, không đổi tên biến, không đụng phần hiện danh sách."
- Cách trả lời: "Chỉ đưa phần thay đổi kèm vài dòng xung quanh để biết chỗ chèn, và một câu giải thích cách kiểm trùng."
Dòng "giữ nguyên" thường bị bỏ, và đó là lý do trợ lý hay tiện tay "cải tiến" phần đang chạy tốt. Với lát chạm tới cơ sở dữ liệu như chống trùng, hỏi thêm một câu: trường hợp hai người bấm gửi cùng lúc thì cách này có còn chặn được không. Câu hỏi đó thường dẫn tới ràng buộc duy nhất ở mức bảng thay vì chỉ kiểm bằng mã.
Dấu hiệu lát đang quá to và cách cắt tiếp
Mô tả cần chữ "và" quá hai lần. "Thêm chống trùng và kiểm số điện thoại và gửi thư" là ba lát. Tách ra trước khi gửi.
Kết quả trả về chạm hơn hai tệp. Với ứng dụng nhỏ, một hành vi mới hiếm khi cần sửa nhiều tệp. Nếu trợ lý sửa năm tệp, hỏi nó vì sao, hoặc yêu cầu làm lại chỉ trong một hai tệp.
Bạn không tự nghĩ ra được cách kiểm. Nếu không biết thao tác nào chứng minh lát đã đúng, lát đó còn mơ hồ. Viết cách kiểm trước, rồi mới viết câu lệnh.
Đọc hết mã mới mất quá mười lăm phút. Con số này tuỳ người, nhưng khi bắt đầu thấy mỏi và đọc lướt, đó là lúc lỗi lọt qua. Cắt nhỏ thêm rẻ hơn đọc lướt.
Trợ lý tự hỏi lại quá nhiều. Nếu bạn đã dặn hỏi lại khi chưa rõ và nó hỏi tới bảy tám câu, có thể chính việc giao còn quá rộng. Trả lời xong hãy cân nhắc chia đôi.
Chia nhỏ khi dùng tác tử AI tự sửa nhiều tệp
Tác tử có thể tự đọc kho mã, chạy lệnh và sửa nhiều tệp, nên người dùng dễ bị cám dỗ giao cả tính năng một lần. Nguyên tắc chia lát vẫn giữ nguyên, chỉ khác ở cách giao: bạn có thể đưa cho tác tử toàn bộ danh sách lát, nhưng yêu cầu nó làm từng lát một, chạy kiểm thử sau mỗi lát, và dừng lại báo cáo trước khi sang lát kế.
Một câu giao việc cho tác tử theo hướng này: "Đọc kế hoạch sáu bước bên dưới. Làm bước 1, chạy bộ kiểm thử hiện có, rồi dừng và tóm tắt thay đổi. Không làm bước 2 khi chưa được đồng ý." Câu dừng lại ở cuối là phần quan trọng nhất. Thiếu nó, tác tử có thể chạy một mạch hết sáu bước và để lại một khối thay đổi lớn mà bạn phải rà một lần.
Làm trên một nhánh git riêng cho cả tính năng, mỗi lát một lần lưu thay đổi có thông điệp rõ, giúp bạn xem lại theo đúng thứ tự đã làm. Cách quản lý quyền và nhánh cho tác tử có bài riêng ở danh mục tác tử và làm việc nhóm của trang.
Ghi kế hoạch lát vào một tệp, đừng chỉ để trong cuộc trò chuyện
Danh sách lát nên nằm trong một tệp văn bản ngắn ngay trong dự án, ví dụ ke-hoach-dat-lich.md, mỗi lát một dòng gồm hành vi mới và cách kiểm. Làm xong lát nào, đánh dấu lát đó. Lý do rất thực tế: cuộc trò chuyện với chatbot không phải nơi lưu trữ đáng tin, bạn sẽ mở cuộc mới khi cuộc cũ quá dài, và đồng nghiệp không đọc được lịch sử trò chuyện của bạn.
Tệp kế hoạch còn là thứ bạn dán vào đầu mỗi cuộc trò chuyện mới, để trợ lý biết toàn cảnh mà vẫn chỉ làm đúng một lát. Với tác tử AI, chỉ cần bảo nó đọc tệp này và làm lát chưa đánh dấu đầu tiên. Khi giữa chừng phát hiện cần thêm một lát, ví dụ phải lưu múi giờ vì tiệm có chi nhánh ở nơi khác, bạn sửa tệp trước rồi mới giao việc, thay vì nhắc miệng một lần rồi quên.
Sau khi tính năng xong, tệp này có thể xoá hoặc giữ lại làm ghi chú lịch sử. Nhiều nhóm giữ lại vì nó cho người rà mã thấy thứ tự quyết định và lý do có từng phần.
Câu hỏi thường gặp
Chia nhỏ như vậy có làm chậm hơn so với giao một lần không?
Tính theo số câu lệnh thì nhiều hơn, nhưng thời gian tổng thường ít hơn vì gần như không có vòng sửa dài ở cuối. Khi giao một lần mà hỏng ở chỗ khó thấy, bạn có thể mất cả buổi để lần ra lỗi nằm ở tầng nào.
Có nên nhờ chính AI chia nhỏ tính năng giúp không?
Có thể, và thường ra một danh sách hợp lý. Nhưng hãy coi đó là bản nháp: kiểm xem mỗi lát có chạy được từ đầu tới cuối không, phần rủi ro có được đưa lên sớm không, và bỏ những lát trợ lý thêm vào mà bạn không cần.
Lát đầu tiên nên nhỏ tới mức nào?
Đủ nhỏ để chạy được trọn đường đi chính với một ca đơn giản nhất. Nếu lát đầu đã cần ba bảng và hai trang, nó còn quá to. Lát đầu thường xấu và thiếu, điều đó bình thường.
Khi một lát giữa chừng làm hỏng lát trước thì xử lý thế nào?
Quay về điểm lưu của lát trước, đưa lại cho trợ lý mã đang chạy đúng kèm mô tả rõ hành vi đã bị hỏng. Yêu cầu nó làm lại lát mới mà giữ nguyên hành vi cũ, và thêm một ca kiểm thử bảo vệ hành vi đó.
Dự án cá nhân rất nhỏ có cần chia lát không?
Với công cụ vài chục dòng, giao một lần là đủ. Nguyên tắc chia lát đáng dùng khi mã sẽ chạy thật cho người khác, chạm tới dữ liệu, hoặc vượt quá mức bạn đọc hết trong một lần ngồi.