Chuyển tới nội dung chính

Best practices

  1. Sử dụng const khi có thể

    Khi một biến, tham chiếu, hoặc con trỏ không cần thay đổi giá trị sau khi khởi tạo, hãy khai báo nó với từ khóa const. Điều này giúp ngăn chặn các thay đổi ngoài ý muốn và làm mã dễ hiểu hơn.

    const int MAX_SIZE = 100;
    void printName(const std::string &name);
  2. Sử dụng auto cho kiểu suy diễn tự động

    auto giúp bạn tránh phải lặp lại các kiểu dài, đặc biệt khi các kiểu đó đã rõ ràng từ ngữ cảnh. Tuy nhiên, không lạm dụng auto nếu nó làm mã khó đọc.

    auto it = myMap.begin(); // Tự động suy diễn kiểu của it
  3. Sử dụng smart pointers thay vì con trỏ thô (raw pointers)

    std::shared_ptr, std::unique_ptr, và std::weak_ptr giúp quản lý bộ nhớ tự động và ngăn ngừa rò rỉ bộ nhớ. Hạn chế sử dụng con trỏ thô trừ khi thật sự cần thiết.

    std::unique_ptr<int> ptr = std::make_unique<int>(10);
  4. Sử dụng range-based for loop cho các containers

    Vòng lặp range-based giúp mã ngắn gọn hơn và dễ đọc khi duyệt qua các phần tử của container.

    std::vector<int> numbers = {1, 2, 3};
    for (const auto &num : numbers) {
    std::cout << num << std::endl;
    }
  5. Khai báo biến gần với nơi sử dụng

    Khai báo biến chậm nhất có thể, ngay khi bạn cần đến nó để làm mã rõ ràng hơn. Tránh khai báo tất cả biến ở đầu hàm trừ khi cần thiết.

  6. Sử dụng enum class thay vì enum

    enum class giúp tránh xung đột tên và tăng tính an toàn vì các giá trị enum class không thể chuyển đổi ngầm định sang kiểu nguyên.

    enum class Color { Red, Green, Blue };
    Color color = Color::Red;
  7. Sử dụng nullptr thay vì NULL hoặc 0

    nullptr là con trỏ rỗng mới trong C++11, an toàn hơn và làm mã dễ hiểu hơn.

  8. Tránh sử dụng macro trừ khi thật sự cần thiết

    Macro có thể làm mã khó hiểu và khó bảo trì, đặc biệt khi thay thế bằng hằng constexpr, const hoặc inline là hợp lý hơn.

    constexpr int MAX_SIZE = 100;
  9. Tránh dùng quá nhiều inline

    inline nên dùng cho các hàm nhỏ, thường là những hàm được định nghĩa ngay trong lớp. Tránh đánh dấu các hàm lớn inline vì chúng có thể làm mã tăng kích thước không cần thiết.

  10. Chia nhỏ hàm và giữ mỗi hàm làm một việc duy nhất

    Mỗi hàm nên làm một công việc nhất định và được đặt tên mô tả rõ ràng công việc đó. Tránh viết các hàm quá dài hoặc đa nhiệm.

  11. Sử dụng std::arraystd::vector thay vì mảng C-style

    std::arraystd::vector an toàn hơn mảng C-style vì chúng tự động quản lý kích thước và các vấn đề biên.

  12. Sử dụng std::movestd::forward để tối ưu hiệu suất

    std::movestd::forward giúp di chuyển dữ liệu thay vì sao chép nó, tối ưu hóa hiệu suất khi làm việc với các đối tượng lớn hoặc các tài nguyên không sao chép được.

  13. Tránh copy không cần thiết với tham chiếu const trong hàm

    Nếu một tham số là đối tượng lớn và không cần thay đổi, hãy truyền nó dưới dạng tham chiếu const & để tránh việc sao chép không cần thiết.

    void processData(const std::vector<int> &data);
  14. Cẩn trọng khi sử dụng using namespace

    Tránh sử dụng using namespace std; trong các file header hoặc file lớn vì nó có thể gây ra xung đột tên. Thay vào đó, khai báo cụ thể tên cần dùng hoặc sử dụng namespace trong một phạm vi hẹp.

  15. Sử dụng std::optional cho các giá trị có thể không tồn tại

    std::optional giúp đại diện cho các giá trị có thể trống hoặc không xác định, làm mã rõ ràng hơn thay vì sử dụng các giá trị đặc biệt (như -1) để chỉ trạng thái trống.

  16. Sử dụng std::chrono cho thời gian và thời lượng

    Thư viện <chrono> cung cấp các kiểu dữ liệu an toàn và mạnh mẽ cho thời gian và thời lượng, thay vì sử dụng int hoặc float.

  17. Giải phóng tài nguyên bằng RAII (Resource Acquisition Is Initialization)

    RAII giúp quản lý tài nguyên (bộ nhớ, file, mutex, v.v.) bằng cách gán chúng vào các đối tượng có vòng đời tự động. Khi đối tượng ra khỏi phạm vi, tài nguyên sẽ tự động được giải phóng.

  18. Viết tài liệu và bình luận một cách hợp lý

    Bình luận mã để giải thích ý định của bạn, đặc biệt khi mã phức tạp hoặc khó hiểu. Sử dụng tài liệu rõ ràng cho các hàm, lớp, và các tham số của chúng.

  19. Tuân thủ các quy ước đặt tên nhất quán

    Giữ một phong cách đặt tên nhất quán giúp mã dễ đọc và dễ bảo trì hơn. Ví dụ, có thể sử dụng camelCase cho tên biến và hàm, PascalCase cho tên lớp.

  20. Sử dụng các công cụ phân tích mã và kiểm tra bộ nhớ

    Các công cụ như valgrind, AddressSanitizer, và Clang-Tidy giúp phát hiện sớm lỗi bộ nhớ và các vấn đề tiềm ẩn.

  21. Viết unit test cho các đoạn mã quan trọng

    Unit testing giúp bạn kiểm tra các hàm và lớp riêng lẻ, đảm bảo rằng chúng hoạt động như mong đợi và giúp phát hiện lỗi sớm.

  22. Quản lý ngoại lệ

    • Throw exceptions for error handling: Sử dụng ngoại lệ để xử lý lỗi thay vì sử dụng mã lỗi cổ điển.
    • Noexcept specification: Sử dụng noexcept để xác định các hàm không ném ra ngoại lệ.
  23. Tối ưu hóa hiệu suất

    • Profile and optimize: Sử dụng công cụ profiling để xác định các điểm yếu trong mã của bạn và tối ưu hóa chúng.
    • Avoid premature optimization: Không nên tối ưu hóa quá sớm trước khi bạn biết rằng đó là điểm yếu thực sự.