14 điểm bởi GN⁺ 2025-06-26 | 1 bình luận | Chia sẻ qua WhatsApp
  • Năm 1982, đội phần mềm Lisa của Apple đã áp dụng chính sách theo dõi số dòng mã hằng tuần của từng lập trình viên để chuẩn bị phát hành phần mềm
  • Bill Atkinson cho rằng số dòng mã là một thước đo sai lệch về năng suất phần mềm
  • Ông đã viết lại بالكامل bộ máy tính toán region của QuickDraw, cắt giảm khoảng 2.000 dòng mã và cải thiện hiệu năng gấp 6 lần
  • Atkinson đã ghi -2000 vào biểu mẫu quản lý dùng để báo cáo số lượng mã
  • Cuối cùng, quản lý không còn yêu cầu Bill nộp biểu mẫu đó nữa

Đội phần mềm Lisa năm 1982 và chính sách theo dõi số dòng mã

  • Đầu năm 1982, đội phần mềm Lisa bắt đầu tăng tốc với mục tiêu phát hành phần mềm trong vòng 6 tháng tới
  • Một số quản lý cho rằng việc theo dõi số dòng mã mà mỗi kỹ sư viết mỗi tuần sẽ giúp thúc đẩy tiến độ
  • Vì vậy, họ đưa vào sử dụng một biểu mẫu mà kỹ sư phải điền và nộp vào mỗi thứ Sáu, ghi lại số dòng mã đã viết

Quan điểm của Bill Atkinson về tiêu chuẩn năng suất

  • Bill Atkinson, người thiết kế QuickDraw và giao diện người dùng, cho rằng số dòng mã không thể là tiêu chuẩn đo năng suất phần mềm
  • Ông nhấn mạnh rằng mục tiêu là làm cho chương trình nhỏ nhất và nhanh nhất có thể
  • Ông nhận thấy việc đo số dòng mã ngược lại có thể khuyến khích mã lộn xộn và kém hiệu quả

Tái cấu trúc và tối ưu hóa bộ máy region của QuickDraw

  • Gần đây, Atkinson đã viết lại hoàn toàn bộ máy tính toán region của QuickDraw bằng một thuật toán đơn giản hơn và tổng quát hơn
  • Kết quả tối ưu hóa đã tăng tốc các phép toán region lên tới 6 lần
  • Trong quá trình đó, 2.000 dòng mã cũng được cắt giảm một cách tự nhiên

Báo cáo viết -2000 dòng mã và phản ứng của quản lý

  • Khi điền biểu mẫu quản lý của tuần đầu tiên, Atkinson đã viết -2000 vào ô số dòng mã
  • Không rõ các quản lý đã phản ứng thế nào với con số này
  • Vài tuần sau, Bill được bảo rằng không cần nộp biểu mẫu nữa, và ông đã vui vẻ đón nhận điều đó

1 bình luận

 
GN⁺ 2025-06-26
Ý kiến trên Hacker News
  • Commit mà tôi nhớ là xuất sắc nhất là lần xóa khoảng 60.000 dòng code, thay toàn bộ “server” vốn lưu mọi trạng thái trong bộ nhớ bằng khoảng 5.000 dòng logic gọn nhẹ

    • Tôi xem đó là một kỳ tích về mặt thuật toán, vì đoạn code này đủ nhẹ để tích hợp tự nhiên vào các dịch vụ khác và cũng không còn cần trạng thái trong bộ nhớ
    • Tôi đã phát hiện ra rằng có thể giải bài toán đẳng cấu đồ thị con có hướng dẫn trên một cây cụ thể, nhờ đó có thể duyệt một lần qua một đồ thị hai chiều có hướng tổng quát, chỉ theo dõi bằng một lượng nhỏ stack các đường đi từ nút gốc xuất phát để tạo ra đồ thị đầu ra là cây
    • “Commit -60.000 dòng” thực sự là một khoảnh khắc khó quên, và từ đó đến nay tôi vẫn thấy tiếc vì chưa từng làm được việc nào ấn tượng về mặt thuật toán đến thế nữa
      • Tôi là một lập trình viên nghiệp dư, trong công việc viết khá nhiều script và cũng thấy mình khá thành thạo ở vài mảng của lập trình, nhưng mỗi khi nghe những câu chuyện như thế này lại thấy thế giới mình chưa biết thật rộng lớn, học cả đời cũng chưa đủ, nên lại thấy khiêm tốn hơn
      • Muốn nghe thêm bối cảnh. Việc biến một chương trình có trạng thái thành vô trạng thái nghe như phép màu, nên tôi rất muốn học kỹ thuật đó
      • Tôi là nhà toán học có nền tảng về lý thuyết đồ thị và thuật toán, nên tò mò không biết kỹ năng của mình có áp dụng được vào công việc thực tế kiểu này không. Nếu được, bạn có thể chia sẻ chi tiết hơn không?
      • Có vẻ việc đồ thị đích là cây không quá quan trọng. Điểm mấu chốt là phần "guided" mới là thứ cho phép duyệt một lần
        • Giả sử bắt đầu từ một nút cụ thể trong đồ thị gốc, và nếu tồn tại đẳng cấu thì nút gốc của cây đích cũng nhất định phải khớp với nút đó
        • Diễn giải bài toán theo kiểu duyệt đồ thị gốc theo mẫu của cây đích: lệch thì false, khớp hết thì true. Suy ra rằng ngay cả khi không phải cây, nếu chỉ định rõ điểm bắt đầu thì cách này cũng có thể áp dụng cho mọi đồ thị con
      • Đùa rằng có lẽ những bài phỏng vấn kiểu “hãy đảo ngược cây nhị phân” ngày nay bắt nguồn từ chính kiểu lập trình viên như thế này
        • Xin một lời giải thích dễ hiểu cho các lập trình viên bình thường tò mò về lý thuyết đồ thị nhưng thấy thuật ngữ quá khó
  • Hồi đại học tôi từng làm cho một công ty có chủ trương quản lý rằng tân binh cũng có thể viết ra code tốt, và rốt cuộc họ trở thành một ví dụ thất bại chưa thể chứng minh điều đó

    • Sau khi sửa bug trong code mà vẫn thấy cùng bug đó tiếp tục xuất hiện, tôi phân tích thì phát hiện họ cứ tạo bản sao của hàm cũ rồi chỉ sửa chút ít thay vì thêm tham số vào hàm hiện có. Kết quả là tôi đã xóa hơn 3/4 codebase, tức hàng nghìn dòng Turbo Pascal
    • Khách hàng của dự án là bộ phận Energy, và đó là chương trình quản lý tồn kho vật liệu hạt nhân, nên tôi vẫn nhớ những đêm mất ngủ vì chuyện đó
      • Nhắc một cách châm biếm rằng ưu điểm của việc copy code cũ là không làm ảnh hưởng đến độ ổn định của code hiện có, đồng thời còn giúp đẹp chỉ số ‘mức độ đóng góp’ trong mắt quản lý. Cần revert thì chỉ việc xóa bản sao đi cũng xong
      • Trong nhóm tôi cũng có đồng nghiệp thường xuyên lặp lại kiểu trùng lặp code này. Tôi nghĩ đó là thói quen để nhanh chóng ra kết quả cho những yêu cầu gấp hoặc những người nói to nhất. Vấn đề gốc là họ không muốn đầu tư thời gian cho việc refactor hàm dùng chung và viết đủ test
      • Các lập trình viên thuê ngoài tôi từng phụ trách trước đây cũng có thói quen giống vậy. Khi tôi chỉ ra rằng điều đó có thể gây hỗn loạn, họ trả lời: “Lúc đó dùng Ctrl+F là được mà”
      • Không biết câu chuyện trên có xảy ra ở khu vực Blacksburg không?
      • Kinh nghiệm của tôi cũng tương tự: tôi từng làm ở một công ty vận hành các cổng thông tin gần như giống hệt nhau cho nhiều quốc gia ở Đông Nam Á. Mỗi portal lại có source code trong một kho Git riêng, nên mọi tính năng hay bản sửa lỗi cần áp dụng chung đều phải backport thủ công vào từng bản sao mã nguồn, một trải nghiệm cực kỳ ngán ngẩm
        • Tôi đã hỏi “không thể đưa tất cả vào một kho duy nhất rồi dùng feature flag để tùy biến theo từng portal sao?”, nhưng bị từ chối là không thể
        • Cuối cùng chỉ trong hai ba tháng tôi gộp code của 4~5 portal vào một kho, áp dụng feature flag và nâng cấp framework, rồi triển khai trơn tru. Giờ đây có thể sửa bug đồng thời cho tất cả portal, cảm giác như được giải thoát khỏi nỗi khổ thao tác lặp đi lặp lại bằng tay
  • Về chủ đề liên quan, có người đã tổng hợp các thread nổi tiếng trên Hacker News về “-2000 dòng code” tại liên kết

    • Họ chỉ ra rằng việc định kỳ đăng lại những bài kinh điển trong quá khứ là một truyền thống có ích cho cả người dùng mới lẫn người dùng cũ
      • Tôi là kiểu người đơn giản: cứ thấy “-2k lines of code” là tự động upvote
        • Tôi thường kể câu chuyện của Atkinson cho các khách hàng muốn quản lý năng suất bằng một metric trên một trục duy nhất. Thước đo năng suất thực sự phải là tính hữu dụng, và nếu ai đó thật sự định lượng được điều này thì có lẽ xứng đáng được đề cử Nobel Kinh tế
  • Dự án web UI tôi phụ trách có 250.000 dòng code, chưa tính backend

    • Lập trình viên trước đó rất thông minh nhưng JS thì là lần đầu, và cấu trúc của họ là lưu mọi trạng thái vào các thuộc tính tùy biến của DOM, rồi rải đầy addEventListener. Tôi còn đùa rằng “đưa cho một nhà sư một cuốn sách JavaScript và 10 năm biệt giam thì sẽ ra loại code như thế này”
    • Trong vài tháng tôi chuyển cấu trúc sang web components và loại bỏ được 50.000 dòng; sau đó bắt tay vào viết lại toàn bộ, hiện mới đạt khoảng 80% chức năng tương đương nhưng toàn bộ code chỉ còn khoảng 17.000 dòng gọn nhẹ (không tính thư viện như Vue/pinia)
    • Sắp tới tôi sẽ xóa hơn 200.000 dòng, và có lẽ từ nay về sau sẽ không còn trải nghiệm nào vượt nổi chuyện đó nữa, đến mức chỉ muốn nghỉ hưu
      • Tôi cũng có trải nghiệm tương tự. Tác giả ban đầu thực chất chỉ hơn junior một chút, nhưng lại là nhà sáng lập công ty và cực kỳ năng suất. Vì phát triển mà không có kinh nghiệm làm việc nhóm hay cộng tác trên code của người khác nên cấu trúc chứa đủ mọi code smell có thể tưởng tượng ra
        • Mô tả thêm rằng có những hàm dài hàng nghìn dòng, switch/case/if/else lồng nhau và toán tử ba ngôi tới 10 tầng, câu SQL trộn lẫn với JS/HTML/HTML chèn JS, và hoàn toàn không có test tự động trong một kiểu frontend thời PHP/Dojo
      • Có người chỉ ra rằng mô tả “code gọn nhẹ nhưng mới có 80% chức năng” tự nó đã cho thấy điểm mù của kiểu so sánh này. Nếu mới chỉ triển khai một phần chức năng thì dĩ nhiên chưa cần nhiều dòng như code gốc
  • Có một tranh Dilbert về cấu trúc thưởng vô hạn: sếp của Dilbert hứa sẽ thưởng tiền mỗi khi sửa được một bug, và Wally liền nói “Hôm nay chắc tôi phải code ra ít nhất một chiếc minivan mới được!”

    • Tình huống này được gọi là “Perverse incentive”, giải thích thêm tại liên kết tham khảo
    • Quản lý của tôi cũng từng dán chính truyện tranh này ( hình ảnh ) lên tường phòng nghỉ
    • Có người thực tế hỏi “minivan” ở đây nghĩa là gì
  • Chia sẻ một trường hợp thực tế xóa 64.000 dòng trong kho dotnet/runtime

    • Họ thay hỗ trợ interop C# + WinRT vốn tích hợp sẵn bằng một công cụ sinh mã nguồn, một thay đổi kiến trúc đòi hỏi quyết tâm thay dứt khoát trong một lần. Xem PR
  • Mỗi khi thấy thống kê nói LLM đã nâng năng suất lập trình viên lên bao nhiêu, tôi lại nhớ đến câu chuyện kinh điển này

    • Có người phản biện rằng AI cũng khá giỏi trong việc xóa code, rồi chia sẻ một trường hợp vui về Cursor trong cộng đồng: “AI đã xóa sạch mọi thứ”
    • Dạo này câu cửa miệng của ngành là “X% code mới của chúng tôi được AI viết!”
    • Châm biếm rằng nếu tính cả chi phí xây dựng và duy trì các nhà máy điện hạt nhân mới, thì các chỉ số năng suất lập trình viên kia bị thổi phồng phi thực tế đến mức nào
  • Tôi không học CS bài bản mà là người đi làm rồi học thực chiến

    • Dự án của chúng tôi có mục tiêu là tái cấu trúc các live object sao cho con người dễ đọc hơn
      • Biểu diễn cuối cùng đòi hỏi rất nhiều kiểu phức tạp, còn biểu diễn ban đầu thì tương đối đơn giản
      • Khi có các nút dữ liệu tương tự nhau, chúng tôi phải so sánh rồi hợp nhất chúng lại — tức là trích xuất thành phương thức và tìm ra các tham số — để cải thiện khả năng đọc hiểu
        • Ban đầu chúng tôi chuyển đổi sang kiểu cuối cùng trước rồi mới đem so sánh, khiến số tổ hợp kiểu bùng nổ, gần như không thể quản lý nổi, và đạt đến mức phức tạp mà trong nhiều năm các kỹ sư không sao hiểu được cấu trúc đó
      • Sau này tôi biết đến cách tiếp cận dựa trên hashmap, dùng giá trị hash để phân biệt các nút có cùng bộ khung, so sánh và hợp nhất trước rồi mới chuyển sang kiểu cuối cùng theo cấu trúc hai giai đoạn
      • Nhờ chuyển từ trừu tượng hóa xoay quanh kiểu sang trừu tượng hóa xoay quanh dữ liệu, cả những cấu trúc phân cấp lớp kỳ quặc cũng có thể được quản lý dễ dàng bằng các thuộc tính đơn giản
      • Tóm lại đó là một cấu trúc decompiler nhiều tầng khá ngớ ngẩn, nhưng trải nghiệm cho thấy tốc độ xử lý và độ dễ đọc đều được cải thiện mạnh. Không có viên đạn bạc nào đúng cho mọi tình huống, nhưng với chúng tôi thì ‘kiểu’ mới là vấn đề cốt lõi, và cách giải quyết này đã giúp ích rất nhiều cho dự án
  • Trước kỳ đánh giá cuối năm, tôi nhìn lại thống kê trong monorepo nội bộ và phát hiện mình đã trở thành người có số dòng code ròng âm

    • Lý do là xóa code sinh tự động cho API và type, loại bỏ API phiên bản cũ, v.v., nhưng cảm giác mỗi ngày đi làm chỉ để xóa code lại kỳ lạ mà vui
  • Từ rất lâu trước đây, tôi từng sốc khi thấy trong một dự án lớn, các PL ghi tay offline số bug theo từng lập trình viên — số bug sửa được, số bug gây ra — rồi dán lên tường như một KPI thảm họa

    • Tôi không bị ảnh hưởng vì chỉ là dự án liên quan, nhưng một đồng nghiệp thì lấy cảm hứng từ giai thoại đạo diễn Lars von Trier từng cắt phần hình thập tự trên lá cờ Đan Mạch rồi khâu lại thành kiểu giống cờ cộng sản đỏ để phản đối và bị loại khỏi ‘danh sách tác giả’ của giới quan liêu; anh ấy cắt dòng bug count của chính mình ra rồi dán lại như một cách phản kháng công khai. Ngày hôm sau danh sách đó biến mất mãi mãi, và đó vẫn là một ký ức quý giá với tôi
      • Câu trả lời đơn giản và trực diện của anh ấy, “Vì tôi không muốn thuộc về cái danh sách này!”, tóm gọn hoàn hảo toàn bộ tình huống
      • Có người cũng chia sẻ rằng rất khó hình dung lá cờ và danh sách đó đã được trực quan hóa như thế nào