• 这些代码,差点把我气出内伤


    先问大家一个小问题:你觉得看别人代码累,还是自己写代码累?

    我相信有很多朋友会说,当然是自己写代码累了,要思考逻辑、要动手敲键盘,身心俱疲啊;但是,如果你需要经常阅读别人的代码,尤其是烂代码,答案就不一定了。

    因为自己写代码,逻辑是自己来梳理的、代码自己是熟悉的;但是看别人的代码,你就要去理解别人的代码逻辑,再加上烂代码的加持,可能很简单的逻辑,你都得看半天才能懂。所以很多大佬在面对前人的 “屎山” 项目时,宁愿自己重写,也不去读烂代码。

    举个夸张的例子:让你实现 1 + 1 的求和

    自己写:

    let sum = 1 + 1;
    

    某烂代码可能是:

    1. let a = {};
    2. let b = {};
    3. a.toString = function() {
    4.   return 1;
    5. };
    6. b.valueOf = function() {
    7.   return "1";
    8. };
    9. let sum = a + b;

    把简单的逻辑搞复杂,便是绝大多数程序员的拿手好戏(当然也包括我)。

    因为我从大学就开始带团队做项目了嘛,所以经常会审查团队同学的代码,做好二次校验。包括现在虽然开公司了,前端 / 后端同学的代码,也都会在我这过一遍才会发布上线。

    总之算是看了很多代码,其中有一些真的是让我哭笑不得。下面给大家分享一些代码片段出来,希望大家 不要学习 。

    1、过于抽象的命名

    还记得咱们刚学编程的时候,变量的命名都是用的 abcdefg。

    自学时这么写完全没问题,但是在实际项目中,如果还用过于抽象的命名,那就不太合适了。

    比如下面这段,大家能看懂是什么意思么?

    1. const [l, setL] = useState<boolean>(false);
    2. const [d, setD] = useState<any>();

    但如果我稍微完善下命名呢:

    1. const [loading, setLoading] = useState<boolean>(false);
    2. const [data, setData] = useState<any>();

    很多同学应该立刻能看懂了,一个是 “加载中” 的变量,一个是 “存储数据” 的变量。

    最好的代码应该是不用写注释的,因为 代码即注释 。如果你能把命名做到 “见名知义”,看代码的人会极度舒适。

    2、有深度的代码

    比如下面这段:

    1. if (condition1) {
    2.   // 逻辑 A
    3.   if (condition2) {
    4.     // 逻辑 B
    5.     if (condition3) {
    6.       // 逻辑 C
    7.       if (condition4) {
    8.         // 逻辑 D
    9.       }
    10.     }
    11.   }
    12. }

    这里的深度有 2 重含义,一重是字面意思:代码一层嵌一层、深不见底;另外一重是指真的 “很有深度” —— 指让人看不懂。

    阅读这段代码的感觉就像是你在一座巨大的迷宫里,每次转弯都要判断下是左还是右,最后你只会迷失方向。

    如何改进呢?

    最简单直接的方法就是使用早返回策略(early return):

    1. if (!condition1
    2.  // 逻辑 A
    3.  return;
    4. if (!condition2)
    5.   // 逻辑 B
    6.  return;
    7. if (!condition3)
    8.   // 逻辑 C
    9.  return;
    10. if (!condition4)
    11.   // 逻辑 D
    12.  return;

    这样,你的代码就清晰了很多,阅读这种代码的感觉就像是走在了一条直路上,前方的路一目了然。

    当然,还可以将一些逻辑抽象成独立函数来简化代码,或者使用设计模式来优化。

    怎么判断一段代码是否过于复杂、应该优化了呢?这里提到一个概念:圈复杂度 ,这是一种量化代码复杂程度的概念。通常你代码中的 if else 分支越多,圈复杂度就越高,代码就越复杂。

    企业中一般建议圈复杂度不要超过 10 - 15,我个人的编码习惯是一般不会在代码中出现 3 层以上的嵌套(除非必要)。

    3、冗余代码

    这是我遇到最多的问题!分为 3 种情况:

    1. 能用一行代码搞定,偏偏要写 10 行

    2. 能用一个变量或函数搞定,偏偏每次都是复制粘贴重复写

    3. 没有用到的代码,又不舍得删除

    举个例子,下面这段前端代码,大家觉得有什么问题:

    这是我们鱼聪明 AI 前端开发过程的真实代码

    1. <Spin spinning={!(currDownloadUrl || originPictureUrl || pictureUrl)}>
    2. {type === DRAW_APP ? (
    3. drawImg(image)
    4. ) : (
    5. drawImg(currDownloadUrl || originPictureUrl || pictureUrl)
    6. )}
    7. </Spin>

    第一眼看到这段代码时,我就发现了,判断 spinning(旋转)的代码逻辑比较复杂,包含了两个 || 逻辑。而下面的 drawImg 函数的参数中,又包含了这段一模一样的逻辑。这段判断,其实就是冗余代码,完全没必要写两遍!

    我调整过后的代码如下:

    1. // 要展示的图片地址
    2. const showPictureUrl = currDownloadUrl || originPictureUrl || pictureUrl;

    直接定义一个通用变量,写上清晰的注释,其他地方要使用时就无需关注内部判断逻辑,看注释就行了。

    这就是所谓的 DRY 原则(Don't Repeat Yourself) ,尽量避免代码冗余。如果你在多处写下相同的代码,那么当需要修改这段代码时,你就需要在所有这些地方都修改,漏一个地方就是一个 Bug。

    还有,关于项目中没有用到的函数和变量,如果你近期没有使用计划,不妨就删除或者注释掉,别舍不得。利用好 Git 版本控制系统,只要你的代码提交信息写得好,要用到被删掉的历史代码时,去提交记录里找即可。

    注意,如果是学习时写代码,多保留一些也是合理的。但企业项目中,项目代码精简凝练些会更好。

    这里打个比方,写代码就像是我在公司里堆东西,一开始总觉得多一点没关系,反正有空间。但是,冗余代码就像是杂物,会越堆越多,迟早有一天,会影响到你。

    大概就分享到这里,请大家在评论区 @ 出你写烂代码的同事吧 🐶 

  • 相关阅读:
    鸿蒙OpenHarmony开发板解析:【特性配置规则】
    Power BI 的 各种限制 和 DataFlow模式
    Namomo Summer Camp 23 Day 1
    Linux基本指令(下)——“Linux”
    数据库系统概论的一些知识点
    openGauss学习笔记-86 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT部署配置
    RocketMQ——MQ基础知识
    SpringBoot整合RabbitMQ
    python3 可变对象与不可变对象
    FPGA板卡启动以及LED灯带调试
  • 原文地址:https://blog.csdn.net/liuxing__jacker/article/details/132928746