Tiết kiệm thời gian và sự tỉnh táo của bạn - Ngoài định dạng tiếng kêu.
Một trong những điều tác động nhất bạn có thể làm với tư cách là Kỹ sư phần mềm là tự động hóa các hoạt động lặp đi lặp lại. Đặc biệt, một lĩnh vực thường đáng được tự động hóa hơn là xem xét mã.
Hôm nay, chúng ta sẽ xem xét cách giảm tải kiểm tra kiểu và thực thi định dạng clang cho các ngôn ngữ C, C ++, C #, Java, JavaScript, Objective-C và Objective-C ++. Chúng tôi sẽ thảo luận thêm về các tùy chọn nâng cao hơn cho C ++ bằng cách sử dụng clang-slim và cách tích hợp cả hai công cụ với quy trình làm việc yêu cầu git pull.
định dạng clang
Bạn có thể đã nghe nói về định dạng clang, vì nhiều IDE sử dụng nó (thông qua libformat) làm giải pháp định dạng mã tiêu chuẩn. Chúng tôi quan tâm đến định dạng clang vì lý do tương tự, để định dạng mã thống nhất.
Mặc dù điều này không loại bỏ sự xáo trộn ban đầu khi thiết lập một kiểu mã, nhưng nó sẽ loại bỏ bất kỳ khả năng gây mất tập trung nào trong quá trình xem xét mã.
Lựa chọn phong cách của bạn
Nhược điểm của việc sử dụng định dạng clang là bạn cần phải chọn hoặc xác định một định dạng mã nghiêm ngặt và rất nhiều tùy chọn mà định dạng clang cung cấp có thể áp đảo.
Vì vậy, trước tiên, hãy cân nhắc xem bạn thuộc loại nào trong số hai loại này:
- Bạn không có mã tồn tại từ trước hoặc không quan tâm đến sự khác biệt được tạo ra bằng cách định dạng lại cơ sở mã.
- Bạn muốn khớp kiểu mã gần với cơ sở mã hiện tại, giảm thiểu sự khác biệt về định dạng lại.
Bạn cũng có thể sử dụng một trong các kiểu được xác định trước làm đường cơ sở và xếp lớp các thay đổi của bạn lên trên. Ví dụ, đây là kiểu thông thường của tôi cho C ++:
Nếu bạn quan tâm, có một số công cụ tự động phát hiện cấu hình định dạng từ các mẫu mã:
- tiện ích mở rộng công cụ điện clang cho Visual Studio
- unformat (dựa trên python)
- clang-unformat (dựa trên C ++)
Trên hết, kết quả cuối cùng khó có thể hoàn toàn khác biệt. Nếu bạn hiện không sử dụng công cụ thực thi định dạng, bạn sẽ có một số mâu thuẫn về kiểu dáng. Hãy chuẩn bị để đi sâu vào cấu hình để tinh chỉnh phong cách.
Khi bạn có cấu hình dựa trên kiểu được xác định trước hoặc kiểu được phát hiện, hãy lưu trữ nó trong một .clang-format
tệp trong thư mục gốc của dự án.
Cam kết trước
Mặc dù hiện tại chúng ta đã có một kiểu mã, nhưng chúng ta cần một bước quan trọng nữa để giảm bớt công việc thủ công trong quá trình xem xét mã. Chúng tôi cần tự động thực thi kiểu mã cho mọi đoạn mã trước khi nó đi vào kho lưu trữ git của chúng tôi (lưu ý rằng các hệ thống quản lý phiên bản khác cung cấp các tiện ích tương tự).
Việc thực thi này có hai phần: thứ nhất, trên máy của nhà phát triển như một phần của quy trình làm việc điển hình của họ và thứ hai, trong khi yêu cầu kéo.
Hầu hết các IDE sẽ .clang-format
tự động nhận một tệp, một số sẽ yêu cầu bạn bật cài đặt:

Giải pháp IDE phải là đủ cho hầu hết các nhà phát triển. Tuy nhiên, nếu bạn giống như tôi và đôi khi chỉnh sửa tệp từ các trình chỉnh sửa cơ bản, bạn có thể hưởng lợi từ một lớp thực thi nữa bằng cách sử dụng móc cam kết trước.
Bạn có thể sử dụng hook pre-commit , nhưng chúng tôi sẽ thực thi nhiều hơn với clang-slim, vì vậy, thay vào đó, chúng tôi sẽ sử dụng pre-commit framework .
Khung công tác cung cấp một cách thuận tiện để kéo các móc cam kết trước khác nhau mà bạn có thể cần chỉ bằng cách tham khảo các kho lưu trữ có chứa các móc đó:
Với tệp này trong thư mục gốc của kho lưu trữ của chúng tôi, tất cả những gì chúng ta cần làm là chạy pre-commit install
một lần trên mỗi kho lưu trữ để định cấu hình các hook. Sau đó, nếu chúng tôi cố gắng xác nhận một tệp có định dạng không chính xác, tệp đó sẽ tự động được định dạng lại và khung pre-commit sẽ cho chúng tôi biết để chúng tôi có thể kiểm tra sự khác biệt:

Bạn có thể kiểm tra kết quả cuối cùng tại đây: github.com/HappyCerberus/article-sanity-format .
Luồng yêu cầu kéo
This leaves us with one more line of defence. While setting up local enforcement on developer machines is very easy (running pre-commit install
once), we still want to ensure that unformatted code doesn’t get into the repository when someone forgets.
Since this is all about limiting manual work on code reviews, we will piggyback on the pull request workflow, and since we are already using pre-commit, we will use its git action. There is no additional configuration required, and the pre-commit CI only needs to be authorized by clicking on the “Sign in with Github” button.
Once enabled, pull requests will be automatically formatted to conform to the configured code formatting:

clang-tidy
Both clang-format and pre-commit are multi-lingual tools. In this section, we will discuss clang-tidy, which is a C++ specific static analyzer.
You might be familiar with clang-tidy. However, you might not know that clang-tidy offers a suite of highly configurable code style checks and fixes. These fixes cover changes to code that go beyond formatting, such as the style of naming (e.g. CamelCase vs snake_case).
There are too many checks to cover exhaustively. Fortunately, most of the checks under the readability category are no-brainers and should be enabled in any repository (in their default configuration).

The primary check relating to code style is readability-identifier-naming. This check enforces case style (e.g. CamelCase, snake_case) and prefixes and suffixes for all identifiers of a particular category (with support for Hungarian notation coming soon). For inspiration, you can search for ready-made styles, like the Google code style.
Finally, here are the checks that are either configurable or are worth considering but not applicable universally:
- warn about member functions that can be const and aren’t
readability-make-member-function-const - warn about member functions that can be static and aren’t
readability-convert-member-functions-to-static - enforce a brace block for if, for, while…
readability-braces-around-statements - enforce uppercase literal suffixes, e.g.
0U
instead of0u
readability-uppercase-literal-suffix - heuristically detect swapped function call arguments
readability-suspicious-call-argument - function size and complexity (will require fine-tuning for your code-base)
readability-function-cognitive-complexity, readability-function-size - magic number detection (might require fine-tuning for your code-base)
readability-magic-numbers
One issue with clang-tidy is that it requires the compilation database to function correctly. CMake and Bazel can emit this information automatically; for other build systems, you can use a build interceptor tool like Bear. For simplicity, I will be demonstrating the integration using CMake:
The local workflow is very similar to just using clang-format, with the caveat that clang-tidy is generally more verbose:

The downside of needing to run CMake is that we can no longer use pre-commit CI. Instead, we need to write our own Github action. You have several options for how you want this to work. I opted for an action that attempts to fix the formatting and style, and if it fails, it closes the pull request.
- pull request with automated fix succeeding
- pull request auto-closed requiring manual intervention
Final remarks and links
One aim of this article is to be inspirational. Many checks can be added to the pre-commit framework or straight through git hooks. However, take care to maintain parity between the CI and local environments.
Locally run checks (and especially auto-fixes) have effectively zero downtime and are entirely localized to the developer in question. This isolation will allow you to scale productivity as you build up a suite of style checking tools.
Links for clang-format-only automation
- demo repository
- auto-formatted pull request
- clang-format style options
- pre-commit hooks (not all compatible with pre-commit CI)
- demo repository
- GitHub action to run on pull requests
- example pull requests: automatically fixed, failed and closed
- clang-tidy checks
Cảm ơn bạn đã đọc. Tôi viết về chủ đề Kỹ thuật phần mềm và ngôn ngữ lập trình phụ trợ.
Tôi cũng xuất bản video trên YouTube . Bạn có câu hỏi? Đánh tôi trên Twitter hoặc LinkedIn .