77 điểm bởi GN⁺ 2024-11-18 | 9 bình luận | Chia sẻ qua WhatsApp
  • Bài viết này không phải là lời khuyên, mà là nội dung về những thói quen phát triển mà tác giả hiện đang áp dụng
  • Đây là bài tổng hợp trải nghiệm nỗ lực tránh các thói quen xấu và xây dựng thói quen tốt, đề cập đến 10 thói quen đã giúp cải thiện năng suất và duy trì chất lượng

1. Giữ commit nhỏ

  • Cần giữ commit càng nhỏ càng tốt. Commit nhỏ cho phép chỉ cần hoàn tác đúng commit gây lỗi khi có bug, từ đó tránh được các xung đột merge phức tạp
  • Tác giả lấy quy tắc "phải có thể commit khi phần mềm biên dịch được" làm nguyên tắc

2. Refactoring liên tục

  • Lời khuyên của Kent Beck: "Khi bạn muốn thay đổi, trước tiên hãy làm cho việc thay đổi trở nên dễ dàng, rồi sau đó hãy thực hiện thay đổi một cách dễ dàng."
  • Ít nhất một nửa số commit nên bao gồm refactoring. Những đợt refactoring nhỏ sẽ rất hữu ích khi có yêu cầu lớn xuất hiện
  • Nên tránh refactoring lớn. Thay vào đó, hãy liên tục thực hiện những cải tiến nhỏ trong vòng 10 phút

3. Tầm quan trọng của việc triển khai code

  • Bản thân code là một khoản nợ tiềm ẩn, và code chưa được triển khai là khoản nợ lớn nhất
  • Test mang lại sự tự tin, nhưng triển khai thực tế mới mang ý nghĩa là sự phê duyệt thực sự
  • Tần suất triển khai càng cao thì chi phí hosting có thể tăng, nhưng việc xác nhận rằng phần việc mới nhất thực sự hoạt động là một lợi ích quan trọng

4. Không test chức năng của framework

  • Không test chức năng của framework. Framework đã được kiểm chứng đầy đủ
  • Nếu giữ component nhỏ, framework sẽ xử lý phần lớn công việc và số lượng test sẽ giảm
  • Component lớn làm tăng độ phức tạp, kéo theo nhu cầu phải viết nhiều test

5. Tạo module mới

  • Nếu một chức năng cụ thể không phù hợp với module hiện có, tốt hơn là tạo một module mới
  • Tốt hơn nên để nó là một module độc lập thay vì cố ép thêm chức năng vào module hiện có

6. Áp dụng linh hoạt phát triển hướng kiểm thử (TDD)

  • Khi thiết kế API chưa rõ ràng, hãy viết test trước để suy nghĩ từ góc nhìn của "khách hàng"
  • Tác giả không tuân theo TDD như một giáo điều. Khi cần, có thể làm việc ở đơn vị lớn hơn rồi mới test
  • Không nhất thiết phải để các đơn vị code nhỏ ở trạng thái thất bại, và không bị trói buộc bởi sự giáo điều làm cản trở năng suất

7. Chỉ cho phép copy-paste một lần

  • Copy một lần thì không sao, nhưng từ lần thứ hai trở đi sẽ phát sinh trùng lặp
  • Ở thời điểm đó cần loại bỏ trùng lặp bằng một mức trừu tượng phù hợp. Dù việc tham số hóa có hơi kỳ quặc, nó vẫn tốt hơn việc gộp nhiều cách triển khai vào chung một chỗ

8. Chấp nhận sự thay đổi của thiết kế

  • Thiết kế sẽ cũ đi theo thời gian. Refactoring có thể làm chậm quá trình lão hóa, nhưng cuối cùng nó vẫn sẽ phải thay đổi
  • Đừng quá bám chấp vào thiết kế trước đây, mà hãy chấp nhận sự thay đổi
  • Không có thiết kế nào là hoàn hảo, và khả năng thích ứng tốt với thay đổi là cốt lõi của phát triển phần mềm

9. Ba loại technical debt

  • Technical debt có thể được chia thành ba loại:
    1. Những thứ cản trở công việc hiện tại
    2. Những thứ có khả năng cản trở công việc tương lai
    3. Những thứ có thể có khả năng sẽ cản trở
  • Cần giảm thiểu loại nợ thứ nhất, tập trung vào loại thứ hai và bỏ qua loại thứ ba

10. Mối quan hệ giữa khả năng test và thiết kế tốt

  • Nếu khó test, rất có thể thiết kế đang có vấn đề
  • Thiết kế test cũng có thể là đối tượng cần cải thiện. Ví dụ, nếu bạn thấy khó viết mock cho em.getRepository(User).findOneOrFail({id}), thì nên tách nó ra thành một hàm riêng hoặc sử dụng test utility
  • Lý do test không được viết là vì nó khó test, và đó có thể là vấn đề của thiết kế

9 bình luận

 
yangeok 2024-11-25

Có vẻ là cần đạt được srp hơn là dry, thì dù giao cho AI cũng sẽ không nói linh tinh.

 
progdesigner 2024-11-21

Điều quan trọng nhất dường như là bạn đã xây dựng được mã nguồn và môi trường có thể thích ứng nhanh với thay đổi đến mức nào.

Và thông qua việc trừu tượng hóa phù hợp, bạn có thể nâng cao khả năng tái sử dụng và mở rộng của mã nguồn, đồng thời tận dụng các công cụ AI để tối đa hóa tốc độ phát triển.

 
pcj9024 2024-11-20

Đúng là một bài viết rất hay. Mình muốn giới thiệu nó ở khắp nơi.

 
tsboard 2024-11-20

Chấp nhận thay đổi, chỉ copy-paste một lần, để việc kiểm thử hoạt động tốt hơn, commit nhỏ hơn...!

 
aer0700 2024-11-19

Bài viết hay đấy.

 
puersum 2024-11-19

Mình nghĩ bài này rất đáng để xem bản gốc.

Thường nếu là tin mình quan tâm thì mình vẫn hay đọc nguồn gốc, nhưng bài này thì đặc biệt càng nên làm vậy. Nhìn vào mục 1, câu trong nguyên văn là
Keep commits small enough that you wonder if you're taking this "keep commits small" thing a little too far. nhưng đã được rút gọn thành "phải giữ commit nhỏ nhất có thể"..

 
ilbanin00 2024-11-19

Đúng là một bài viết rất hay.

 
joon14 2024-11-19

Mục số 7 thực sự rất hay.

 
GN⁺ 2024-11-18
Ý kiến trên Hacker News
  • Nên dùng tham số để tránh có nhiều cách triển khai. Việc cải thiện tham số sẽ dễ hơn so với hợp nhất nhiều cách triển khai.

    • Nếu không thể tránh các "tham số kỳ quặc", tốt hơn nên tách mã ra. Nên tránh cờ boolean và nhiều tham số kiểu enum.
    • Chữ ký hàm phức tạp khiến việc bảo trì trở nên khó khăn.
  • Sao chép mã một lần thì có thể chấp nhận được, nhưng từ lần thứ hai trở đi nên tránh trùng lặp. Nên tạo ra một abstraction tốt khi đã có đủ dữ liệu thực tế.

    • Dù ban đầu mã có giống nhau, khi cần thay đổi thì điều quan trọng là xem chúng có cần thay đổi cùng nhau hay không.
    • Mục tiêu không phải là tránh trùng lặp mã bằng mọi giá, mà là giữ những phần mã cần tiến hóa cùng nhau ở cùng một chỗ.
  • DRY (đừng lặp lại chính mình) hay WET (viết mọi thứ hai lần) không phải là những quy tắc tuyệt đối. Điều khó là hiểu khi nào nên để trùng lặp mã và khi nào nên hợp nhất.

  • Thay vì chỉ nhắm đến các commit nhỏ, cũng có thể thêm một commit mới để sửa lỗi mà không cần hoàn tác một commit lớn.

    • Chưa rõ vì sao những đợt refactor lớn lại luôn bị xem là xấu.
    • Tạo ra cấu trúc độc lập sẽ tốt hơn là cố ép nhét vào module hiện có.
    • Khi thiết kế API, có thể tổ chức các buổi thảo luận thiết kế thay cho chỉ dựa vào unit test.
  • Khả năng kiểm thử có liên quan đến thiết kế tốt. Nếu thứ gì đó không dễ kiểm thử, đó có thể là dấu hiệu cho thấy thiết kế cần được thay đổi.

    • Mã kiểm thử cũng nên được rà soát theo những cách khác.
  • Cần cẩn thận khi kiểm thử các tính năng của framework. Framework có thể thay đổi theo thời gian.

    • Một vai trò quan trọng của kiểm thử là xác nhận xem việc nâng cấp dependency có an toàn hay không.
  • Về kích thước commit, nên hướng tới các commit có thể dễ dàng hoàn tác khi cần đảo ngược một thay đổi cụ thể.

  • Các công ty muốn có codebase ổn định, nhưng vẫn cần refactor liên tục. Điều này có thể xung đột với tính ổn định.