Âm 2.000 dòng mã
(folklore.org)- Đầu năm 1982, nhóm phần mềm Lisa chịu áp lực phải phát hành trong vòng 6 tháng nên định đo tiến độ bằng số dòng mã hàng tuần của từng kỹ sư
- Bill Atkinson cho rằng số dòng mã không phản ánh đúng năng suất, và cũng đi ngược mục tiêu tạo ra chương trình nhỏ gọn và nhanh
- Khi viết lại bộ máy tính toán vùng của QuickDraw bằng một thuật toán đơn giản và tổng quát hơn, các phép toán vùng trở nên nhanh hơn gần 6 lần và mã giảm khoảng 2.000 dòng
- Trong biểu mẫu quản lý đầu tiên, ở mục hỏi số dòng mã đã viết trong tuần đó, Bill ghi
-2000, qua đó phơi bày nguyên vẹn lỗ hổng của cách đo này - Vài tuần sau, các quản lý không còn yêu cầu Bill nộp biểu mẫu đó nữa, và giai thoại này cho thấy quản lý dựa trên số dòng mã có thể bỏ lỡ những cải tiến thực sự
Đo số dòng mã trong nhóm Lisa
- Đầu năm 1982, nhóm phần mềm Lisa muốn tăng tốc công việc כדי phát hành phần mềm trong 6 tháng tới
- Một số quản lý đã cố theo dõi tiến độ bằng số dòng mã mà mỗi kỹ sư viết ra mỗi tuần
- Các kỹ sư nhận được một biểu mẫu phải nộp vào mỗi thứ Sáu, trong đó có mục ghi số dòng mã đã viết trong tuần đó
-2000 của Bill Atkinson
- Bill Atkinson, tác giả của QuickDraw và là nhà thiết kế giao diện người dùng chủ chốt, giữ vai trò quan trọng trong việc hiện thực hóa Lisa
- Bill cho rằng chỉ số số dòng mã không thể đo đúng năng suất
- Ông tin rằng mục tiêu của phần mềm tốt là viết ra chương trình nhỏ gọn và nhanh nhất có thể
- Một chỉ số khuyến khích tăng số dòng có thể thúc đẩy việc viết mã cẩu thả, cồng kềnh và dễ hỏng
- Khi đó ông đang tối ưu hóa bộ máy tính toán vùng của QuickDraw
- Ông viết lại hoàn toàn bộ máy vùng bằng một thuật toán đơn giản và tổng quát hơn
- Sau khi điều chỉnh, các phép toán vùng trở nên nhanh hơn gần 6 lần
- Đồng thời, mã giảm khoảng 2.000 dòng
- Khi điền biểu mẫu quản lý đầu tiên, ông nhìn mục số dòng mã một lúc rồi ghi
-2000 - Không rõ các quản lý đã phản ứng thế nào, nhưng vài tuần sau họ không còn yêu cầu Bill nộp biểu mẫu nữa
1 bình luận
Ý kiến trên Hacker News
Gợi nhớ đến trường hợp xung đột về số dòng code giữa Microsoft và IBM
Trong loạt chương trình truyền hình của PBS dựa trên Accidental Empires của Bob Cringely, có một đoạn Steve Ballmer kể lại trải nghiệm cùng phát triển OS/2 với IBM
Microsoft có thái độ hoàn thành công việc như một công ty nhỏ, còn IBM thì tập trung vào các chỉ số nội bộ, đặc biệt là đo năng suất lập trình viên bằng KLoC (số dòng code tính theo nghìn dòng)
Ballmer nói rằng: “Điều họ quan tâm chỉ là KLoC, KLoC, rồi lại KLoC”, và có vẻ IBM quan tâm số lượng code nhiều hơn là code có tốt hay không
https://ubiquity.acm.org/article.cfm?id=1022357
Những người hiểu chuyện xem màn “ăn mừng” đó chẳng khác nào một đám tang
Dùng số dòng code làm chỉ số năng suất thật sự là điều ngớ ngẩn
Tôi từng sửa một bug không ai giải được suốt 20 năm chỉ bằng một dòng code, và cũng nhớ có bug tồn tại 3 năm được giải quyết chỉ với một
order by. Làm sao đo được tác động của một dòng code? Theo kinh nghiệm của tôi, lập trình viên kém thường viết nhiều code hơn rất nhiềuCũng không thể quên câu chuyện một lập trình viên Microsoft viết lại đoạn code IBM dài 33 nghìn ký tự xuống còn 220 ký tự[1]. Kết quả là khối lượng công việc của Microsoft thành ra “âm”, và chiến tranh nổ ra vì chuyện đó
[1] https://archive.org/details/bigbluesunmaking00carr/page/4/mode/2up trang 101
Ví dụ hiện nay là có công ty lấy “tác động”, tức việc ra mắt sản phẩm mới, làm tiêu chí thăng chức. Kết quả là dễ sinh ra hàng đống sản phẩm thất bại mà chẳng ai bảo trì
Trong số các nhà khoa học máy tính và kỹ sư vĩ đại có những người tạo ra lượng code khổng lồ, và tôi tin điều đó bằng cách nào đó liên hệ trực tiếp với sức ảnh hưởng của họ. Vấn đề bắt đầu từ lúc số dòng code trở thành chỉ số để đo thành tích
Khi đó định luật Goodhart sẽ phát huy tác dụng: “Khi một thước đo trở thành mục tiêu, nó sẽ không còn là thước đo tốt nữa”
Theo góc nhìn chỉ số năng suất, code được xem là tài sản, nhưng cách nhìn gần với thực tế hơn là tính năng mới là tài sản còn bản thân code là nợ
Chủ đề này lên lại khá thường xuyên. Các thảo luận trước đây gồm có
https://news.ycombinator.com/item?id=33483165 (2022)
https://news.ycombinator.com/item?id=26387179 (2021)
https://news.ycombinator.com/item?id=10734815 (2015)
https://news.ycombinator.com/item?id=7516671 (2014)
https://news.ycombinator.com/item?id=4040082 (2012)
https://news.ycombinator.com/item?id=1114223 (2010)
https://news.ycombinator.com/item?id=1545452 (2010)
Đầu sự nghiệp, tôi từng tối ưu một chương trình C hơn 10 nghìn dòng mà mình được bàn giao xuống còn chưa tới 500 dòng. Đó là một chương trình C gọi SQL tới cơ sở dữ liệu Sybase
Không phải vì tôi có hiểu biết gì ghê gớm, mà vì tôi đưa ra một giả định đơn giản rằng có lẽ người tiền nhiệm không biết cách dùng hàm, hoặc không biết cách dùng tham số để đưa dữ liệu biến đổi vào truy vấn SQL. Quả đúng vậy: họ viết inline cùng một câu SQL lặp đi lặp lại, chỉ thay vài giá trị mỗi lần
Tôi viết lại phần gọi SQL thành các lời gọi hàm, và truyền bind variable như tham số của hàm. Phần code inline lặp lại được thay bằng cách lấy các giá trị bind thay đổi từ một mảng rồi gọi hàm trong vòng lặp
Tác động lớn nhất đôi khi đến từ việc đặt ra những câu hỏi đơn giản như “X sẽ được xử lý như thế nào?” để rồi khiến người ta không xây dựng thứ gì đó ngay từ đầu
Nếu thứ đó thậm chí còn chưa có cơ hội hoạt động đúng, thì coi như đã tiết kiệm được toàn bộ chi phí của việc cố gắng tạo ra nó
Kiểu này không chỉ không thể đo bằng chỉ số số học mà còn dễ làm mất lòng người khác. Dù vậy, vẫn xin dành lời tán dương cho những ai dám làm thế
Những người xem lập trình giống như đánh máy thật nhanh có điểm tương đồng thú vị với LLM. Họ viết ra cả đống mã không được dùng đến, rồi xóa đi, rồi lại viết tiếp, rồi lại xóa
Khoảng một nửa các yêu cầu thông tin gửi đến bộ phận lúc nào cũng theo kiểu “rất quan trọng, cần ngay lập tức, và có thể kiếm hoặc tiết kiệm rất nhiều tiền”, nhưng câu trả lời hiển nhiên là “Hãy tính bằng những thông tin đã có. Chẳng phải anh đã có máy tính và bảng tính rồi sao. Có cần tôi đưa bút chì không?”
Tránh để hệ thống phải xử lý X còn tốt hơn là bắt nó xử lý X. Những trường hợp đặc biệt chỉ dùng một hai lần sẽ làm hệ thống phình to ra, và rồi chẳng ai biết những trường hợp đặc biệt hay chương trình đó có tồn tại hay không, hoặc thực sự làm gì. Dù có tài liệu tốt đi nữa thì cũng hiếm ai bỏ thời gian học xem hệ thống làm được gì. Vì vậy phần lớn những tính năng đặc biệt như thế trên thực tế chỉ là lãng phí thời gian
Như một thí nghiệm tư duy tương ứng, có thể nghĩ đến tình huống ngược lại. Nếu một quản lý đọc bài này rồi đơn giản quyết định đo lường bằng số dòng mã đã xóa, liệu mọi thứ sẽ tốt hơn hay tệ hơn?
Loại thước đo này nhìn chung gần như vô dụng trừ khi có quy trình review code thật chắc chắn. Trái với điều mọi người ở đây muốn tin, những quy trình như vậy là hiếm. Nhưng nếu đã có review tốt thì hiệu suất kém hay việc thao túng chỉ số cũng sẽ bị phát hiện, nên lý do để đưa loại chỉ số này vào ngay từ đầu lại càng ít đi
Ví dụ như ý tưởng cũ kỹ rằng hãy loại bỏ toàn bộ kỹ sư phần mềm và những đoạn văn bản mã khó hiểu, thay bằng việc để quản lý sản phẩm vẽ các loại sơ đồ hay lưu đồ đặc biệt để tạo ra sản phẩm “low-code” hoặc “no-code”
Đếm riêng số dòng thêm vào và số dòng xóa đi, thì một bản vá
+50,-150sẽ được tính là 200 ΔSLOCĐây không phải thước đo tốt để đánh giá năng suất, đặc biệt là nếu dùng riêng lẻ thì càng không. Dù vậy, như một chỉ số kiểu tính nhẩm để ước lượng mức độ thay đổi thì nó vẫn hợp lý. Việc một lập trình viên có ΔSLOC cao hơn có năng suất hơn đồng nghiệp có ΔSLOC bằng 0 trong 1–2 tuần hay không còn tùy người đồng nghiệp đó đang làm gì, nhưng ít nhất có thể chắc chắn rằng trong khoảng thời gian đo đó, người thứ nhất đã thay đổi codebase nhiều hơn
Nếu sản phẩm đã “hoàn thiện” thì có thể vẫn như cũ hoặc tốt hơn. Nếu không thì các thay đổi số dòng mã âm sẽ không thể đi đến mức triển khai
Nhưng hầu hết sản phẩm đều tiếp tục tiến hóa. Vì thế chúng ta mới có thể ở lại cùng một dự án trong nhiều năm, và những đóng góp chỉ toàn xóa bỏ cuối cùng sẽ chẳng bổ sung được gì
Câu chuyện thật sự là có những lúc khi bắt đầu một dự án, ta không biết chính xác mình đang đi về đâu
Trong quá trình làm, ta hiểu bài toán và câu trả lời mong muốn rõ hơn rất nhiều, rồi từ đó có thể bóc bỏ những khối lớn để thay bằng thứ nhỏ hơn và tốt hơn
Và cũng không được quên rằng những người này phải nhét mọi thứ, kể cả mã assembly, vào trong ROM 64KB, với
-2000dòng mã. Áp lực phải làm cho nó nhỏ hơn là cực kỳ lớnCũng không chắc nó thực sự nằm trong ROM hay trên đĩa mềm khởi động. Nói thêm thì theo Wikipedia, ROM của Lisa là 16KB
[1] https://computerhistory.org/blog/the-lisa-apples-most-influential-failure/
[2] https://computerhistory.org/blog/macpaint-and-quickdraw-source-code/
Là Bill Atkinson, người nổi tiếng với Atkinson Dither. https://beyondloom.com/blog/dither.html
Trong quá trình đó, ông liên tục phải phát minh ra những cách mới để giao diện người dùng vận hành, cũng như cách viết phần mềm để giải quyết chúng. Ông tối ưu hóa đồng thời để “chạy nhanh trên phần cứng Mac” mà vẫn “mang lại trải nghiệm người dùng tuyệt vời”, và sự cộng hưởng đó đã để lại dấu ấn của ông lên toàn bộ thẩm mỹ của những chiếc Mac đen trắng thời kỳ đầu. Kiểu dithering đó cũng là một ví dụ khác về sự kết hợp giữa thiên tài thuật toán và cảm quan thẩm mỹ
Cảm quan này cũng thể hiện ở những thứ như đường viền chọn kiểu “marching ants” (https://en.wikipedia.org/wiki/Marching_ants). Tương tự, rất nhiều phản hồi trong UI Mac cổ điển được thể hiện bằng cách đảo ngược pixel. Việc chọn văn bản, làm nổi bật menu, cách nút bấm hiển thị khi đang giữ nút chuột, hay đường viền khi kéo cửa sổ đều như vậy, và vẽ chồng lên bằng chế độ XOR là một cách rất phù hợp để tạo ra các hiệu ứng này
Cách QuickDraw kết hợp các công cụ như vậy đã dẫn tới việc cuộc đối thoại nổi tiếng về hình chữ nhật bo góc với Steve Jobs (https://www.folklore.org/Round_Rects_Are_Everywhere.html) thực sự kết tinh thành kết quả là trong QuickDraw, việc vẽ hình chữ nhật bo góc trở nên dễ như vẽ hình chữ nhật thường, và khiến các hình bo góc xuất hiện khắp hệ điều hành
Thành công của UI Mac không chỉ vì nó trông đẹp. Một phần rất lớn là vì Bill Atkinson đã tạo ra một bộ công cụ nhỏ nhưng thông minh, giúp việc làm ra thứ gì đó đẹp mắt trở nên dễ dàng
Những biểu tượng tuyệt vời của Susan Kare cũng sẽ không được nhớ đến đầy trìu mến như vậy nếu Bill không tạo ra các công cụ cho phép dễ dàng đưa bitmap mask 32x32 pixel vào UI và đảo ngược chúng khi được nhấp
Bài học là dù có thông minh đến mức Einstein thì cuối cùng vẫn là một nhân viên, và với tư cách nhân viên thì phải làm những việc một nhân viên cần làm
Tôi chưa bao giờ hiểu vì sao khi nói về số dòng mã mà mọi người viết, họ luôn tính theo kiểu “số dòng thêm vào - số dòng xóa đi”
Việc tôi chạy 10km rồi quay lại điểm xuất phát không có nghĩa là tôi đã chạy 0km
Ví dụ như đổi từ dạng
if cond { ... return; } ...sangif cond { ... return; } else { .... }Nhưng dẫu vậy thì cách giải thích đó cũng không bao quát được toàn bộ