垃圾代码编写指南_C语言版

原文链接:https://kashima19960.github.io/2025/03/10/垃圾代码编写指南_C语言版/

前言

作为一名程序员,通常都需要跟别人协作编写代码。https://github.com/trekhleb/state-of-the-art-shitcode 是一个教你如何编写 💩 代码的教程,但是这个教程的代码示例是用 JavaScript 编写的,在本文我将其转成了经典的C语言,并且将一些语言风格写成符合中国程序员的编码习惯

代码编写原则

💩 定义变量的时候,尽可能用混淆的方式

变量命名的时候尽可能写短,能节省敲代码的时间

正确做法 👍🏻

int a = 42;

错误做法 👎🏻

int age = 42;

💩 采用变量/函数的混合命名风格

命名风格要采取多样化,彰显个人魅力

正确做法 👍🏻

int wWidth = 640;
int w_height = 480;

错误做法 👎🏻

int windowWidth = 640;
int windowHeight = 480;

💩 永远不要写注释

程序员最讨厌的两件事是:

  1. 别人的代码不写注释
  2. 别人让自己给代码写注释

正确做法 👍🏻

const int cdr = 700;

错误做法 👎🏻

注释应该包含一些"为什么"而不是"做了什么"。如果代码中的"做了什么"不清楚,那么代码可能太混乱了。

// 700ms的数量是根据UX A/B测试结果进行经验计算的。
// @查看: <详细解释700的一个链接>
const int callbackDebounceRate = 700;

💩 尽量用母语写注释

中国人写注释当然要用中文,怎么可能用英语这种通用语言,当然是怎么爽怎么来

正确做法 👍🏻

// 错误时隐藏模态窗口。
closeModal(0);

错误做法 👎🏻

// Hide modal window on error.
closeModal(0);

💩 尽可能混合各种格式风格

跟上述变量命名的原则一样,保持个性化~

正确做法 👍🏻

char* i[] = {"tomato", "onion", "mushrooms"};
char* d[] = { "ketchup", "mayonnaise" };

错误做法 👎🏻

char* ingredients[] = {"tomato", "onion", "mushrooms"};
char* dressings[] = {"ketchup", "mayonnaise"};

💩 把代码都写到一行

正确做法 👍🏻

void parse_url_params(char* url, char* params) { char* p=strstr(url,"?");if(!p)return;p++;char* token=strtok(p,"&");while(token!=NULL){char* eq=strchr(token,'=');if(eq){*eq='\0';strcat(params,token);strcat(params,"=");strcat(params,eq+1);strcat(params,";");}token=strtok(NULL,"&");}}

错误做法 👎🏻

void parse_url_params(char* url, char* params) {
    // Find the '?' character
    char* p = strstr(url, "?");
    if (!p) return;
  
    // Skip the '?' character
    p++;
  
    // Parse each parameter
    char* token = strtok(p, "&");
    while (token != NULL) {
        char* eq = strchr(token, '=');
        if (eq) {
            // Separate key and value
            *eq = '\0';
            strcat(params, token);
            strcat(params, "=");
            strcat(params, eq + 1);
            strcat(params, ";");
        }
        token = strtok(NULL, "&");
    }
}

💩 不要做异常处理

程序中任何可能出现异常的代码片段,没必要去捕捉,也不要写日志进行记录,更不要弹出啥错误提示,让你的协作者自己猜可能的报错原因就好了

正确做法 👍🏻

FILE* file = fopen("important.dat", "r");
if (file == NULL) {
    // tss... 🤫
}

错误做法 👎🏻

FILE* file = fopen("important.dat", "r");
if (file == NULL) {
    perror("Error opening file");
    // and/or
    log_error("Failed to open important.dat");
}

💩 大量使用全局变量

吕蒙过江,我也过江,别的函数能使用的变量,我为什么不能访问到?所以要多使用全局变量

正确做法 👍🏻

int x = 5;

void square() {
    x = x * x;
}

int main() {
    square(); // Now x is 25.
    return 0;
}

错误做法 👎🏻

int x = 5;

int square(int num) {
    return num * num;
}

int main() {
    x = square(x); // Now x is 25.
    return 0;
}

💩 多创建一些用不到的变量

以备不时之需。

正确做法 👍🏻

int sum(int a, int b, int c) {
    const int timeout = 1300;
    const int result = a + b;
    return a + b;
}

错误做法 👎🏻

int sum(int a, int b) {
    return a + b;
}

💩 如果你的编程语言允许,不要指定类型和/或不做类型检查

代码跑的怎样你别管,你就说能不能跑吧

正确做法 👍🏻

void* sum(void* a, void* b) {
    // 不做类型检查,直接转换并希望一切顺利
    return (void*)((long)a + (long)b);
}
    // 在这里尽情享受无拘无束的乐趣
int main() {
    char* result1 = sum("hello", "world");  // 未定义行为
    int result2 = (int)sum((void*)5, (void*)10);  // 可能行得通?
    return 0;
}

错误做法 👎🏻

int sum(int a, int b) {
    return a + b;
}

int main() {
    int result = sum(5, 10);  // 类型安全,意图明确
    return 0;
}

💩 你需要有一段永远无法执行到的代码

没想到吧 jojo 这就是我的逃跑路线!

正确做法 👍🏻

int square(int num) {
    if (num == 0) {
        return 0;
    }
    else {
        return num * num;
    }
    return -1; // 这就是我的逃跑路线哒!哈哈哈
}

错误做法 👎🏻

int square(int num) {
    if (num == 0) {
        return 0;
    }
    return num * num;
}

💩 三角形原则

像鸟一样筑巢,一层又一层。

正确做法 👍🏻

void someFunction() {
    if (condition1) {
        if (condition2) {
            beginAsyncOperation(params, callback);
            if (callbackCalled) {
                if (result) {
                    for (;;) {
                        if (condition3) {
                            // 代码逻辑
                        }
                    }
                }
            }
        }
    }
}

错误做法 👎🏻

void someFunction() {
    if (!condition1 || !condition2) {
        return;
    }
  
    beginAsyncOperation(params, callback);
    if (!callbackCalled || !result) {
        return;
    }
  
    for (;;) {
        if (condition3) {
             // 代码逻辑
        }
    }
}

💩 搞乱缩进

避免使用缩进,因为它们会使复杂的代码在编辑器中占用更多空间。如果你不想避免它们,那就把它们弄乱。

正确做法 👍🏻

const char* fruits[] = {"apple",
"orange", "grape", "pineapple"};
    const char* toppings[] = {"syrup", "cream", 
                "jam", 
                "chocolate"};
char desserts[100][100];
int i = 0;
for (int f = 0; f < 4; f++) {
for (int t = 0; t < 4; t++) {
    sprintf(desserts[i], "%s with %s",
fruits[f],toppings[t]);
    i++;}}

错误做法 👎🏻

const char* fruits[] = {"apple", "orange", "grape", "pineapple"};
const char* toppings[] = {"syrup", "cream", "jam", "chocolate"};
char desserts[100][100];
int i = 0;

for (int f = 0; f < 4; f++) {
    for (int t = 0; t < 4; t++) {
        sprintf(desserts[i], "%s with %s", fruits[f], toppings[t]);
        i++;
    }
}

💩 总是将你的逻辑判断的变量命名为 flag

布尔变量统一命名为 flag ,如果有多个逻辑变量,那就定义成 flag+数字,以此类推
至于这个逻辑变量到底是判断啥逻辑的,你别管,让你的协作者猜就好了

正确做法 👍🏻

bool flag = 1;

错误做法 👎🏻

bool isDone = 0;
bool isEmpty = 0;

💩 长函数比短函数更好

不要将程序逻辑分割成可读的片段。如果你的IDE搜索功能出故障,你将无法找到必要的文件或函数,那该怎么办?

  • 10000 行代码在一个文件中是可以的。
  • 1000 行的函数体是可以的。
  • 在一个 service.c 中处理许多服务(第三方和内部的,还有一些辅助工具、手写的数据库ORM和套接字实现)?没问题。

💩 避免用测试覆盖你的代码

这是重复和不必要的工作量。代码能跑就行了,还测试啥

💩 尽可能避免使用代码检查工具

按照你想要的方式编写代码,尤其是当团队中有多个开发人员时。这是一种"自由"原则。

💩 在没有 README 文件的情况下开始你的项目

写啥说明文档啊,让用户自己摸索就好了

💩 代码冗余是有必要的

不要删除你的程序没有使用的代码。最多,注释掉它。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值