Đến nội dung chính
Thư viện GKNơi khơi nguồn tò mò
Tiếng Việt

Mã quá thông minh thì khó sửa: Định luật Kernighan (Kernighan's Law)

Khi lập trình, có những lúc ta muốn viết một đoạn mã được rút gọn tài tình xuống một dòng, hoặc dùng một cách giải độc đáo mà người khác khó nghĩ ra. Bởi mã ngắn gọn và thông minh đem lại cảm giác như một bằng chứng về năng lực. Thế nhưng, nếu đoạn mã ấy phát sinh lỗi vài tháng sau, ngay cả người viết cũng thường phải nhìn rất lâu mới hiểu được ý nghĩa của nó. Quy tắc kinh nghiệm chỉ ra sắc sảo tình huống này chính là “Định luật Kernighan (Kernighan's Law)”.

Nói một cách đơn giản, định luật Kernighan là nguyên tắc cho rằng “việc tìm và sửa lỗi khó gấp đôi việc viết mã ban đầu, nên nếu viết mã theo cách thông minh nhất mà mình có thể nghĩ ra, bạn sẽ không thể tự sửa đoạn mã ấy”. Lời khuyên đặt sự rõ ràng lên trên sự thông minh này đến nay vẫn được giới lập trình viên trích dẫn rộng rãi.

Trong tài liệu này, chúng ta sẽ lần lượt tìm hiểu bối cảnh ra đời của định luật Kernighan, ý nghĩa của câu nói, những cách hiểu sai về định luật và cách vận dụng nó trong công việc thực tế.

Sơ đồ khái niệm về định luật Kernighan. Sơ đồ so sánh đoạn mã phức tạp có ý nghĩa khó nhận ra với đoạn mã được chia thành các bước đọc, tính toán và xuất kết quả, qua đó cho thấy việc kiểm tra các hoạt động trung gian giúp dễ khoanh vùng nguyên nhân gây lỗi. “Gấp đôi” là cách diễn đạt để nhấn mạnh, không phải giá trị đo lường.
Tên dễ đọc và các bước được phân chia rõ ràng giúp hiểu cách mã hoạt động và tìm lỗi. Đây là sơ đồ khái niệm nhằm hỗ trợ việc hiểu, còn “gấp đôi” không phải giá trị đo lường. Tham khảo: UCF COP-3402 Introduction, lời khuyên của Kernighan (https://www.cs.ucf.edu/~pappas/teaching/cop3402/spr2026/introduction.html).

Vì sao mã rõ ràng tồn tại lâu hơn mã thông minh

Một câu nói ra đời tại Bell Labs

Một lập trình viên mặc áo len ngồi trước thiết bị đầu cuối máy tính cũ trong phòng nghiên cứu vào thập niên 1970, bên cạnh là chồng giấy in liên tục và các bìa còng

Brian Kernighan, người viết câu nói này, là nhà khoa học máy tính người Canada từng làm việc tại Bell Labs ở Mỹ. Ông cùng Dennis Ritchie viết cuốn sách được xem là giáo trình kinh điển về ngôn ngữ C, đồng thời tham gia sâu vào quá trình phát triển Unix. Chữ K trong ba chữ cái của tên ngôn ngữ xử lý văn bản awk cũng được lấy từ họ của ông, và từ năm 2000, ông giảng dạy tại Đại học Princeton.

  • Nguồn (The Elements of Programming Style): Câu nói này xuất hiện trong cuốn “Các yếu tố của phong cách lập trình”, xuất bản năm 1974 cùng người đồng nghiệp P. J. Plauger.
  • Ấn bản sửa đổi (Second Edition): Ấn bản thứ 2 ra mắt năm 1978, và câu nói được nhắc đến nằm trong chương 2, bàn về công thức và biểu thức.
  • Động cơ biên soạn (Textbook Examples): Hai tác giả lần lượt viết lại những đoạn mã FORTRAN và PL/I sơ sài trong các giáo trình thời đó, từ đó rút ra các quy tắc viết mã tốt.

Tên sách được phỏng theo cuốn “Các yếu tố của văn phong (The Elements of Style)”, nổi tiếng là sách hướng dẫn viết văn. Tư tưởng xuyên suốt cuốn sách là mã tốt cũng giống như câu văn hay: phải rõ nghĩa và không có chi tiết thừa.


Ý nghĩa của câu nói “khó gấp đôi”

Một lập trình viên trẻ chống cằm suy nghĩ chăm chú để tìm lỗi trước máy tính xách tay vào ban đêm, trên bàn có một chú vịt cao su nhỏ và một tách trà

Nguyên văn gồm hai câu mang ý nghĩa: “Như mọi người đều biết, gỡ lỗi khó gấp đôi việc viết chương trình ban đầu. Vậy nếu đã viết chương trình một cách thông minh hết mức có thể, bạn định gỡ lỗi bằng cách nào?” Ở đây, gỡ lỗi (Debugging) là việc tìm và sửa các lỗi, hay bug, trong chương trình.

(1) Sửa khó hơn viết
Khi viết mã, ý định vẫn còn rõ ràng trong đầu, nhưng khi tìm lỗi, ta phải lần ngược lại để xác định ý định đó và hoạt động thực tế lệch nhau ở đâu. Việc này khó hơn vì sai sót ẩn ở đâu đó trong phần mà ta từng tin là đúng.

(2) Dùng hết sự thông minh thì không còn sức dự phòng
Với đoạn mã được viết bằng cách vận dụng năng lực đến giới hạn, bạn sẽ không đủ khả năng khi phải gỡ lỗi, một công việc khó gấp đôi. Ở đây, “gấp đôi” không phải con số được đo chính xác mà là cách diễn đạt nhấn mạnh sự chênh lệch lớn.

(3) Vì vậy, cần viết rõ ràng
Kết luận là hãy để dành một phần sự thông minh. Nếu ngay từ đầu bạn viết mã sao cho chỉ cần khoảng một nửa năng lực của mình là có thể hiểu được, thì khi có vấn đề về sau, phần sức lực còn lại vẫn đủ để tìm ra nguyên nhân. Trên thực tế, cuốn sách ấy còn đưa ra quy tắc “Hãy viết rõ ràng, đừng tỏ ra quá thông minh (Write clearly - don't be too clever)”.


Những cách hiểu sai về định luật

Một bên chiếc bàn trắng có các dây cáp nhiều màu rối vào nhau, còn bên kia là những dây cáp tương tự được bó gọn gàng, tạo sự tương phản giữa hỗn loạn và ngăn nắp

Vì ngắn gọn và dí dỏm, định luật Kernighan đôi khi cũng được hiểu khác với ý nghĩa ban đầu.

Có phải định luật khuyên không nên dùng kỹ thuật khó?

Định luật này không cấm bản thân các kỹ thuật khó. Dùng phương pháp tinh vi ở nơi thật sự cần thiết khác với việc cố tình viết rắc rối một bài toán vốn có thể giải đơn giản. Điều cần đề phòng là thói quen viết mã khó hiểu để khoe tài. Code Golf, trò chơi giảm số ký tự xuống mức thấp nhất có thể, là một hình thức rèn luyện trí óc thú vị, nhưng nếu đưa nguyên những đoạn mã ấy vào dịch vụ thực tế, người sửa sẽ phải vất vả.

Một cách diễn giải khác mang tên Đòn bẩy Kernighan

Lập trình viên người Thụy Điển Linus Åkesson đã diễn giải lại câu nói này thành “Đòn bẩy Kernighan (Kernighan's Lever)”. Theo cách hiểu đó, chính quá trình nỗ lực sửa đoạn mã vượt quá năng lực bản thân lại giúp năng lực phát triển. Tuy nhiên, điều này phù hợp trong bối cảnh học tập; với mã được nhiều người sử dụng lâu dài, lời khuyên ban đầu vẫn an toàn hơn.


Cách vận dụng định luật Kernighan trong công việc thực tế

Hai đồng nghiệp ngồi cạnh nhau trong văn phòng sáng sủa, cùng nhìn vào một màn hình lớn; một người chỉ vào màn hình, người kia gật đầu

Định luật Kernighan dẫn đến nhiều thói quen giúp mã dễ đọc hơn.

(1) Nghĩ đến người đọc trước tiên
Mã được viết một lần nhưng được đọc nhiều lần. Hãy đặt tên rõ ràng và tránh dồn quá nhiều việc vào một dòng để chính mình vài tháng sau, hoặc đồng nghiệp lần đầu đọc mã, có thể hiểu ngay.

(2) Làm cho đúng rồi mới làm cho nhanh
Cũng trong cuốn sách ấy có lời khuyên “Hãy làm cho đúng trước khi làm cho nhanh”. Việc biến đổi mã để cải thiện hiệu năng vẫn chưa muộn nếu được thực hiện sau khi xác định nơi thực sự chạy chậm.

(3) Chọn mã dễ sửa hơn mã ngắn
Ngày nay, công cụ trí tuệ nhân tạo có thể tạo ra mã phức tạp chỉ trong chớp mắt, nhưng trách nhiệm hiểu và sửa mã ấy vẫn thuộc về con người. Sẽ an toàn hơn nếu không chấp nhận nguyên xi đoạn mã mà bản thân không thể giải thích.

Trong một bài viết năm 1979, Kernighan cũng nói rằng công cụ gỡ lỗi hiệu quả nhất vẫn là suy nghĩ thận trọng và các câu lệnh xuất được đặt đúng chỗ. Điều đó có nghĩa là nền tảng để giải quyết vấn đề nằm ở mã đơn giản mà ta có thể bình tĩnh suy xét, hơn là ở những công cụ hào nhoáng.


Định luật Kernighan không khuyên bạn che giấu năng lực, mà chỉ ra nên dùng năng lực vào đâu. So với một dòng mã thông minh viết hôm nay, mười dòng mã bình thường mà ngày mai vẫn đọc trôi chảy rốt cuộc sẽ tiết kiệm được nhiều thời gian hơn.

Chỉ viết thông minh đến mức chính mình vẫn có thể suy luận và hiểu lại được: đó là bước đầu tiên để tạo ra mã có thể tồn tại lâu dài.