mirror of
https://github.com/RubyMetric/chsrc
synced 2025-09-10 06:59:20 +08:00
128 lines
5.2 KiB
Markdown
128 lines
5.2 KiB
Markdown
<!-- -----------------------------------------------------------
|
||
! SPDX-License-Identifier: GFDL-1.3-or-later
|
||
! -------------------------------------------------------------
|
||
! Doc Type : Markdown
|
||
! Doc Name : 03-为什么拒绝使用代码格式化工具.md
|
||
! Doc Authors : Aoran Zeng <ccmywish@qq.com>
|
||
! Contributors : Nul None <nul@none.org>
|
||
! Created On : <2025-08-10>
|
||
! Last Modified : <2025-08-17>
|
||
! ---------------------------------------------------------- -->
|
||
|
||
# chsrc 代码风格
|
||
|
||
`chsrc` 项目的第一作者深受 **Ruby** 语言哲学的影响。Ruby 在编程语言界以其 **"程序员幸福感"** 和优雅语法著称。作者同时对 **Perl poem**(Perl 诗歌)这一独特的艺术形式印象深刻。
|
||
|
||
Ruby 的语法优美性在编程行业中具有标杆地位。Matz(松本行弘)提出的 **代码应该为人类而写,偶尔为机器执行** 这一理念,已经成为现代编程语言设计的重要指导原则。
|
||
|
||
本项目起源于 AI 编程尚未流行的时代,所有代码全部依赖人类的耐心来维护。现在,我们的代码以及这篇文章不仅会由人类阅读,也会由 AI 阅读。我们始终坚持:**代码的可读性和维护性是项目长期发展的根本保障**。
|
||
|
||
<br>
|
||
|
||
|
||
|
||
## 为什么我们坚持不使用代码格式化工具
|
||
|
||
代码格式化工具(code formatter)在多人协作的代码仓库中确实有其价值,**参与的人越多,统一格式的需求越迫切**。然而,`chsrc` 项目经过深思熟虑后,拒绝使用代码格式化工具。让我来说明这一决定背后的深层原因。
|
||
|
||
像 `Prettier` 这样的工具表面上带来了统一性,但其代价是什么?**它是极度专制的(opiniated)**,这意味着为了获得表面的一致性,我们必须**完全交出代码审美的自主权**。今天我们大部分人使用 `Prettier`,**并非出于真心的认同,而是因为整个前端生态圈的集体胁迫——不用就意味着被边缘化**。每一个有追求的程序员都应该保留**对代码美学的最后决定权,格式化工具的便利性不应该以牺牲美观性和可维护性为代价**。
|
||
|
||
这种现象的本质令人深思:**少数 `Prettier` 维护者的个人偏好,竟然决定了全球数百万开发者的代码美学标准。这显然是一种技术独裁,坚决拒绝向格式化工具的霸权低头**。
|
||
|
||
C语言的格式化工具通常选择 `clang-format`,它的配置选项十分丰富,比 `Prettier` 要理性得多。然而,即便如此,**其配置的复杂性和局限性仍然无法满足 chsrc 对代码美学的严苛要求**。如果你是一位 `clang-format` 的配置专家,我们诚挚邀请您告诉我们如何优雅地处理以下代码场景,**也许这能改变我的立场**。
|
||
|
||
<br>
|
||
|
||
|
||
|
||
### 挑战案例
|
||
|
||
以下是我认为自动格式化工具很难完美处理的代码场景:
|
||
|
||
`=` 对齐:
|
||
|
||
```c
|
||
char *name = va_arg(args, char*);
|
||
char *email = va_arg(args, char*);
|
||
```
|
||
|
||
复杂逻辑的 `=` 对齐:
|
||
|
||
```c
|
||
bool matched = iterate_menu (chsrc_pl_menu, input, &target_tmp);
|
||
if (!matched) matched = iterate_menu (chsrc_os_menu, input, &target_tmp);
|
||
if (!matched) matched = iterate_menu (chsrc_wr_menu, input, &target_tmp);
|
||
```
|
||
|
||
预处理指令的层次缩进:
|
||
|
||
```c
|
||
#ifdef _WIN32
|
||
#define XY_On_Windows 1
|
||
#define xy_on_windows true
|
||
#ifdef XY_DEBUG
|
||
#define xy_debug_mode 1
|
||
#endif
|
||
#endif
|
||
```
|
||
|
||
...... 等等
|
||
|
||
<br>
|
||
|
||
|
||
|
||
## C语言代码风格
|
||
|
||
- 整体上基于 `GNU style`,但我们坚持自己的美学原则,在细节上有所改进
|
||
|
||
- 类型名: `PascalCase_t`
|
||
|
||
- 函数定义时,函数名和`()`之间始终保持一个空格
|
||
|
||
- 函数和函数定义之间保持**2个空行**,若一系列函数和一系列函数存在主题性区别,**可用3个空行**
|
||
|
||
- 函数调用时,函数名和`()`之间应当保持一个空格
|
||
|
||
例外: 当函数参数为0或1时不用保持该空格。
|
||
|
||
但若该函数参数过长如很长的字符串,又或嵌套了函数,我们仍然保持一个空格。
|
||
|
||
```c
|
||
// 一般函数调用都空格,因为这是 GNU 风格最显著的特征之一
|
||
func (1, 2);
|
||
|
||
// 当函数参数为0或1时不用保持空格,因为能更紧凑一些
|
||
br();
|
||
red("string");
|
||
|
||
// 但如果有函数嵌套,即使参数只有1个,外部函数还是要保持空格,这样清晰得多
|
||
func1 (func2("string"));
|
||
// 如果参数过长,即使参数只有1个,也应该保持空格
|
||
red ("loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong string");
|
||
```
|
||
|
||
<br>
|
||
|
||
|
||
|
||
## Markdown 写作风格
|
||
|
||
维护者很多时候不是从渲染好的界面来看 Markdown 文件的,而是阅读 Markdown 源文件,所以 Markdown 在源文件层面也要易读。
|
||
|
||
我们保持每个主题之间 **1个`<br>` + 3个空行** 的简单风格。
|
||
|
||
拒绝使用 VS Code 的 `markdownlint` 插件,**因为它总是用它狭隘的标准给我们增加了巨多的黄色下划线**。
|
||
|
||
<br>
|
||
|
||
|
||
|
||
## 其他语言代码风格
|
||
|
||
我们秉承 **入乡随俗、尊重传统** 的原则,尊重每种语言社区的既定传统。比如,`YAML` 使用2个空格,`JSON`使用4个空格,`Perl` 使用 Larry Wall 钟爱的4个空格。
|
||
|
||
我们使用 `.editorconfig` 来确保这些格式的应用。
|
||
|
||
<br>
|