89 điểm bởi GN⁺ 13 ngày trước | 1 bình luận | Chia sẻ qua WhatsApp
  • Khi tiếp cận một codebase mới, hãy phân tích lịch sử Git để nắm cấu trúc dự án và các vùng rủi ro, từ đó thiết lập hướng khám phá hiệu quả
  • Tìm những file bị thay đổi thường xuyên nhất trong 1 năm gần đây, đối chiếu tần suất thay đổi với mức độ tập trung lỗi để xác định code rủi ro cao
  • Thông qua phân bố người đóng góp và xu hướng hoạt động để kiểm tra bus factor, khoảng trống bảo trì và khả năng đứt gãy tri thức
  • Theo dõi sự thay đổi về tốc độ và động lực phát triển của đội ngũ qua số lượng commit theo tháng, đồng thời đánh giá độ ổn định khi phát hành qua tần suất Revert·Hotfix
  • Năm lệnh này có thể được dùng như công cụ thực tiễn để chẩn đoán nhanh tình trạng sức khỏe của dự án trước khi mở đọc dù chỉ một dòng code

Năm lệnh Git nên chạy trước khi đọc code

  • Khi phân tích một codebase mới, đây là cách tiếp cận chẩn đoán sức khỏe dự án bằng lịch sử Git trước khi mở file
    • Qua lịch sử commit, có thể biết ai đã tạo ra nó, vấn đề tập trung ở đâu, và đội ngũ phát hành ổn định đến mức nào
  • Điều gì bị thay đổi thường xuyên nhất

    • Lệnh:
      git log --format=format: --name-only --since="1 year ago" | sort | uniq -c | sort -nr | head -20
      
    • Hiển thị 20 file được chỉnh sửa nhiều nhất trong 1 năm gần đây
    • Các file đứng đầu thường là những file mà cả nhóm “ngại đụng vào”; khi tần suất thay đổi cao (churn) kết hợp với tâm lý né quyền sở hữu, chúng trở thành gánh nặng lớn nhất của codebase
    • Theo nghiên cứu của Microsoft Research (2005), các chỉ số dựa trên tần suất thay đổi dự đoán lỗi tốt hơn các chỉ số độ phức tạp
    • Hãy đối chiếu 5 file đầu với lệnh đo mức độ tập trung lỗi để xác định những file vừa thay đổi nhiều vừa nhiều lỗi là điểm rủi ro lớn nhất
  • Ai là người tạo ra đoạn code này

    • Lệnh:
      git shortlog -sn --no-merges
      
    • Xếp hạng người đóng góp theo số lượng commit
    • Nếu một người chiếm hơn 60%, thì có rủi ro bus factor
    • Nếu người đóng góp hàng đầu không hoạt động trong 6 tháng gần đây, có thể tồn tại khoảng trống bảo trì
    • Nếu trong 30 người đóng góp chỉ còn 3 người hoạt động trong 1 năm gần đây, có thể đã xảy ra đứt gãy tri thức do thay đổi nhân sự phát triển
    • Tuy nhiên, với các nhóm dùng chiến lược squash-merge, thông tin tác giả có thể bị lệch theo người merge, nên cần kiểm tra chiến lược merge
  • Lỗi tập trung ở đâu

    • Lệnh:
      git log -i -E --grep="fix|bug|broken" --name-only --format='' | sort | uniq -c | sort -nr | head -20
      
    • Trích xuất 20 file đứng đầu về phát sinh lỗi dựa trên các commit có chứa từ khóa liên quan đến bug
    • So sánh danh sách này với danh sách tần suất thay đổi để xác định những file vừa hay sửa vừa hay hỏng là code rủi ro cao
    • Độ chính xác của kết quả phụ thuộc vào chất lượng message commit, nhưng ngay cả như một bản đồ mật độ lỗi sơ bộ thì vẫn rất hữu ích
  • Dự án đang tăng tốc hay chững lại

    • Lệnh:
      git log --format='%ad' --date=format:'%Y-%m' | sort | uniq -c
      
    • Có thể nhìn xu hướng hoạt động một cách trực quan qua số lượng commit theo tháng
    • Nhịp độ ổn định là dấu hiệu của một dự án khỏe mạnh
    • Nếu chỉ trong một tháng số commit giảm còn một nửa, có thể nhân sự chủ chốt đã rời đi
    • Nếu giảm liên tục suốt 6–12 tháng, điều đó gợi ý động lực đội ngũ suy giảm; còn nếu tăng vọt theo chu kỳ rồi lại chững, đó có thể là mô hình phát hành theo đợt
    • Có trường hợp thực tế CTO nhìn biểu đồ tốc độ commit và nhận ra: “đó là thời điểm một senior engineer rời đi”
    • Dữ liệu này có ý nghĩa như dữ liệu về đội ngũ, không chỉ là dữ liệu về code
  • Đội ngũ đang phải ứng phó khẩn cấp thường xuyên đến mức nào

    • Lệnh:
      git log --oneline --since="1 year ago" | grep -iE 'revert|hotfix|emergency|rollback'
      
    • Đo tần suất Revert·Hotfix
    • Mỗi năm vài trường hợp là bình thường, nhưng nếu cứ 2 tuần lại có một lần thì đó là tín hiệu mất niềm tin vào quy trình phát hành
    • Đây là dấu hiệu của những vấn đề sâu hơn như kiểm thử thiếu ổn định, không có staging, quy trình rollback quá phức tạp
    • Nếu kết quả là 0, либо đội ngũ rất ổn định, либо message commit không chính xác
    • Mẫu hình khủng hoảng sẽ lộ ra rất rõ, và chỉ riêng việc nó có tồn tại hay không cũng đủ để đánh giá mức độ tin cậy

Kết luận

  • Năm lệnh này có thể chạy chỉ trong vài phút và sẽ chỉ ra nên bắt đầu đọc từ đâu trước khi mở dù chỉ một dòng code
  • Nhờ đó, thay vì khám phá ngày đầu một cách mò mẫm, bạn có thể phân tích code có hệ thống, tập trung vào các vùng vấn đề
  • Quy trình này tương ứng với giờ đầu tiên của một đợt kiểm toán codebase (codebase audit), và sẽ tiếp nối bằng quá trình phân tích trong cả tuần sau đó

1 bình luận

 
Ý kiến trên Hacker News
  • Chia sẻ các ví dụ có thể thay thế những lệnh phân tích git bằng Jujutsu
    Có thể dùng lệnh jj log để xem những file thay đổi nhiều nhất trong 1 năm gần đây, các contributor chính, nơi tập trung bug, mức độ sống còn của dự án, tần suất sửa lỗi khẩn cấp, v.v.
    Cú pháp gần với lập trình hơn so với shell script, nhưng số lượng flag cần nhớ lại ít hơn

    • Với tôi, jujutsu trông giống như Nix của hệ thống quản lý phiên bản
      Cũng như Nix rất hay nhưng làm tăng độ phức tạp, jujutsu cũng cho cảm giác như vậy
      Tôi dùng thử vài tháng rồi quay lại git. git đã quá quen tay và ở đâu cũng dùng được
    • Tôi không hiểu làm sao người ta có thể nhớ hết những ngôn ngữ script tùy biến như thế này
      Với jq, chỉ cần nhớ được vòng lặp mảng thôi tôi đã thấy mừng rồi, còn kiểu cú pháp này thì hoàn toàn không vào đầu nổi
    • Cả lệnh jj lẫn git đều quá dài và phức tạp nên tôi không định học thuộc
      Nếu dùng thường xuyên thì tôi sẽ rút gọn bằng alias
    • Dự án không có commit không có nghĩa là đã chết, ngược lại có thể là dấu hiệu nó ổn định
      Ví dụ có một thư viện tạo mã QR 10 năm không cập nhật mà vẫn hoạt động hoàn hảo
      Đôi khi tôi còn tự hỏi có nên thêm vài commit vô nghĩa bằng bot chỉ để trông cho có hoạt động không
    • Tôi không muốn lập trình với git, tôi chỉ muốn xong việc
      Vì vậy tôi thích các lệnh pipe UNIX truyền thống hơn là công cụ như jujutsu
      Việc tôi dùng Maven thay vì Gradle cũng vì lý do tương tự
  • Thật thú vị khi tác giả giả định rằng các lập trình viên viết commit message tốt
    Thực tế thì đa số chỉ ở mức “changed stuff”
    Người coi trọng commit log như tôi là thiểu số
    Commit message do AI tạo ra có thể giúp giải quyết vấn đề này khá nhiều

    • Đây là vấn đề lãnh đạo. Team lead hoặc CTO giỏi sẽ đặt kỳ vọng rõ ràng về chất lượng commit message
    • Ở các team merge bằng squash PR, phần mô tả PR sẽ trở thành commit message, nên chất lượng thường tốt hơn
    • Trong workflow squash & merge thì cuối cùng tiêu đề PR mới là thông điệp chính
      Dev có thể viết commit message tùy ý, vì đằng nào sau đó cũng chẳng ai đọc
    • Team của chúng tôi phân biệt repo Corerepo Non-Core
      Core bắt buộc có PR review và mô tả chi tiết, còn Non-Core thì được tự do thử nghiệm
      Ở Core, có lúc commit message còn dài gấp 20 lần code; còn Non-Core thì chỉ ở mức “hope this works”
    • Việc dev không viết commit message là vấn đề văn hóa
      Công ty chúng tôi yêu cầu điều đó từ nhau
  • Tôi đã chạy các lệnh này trên nhiều codebase và thấy kết quả khác xa thực tế
    Ví dụ trong kết quả git shortlog -sn --no-merges, người có nhiều commit nhất đôi khi lại là người đã nghỉ việc từ lâu
    Nhiều commit không có nghĩa là đóng góp nhiều hơn

    • Vì vậy tôi thích squash-and-merge hơn
      Những commit quá vụn vặt sẽ chỉ giữ lại ở feature branch, còn khi vào main thì merge cho gọn gàng
    • Các lệnh kiểu này hữu ích khi chẩn đoán dự án có vấn đề
      Còn với codebase bình thường thì thường chỉ cho ra kết quả không mấy ý nghĩa
    • Thành thật mà nói tôi nghi ngờ tác giả có thực sự chạy các lệnh này không, bài viết có cảm giác như LLM viết ra
    • Nếu workflow tự động dùng credential của một người thì thống kê có thể bị méo
    • Ở một codebase trung tâm của công ty cũ, tôi cũng có số commit áp đảo
      Vì tôi là người tạo dự án từ đầu, còn bây giờ những người khác commit thường xuyên hơn tôi
  • Câu “file bị thay đổi nhiều nhất là file mà mọi người ngại đụng vào” nghe khá thú vị

    • Nó giống một nghịch lý kiểu “quán ăn đông đến mức chẳng ai muốn vào”
    • Khi thử kiểm tra, file được sửa nhiều nhất lại là file sinh tự động hoặc các file nhàm chán như entrypoint
    • Những lệnh kiểu này cần có cảnh báo
      Nếu chỉ nhìn kết quả chạy lệnh rồi kết luận thì đôi khi lại trông khá ngớ ngẩn
      Thực tế nó chỉ cho thấy gần đây người ta đã làm những tính năng gì trong 1 năm qua
    • Nếu xem cả Churn (tần suất thay đổi) lẫn Complexity (độ phức tạp) thì sẽ hữu ích hơn nhiều
      Nơi nào cả hai đều cao mới là vùng vấn đề thật sự
      Khi các vùng như vậy tích tụ lại, người ta sẽ bắt đầu nói đến chuyện “phải viết lại app từ đầu”
    • Những file khiến mọi người e ngại thường là các file vừa thiết yếu vừa phức tạp
      Ai cũng phải sửa nhưng nó quá lớn nên rất khó đụng vào
  • Tôi tạo một alias summary cho git để in ra tóm tắt branch, số commit, số tác giả, số file, v.v. chỉ trong một lần
    Ý tưởng lấy từ GitAlias/gitalias

    • Tôi thắc mắc vì sao lại viết bằng hàm trong .gitconfig, làm thành script git-summary có vẻ còn đơn giản hơn
    • Việc phải tự gõ những lệnh này mỗi lần nghe khá giống bài do AI viết, vì người dùng thành thạo thật sự sẽ tái sử dụng bằng alias
    • Script khá hay nhưng trong môi trường của tôi không có lệnh như log-of-count-and-email
    • Có lẽ nên tạo luôn trang man ở máy local
  • Cần thêm ranh giới từ (\b) vào regex
    Ví dụ từ “bug” trong “debugger” có thể làm ra kết quả sai
    Ví dụ đã chỉnh sửa như sau
    git log -i -E --grep="\b(fix|fixed|fixes|bug|broken)\b" ...

    • Trên macOS, \b không được hỗ trợ nên thay vì -E phải dùng tùy chọn regex Perl -P
      Có thể sửa thành dạng git log -i -P --grep="\b(...)\b"
    • Bên tôi cũng dùng từ “rollback” với nghĩa khác nên cần lọc thêm
    • Nhận xét rất hay, chính xác hơn hẳn
  • Nếu không dùng squash-merge thì người có nhiều commit nhất đôi khi lại là dev tệ nhất
    Trước đây tôi từng gặp một người như vậy, cứ sửa đi sửa lại đúng một file rồi cuối cùng bị sa thải
    Squash là cách tốt để che bớt kiểu vấn đề này

  • Thống kê số commit đơn thuần rất khó tin cậy
    Có người chỉ commit khi code đã được test hoàn hảo, có người lại commit rất thường xuyên từng dòng một
    Giá trị của một commit có thể chênh nhau tới 100 lần tùy từng người

    • Nhưng mục đích của tác giả là nhìn vào xu hướng thay đổi
      Tốc độ thay đổi có ý nghĩa hơn giá trị tuyệt đối
  • Cách tiếp cận phân tích này làm tôi nhớ tới “Your Code as a Crime Scene” của Adam Tornhill
    Liên kết gốc
    Nó cũng khá giống khái niệm Developer’s Legacy Index

    • Tôi rất thích những bài viết đầu tiên của Tornhill về C, thật vui khi thấy nhắc lại
  • Sẽ hay hơn nếu tác giả đưa luôn kết quả thực tế của từng lệnh
    Ví dụ đầu ra sẽ thuyết phục hơn là chỉ giải thích

    • Tôi cũng thấy bài viết hơi có mùi AI, nhưng dù sao vẫn học được năm lệnh nên cũng không tệ