V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iamee
V2EX  ›  程序员

我对于代码可读性的理解

  •  1
     
  •   iamee · 2023-07-07 16:23:51 +08:00 · 2695 次点击
    这是一个创建于 484 天前的主题,其中的信息可能已经有所发展或是发生改变。

    总在这个论坛看到有人强调所谓的代码可读性,但后来我发现这些人在说的所谓可读性非常肤浅。

    比如认为下面的代码中,方式 1 比方式 2 更可读。

    // JavaScript
    
    // 1
    if (condition) {
        return true;
    } else {
        return false;
    }
    
    // 2
    return !!condition;
    

    我的观点

    一、代码是否可读与程序员的实际水平强相关

    有效工作经验 5 年的程序员和有效工作经验 1 年的程序员对于可读性的理解是非常不同的(请注意是有效工作经验)。

    这里举个 C 语言的例子,一个 C 语言的初学者和对 C 语言比较熟悉的人,对于下面这段代码的可读性的评价一定是非常不同的:

    #define MAGIC_HEADER "tox3"
    
    if (*(uint32_t *)p != *(uint32_t *)MAGIC_HEADER) {
        report_error("Bad magic header");
    }
    

    二、奇技淫巧的“度”在哪里?

    1. 凡事都有极端,过度使用一些不值得的技巧(比如对于可读性的损伤很大,但对性能并没有帮助)是没有意义的。
    2. 取决于团队水平,最好不要在水平对于你来说过于低下而你又没有话语权的团队久留,会被同化。

    三、我认为的可读性

    我认为,一份真正可读的代码,一定是代码中隐含的想法,而不是这段代码是用 if else 还是三目运算符。

    我读过很多优秀开源项目的代码。其中某些项目甚至充满了大家对于“屎山”的评价标准:魔数乱飞、代码格式乱七八糟,还有各种奇技淫巧。但当你真的读懂了作者的奇妙想法,知道了这个项目的优秀的性能来自于优秀的设计,知道了写出这样的一个项目需要掌握多少高深的知识,你真的还会觉得这是“屎山”吗?

    四、项目质量和个人成长息息相关

    如果你想获得有效的工作经验,一定要远离业务代码!!对于代码的良好品味,是很难通过看书习得的,唯一的途径就是参与一些水平远在自己之上的人领导的项目。如果确实没办法找到这样的工作,可以考虑在业余时间参与感兴趣的开源项目。

    27 条回复    2023-07-08 21:44:27 +08:00
    tool2d
        1
    tool2d  
       2023-07-07 16:36:13 +08:00
    "一定要远离业务代码", 太理想化了,公司招人进来,就是为了写业务代码。

    只能说,写业务代码也别太敷衍。一般来说,重构个几次后,能让自己满意就够了。

    同样是程序员,项目不用,语言不同,代码可能天差地别。
    Pipecraft
        2
    Pipecraft  
       2023-07-07 16:47:39 +08:00
    说的很好 👍
    iamee
        3
    iamee  
    OP
       2023-07-07 16:47:56 +08:00   ❤️ 1
    @tool2d 没办法,这就是现实。不能把话说死,但绝大部分业务项目都是屎山,参与这种项目对技术成长的帮助很有限。
    wu67
        4
    wu67  
       2023-07-07 16:56:56 +08:00   ❤️ 1
    其实在 v 站刷的时间久了, 你就会发现其实程序员群体的素质也是良莠不齐的, 他们对可读性的理解自然不同.

    更离谱的是, 在互联网人、程序员群体占比较大的本站, 也能看到“关于敏感数据存储是否要加密”类似的贴, 还有人觉得没必要加密的...

    反正我已经 block 了十来个以前觉得技术还不错的人, 越是细节的问题, 越能体现出观点的不同...
    ZSeptember
        5
    ZSeptember  
       2023-07-07 17:12:57 +08:00   ❤️ 1
    为什么要远离业务代码,如何远离业务代码,什么不是业务。
    产品业务代码,还是做基础设施,只是业务领域不同而已,和代码可读性没有必然联系。
    产品业务代码烂,很多时候时候是因为代码质量当时不是最关键的问题而已。。


    可读性也远远不是用了什么技巧什么的就不可读了。
    最重要的是封装,,比如命名语义化,写的函数,类,单一职责什么的。只要你封装的好,内部是否用了什么技巧不影响阅读。
    Leviathann
        6
    Leviathann  
       2023-07-07 17:16:15 +08:00   ❤️ 1
    什么叫远离业务?
    业务就是软件软件就是业务
    snarkprayer
        7
    snarkprayer  
       2023-07-07 17:22:16 +08:00   ❤️ 4
    读是行为,目的是理解意图,那么目标就应该是:容易理解+所有人的理解是一致的

    ```javascript
    // bad
    function delay(fn, time) {...}
    // good
    function delayExecute(fn, millisecond) {...}
    ```
    iamee
        8
    iamee  
    OP
       2023-07-07 17:36:31 +08:00
    @ZSeptember
    @Leviathann

    每个人对业务代码(贬义)的阈值不同,这里可以认为是对自己水平提升没有帮助的项目。
    yesterdaysun
        9
    yesterdaysun  
       2023-07-07 17:45:49 +08:00
    我觉得得先统一一下, 什么叫"可读性"

    我觉得可读性是一个偏主观的指标, 抛却主观的部分, 一定有一些相对"客观"的部分, 否则就变成评价一段代码"美不美"这样纯主观的东西了

    就比如你提到有些"大神"的代码, 魔数乱飞、代码格式乱七八糟,还有各种奇技淫巧, 从我看来奇技淫巧我可以接受, 但是魔数乱飞、代码格式乱七八糟这些部分我不能接受, 我可以承认这段代码它能跑, 能得到结果, 写他的人是个高手, 但是你要我承认它"可读".

    即使这样, 我也不会要求它"可读", 为什么? 因为可能这个人写这段代码的目的就不是为了可读, 比如曾经看到大神些的计算圆周率的代码, 3 行代码, 一堆 a,b,c,d,e,f 的变量, 各种魔数, 但是就是算出圆周率 1000 位了, 他写这段代码的目的就是为了炫技, 就是为了做到最短代码, 极致的技巧, 这个时候, "可读"是不必要的, 甚至追求的就是不可读, 反而这里的奇技淫巧才是最重要的

    但是同样的, 搬砖人有机会写这样的代码吗? 是没有的, 工作环境下, 写出能跑的代码是第一要务, 其次是可维护性高的代码, 而"可读性"能间接或直接的提高"可维护性", 所以我们都在追求可读性, 其中我认为相对客观的指标有不使用魔数, 代码格式整齐, 括号整齐, 含义正确清晰的命名, 职责清晰的接口/类/函数的划分, 正确的数据结构, 相对主观的部分是使用高级的语言技巧(闭包, 生成器函数, 新的语法), 惯用的高级技法, 设计模式, 特定算法等等

    我觉得你要对达成什么样的可读性先定义好, 比如我随便写一段算法代码 dp[i][j]=dp[i-1][j-1], 懂算法的人看到这段代码, 立刻知道我是在做动态规划的递推方程, 对他来说这段代码的可读性很高, 你给他换个变量名, 换个写法, 他可能反而认不出来这段代码在干什么, 但是你给一个算法小白看这个, 他只会觉得"可读性"很差.

    所以就像你说的"可读性"是和什么人看有很大关系的, 如果只是追求自己"可读", 那就自己定标准, 如果是追求所有团队成员"可读", 那就要用你的影响力, 让他们接受这个标准, 如果是和论坛上的人讨论"可读", 那最好只讨论相对客观的标准, 主观的部分注定辩不出结果

    比如我说这个技巧可以 3 行变一行, 又非常简洁, 但是就会有人不认可, 比如我说这个设计模式这样用很好, 但是就有人说你滥用设计模式, 老老实实写不好么, 这些都辩不出个所以然. 但是如果有人使用奇奇怪怪的变量名, 拼错单词的名字, 大量使用魔数, 喷他就没问题, 就算他嘴硬硬杠, 也不用管他, 因为其实我们都知道这样肯定是有问题的, 顶多被甩几句"又不是不能用","能跑就行","我看得懂"之类的
    vincent7245
        10
    vincent7245  
       2023-07-07 18:19:29 +08:00
    我想到了设计模式,之前有个直播写代码的程序员,粉丝还挺多的,他大言不惭的说搞设计模式的都是装逼。

    我一时不知道怎么反驳他。

    后来我想明白了一个问题,除了扩展性以外,所谓的设计模式,就是程序员之间约定好的代码语法,我看到这段代码用了什么设计模式,大概就能猜到是什么功能了。
    shyangs
        11
    shyangs  
       2023-07-07 18:35:58 +08:00   ❤️ 2
    不同母語的可讀性/偏好不一樣. 漢語 SVO, 日語 SOV 主賓動語序.

    比如,Java 物件導向看 Lisp 系會覺得一堆括號和閉包沒有可讀性. Lisp 系會覺得 lambda 是日常.

    JS 日常短路求值, 隨處可見. `var locale = navigator.language || navigator.browserLanguage;` 每天工作都看得到, 已經刻入母語底層 不用思考.

    Basic 系會覺得什麼短路求值, 沒有可讀性.
    flyqie
        12
    flyqie  
       2023-07-07 19:00:55 +08:00   ❤️ 1
    有些时候,先入为主的编程习惯和编程语言也可能会决定 可读性。

    这玩意真的非常非常主观。。
    8355
        13
    8355  
       2023-07-07 19:06:37 +08:00
    代码的可读性和实际水平非正相关
    我所接触的开发以 1-10 年为范围吧。
    1-2 年老老实实写,虽然性能可能烂但是可读性好,学习态度良好说说愿意改。
    3-4 年开源项目看的多,奇技淫巧学的多,魔法操作一对对 说还不愿意听 可读性最差的工作年限。
    5-10 年代码健壮度逐渐提升,能够考虑兜底方案,从代码开发阶段及时提出改进方案。

    个人理解的可接受奇技淫巧最主要的前提是性能有真实的提升或者其他代码的便利性有明显提升与此同时性能仅有少量降低,这些是可接受的。
    如果你的奇技淫巧没有性能提升可读性还变差就是垃圾,通常 ide 的代码提示也没有了,关联代码跳不过去,大概率应该与反射有关吧,除非你的需求真的于此有关。

    代码的可读性有很多方面就是通过代码的执行流程让人能够理解你的解决方案,有些为了性能的奇技淫巧应该加代码注释和文档辅助。

    至于你说的远离业务代码我不认同可能你以为的业务代码只有 curd 吧。。。
    就 curd 来说没有并发的 curd 和 qps 过万的 curd 是完全不同的领域。
    lanxinyuchs
        14
    lanxinyuchs  
       2023-07-07 20:32:05 +08:00   ❤️ 5
    好代码是 Don't let me think 。一个团队,共同开发一段代码,而每个人的代码驾驭能力不同,所以还是通俗易懂的好,让同事更 happy 。
    hez2010
        15
    hez2010  
       2023-07-07 20:37:17 +08:00
    谈可读性的前提是大家拥有相似的认知水平,认知水平相差太大就会导致一个人觉得很好读而另一个觉得不好读的情况发生。
    比如你对一个熟悉函数式语言的人讲使用 pattern matching 有助于提升可读性,他大概率会同意你的观点;而你对一个跟没有怎么接触过函数式语言的人讲这件事情,他大概率觉得你在胡扯,而反倒觉得尽可能使用基础的控制流语句才是提升可读性的方法。
    u20237
        16
    u20237  
       2023-07-07 20:43:30 +08:00
    举个例子 python 创建对象要让人能理解对象的含义,可以写很多很多的注释或父类或__doc__
    如果项目使用 ide ,让 ide 理解源码怎么做不触发 error 就 ok 。
    jones2000
        17
    jones2000  
       2023-07-07 20:45:36 +08:00
    看项目代码前,先看项目需求文档,项目设计文档, 等等说明性的文档,对项目和业务有了解在去看代码。 没有没脑的拿一段代码出来, 是谁都不知道干什么用的,更不要说什么可读性了, 你根本就不知道为什么要写这个代码。
    Helsing
        18
    Helsing  
       2023-07-07 20:47:50 +08:00 via iPhone
    有点扯

    可读性强的一个简单评判标准就是,可以让一个初级程序员能够比较轻易的理解

    至于你说的所谓大神的各种奇技淫巧,或许他们确实技术很厉害,但是并不能说明他们的代码可读性强
    424778940
        19
    424778940  
       2023-07-07 22:13:02 +08:00
    @lanxinyuchs 这才是看透本质的观点

    可读性不是一个绝对值, 而是以需要看懂代码的受众作为木桶, 里面技能最差的人的水平来定的
    大神+普通人+实习生的团队, 就要以能让实习生努努力就可以理解的水平来作为可读性的下限标准
    可读性大多数情况下还是为了让人快速上手和提高可维护性服务的, 所以要以大多数人的水平来定一个合适的下限

    奇技淫巧总是有的, 但用还是不用终究是取决于能带来什么好处, 是一时的方便, 还是能提高代码效率
    就拿 op 原贴中 magic header 例子来说, 确实省去了 strcmp 之类的比较字符串的操作提高了效率, 但如果我用的 hex 并不能表示可读字符或者表示的是特殊字符呢? 或者我大于 4 个字符呢?
    奇技淫巧脱离了上下文和实际场景是无法评判是用得好还是用的傻的, 所以拿这来体现不同段位程序员对可读性的认知是不合理的

    我自己也喜欢用这类强转类型引用之类的操作避免大量的内存拷贝, 也喜欢 casting 之类的操作, 但我一般都会至少写一句注释这是在干什么
    lmq2582609
        20
    lmq2582609  
       2023-07-07 23:02:08 +08:00
    上班而已,大部分招人进去都是写业务代码的,给开钱就别挑活。想提升当然可以,业余时间提升。
    Finnn
        21
    Finnn  
       2023-07-07 23:06:27 +08:00
    1. 可读性本身也不是硬性要求, 业务代码需要维护,追求可读性,基础设施/开源封装追求性能与高效,比如用位运算,语法糖
    2. 可读性的解读因人而异,每个人理解问题的心智负担并不一样, 太吃个人水平了
    比如 我还更喜欢 [,男,女][key] 代替 三目运算呢
    darkengine
        22
    darkengine  
       2023-07-08 10:23:46 +08:00
    可读性不好还能赖业务,头一次见。大家都不写业务代码,用爱发电吗。
    ruyu
        23
    ruyu  
       2023-07-08 10:42:20 +08:00
    因为业务代码太 low 了,只是对需求的描述,没什么技术含量,所以对其价值的衡量就只有可读性。高级的代码即使可读性差(按照初级程序员的标准),也是很有价值的。强调代码的可读性本身没错,问题是可能有些人会把 “可读性” 当作代码唯一的价值衡量标准,这就很糟糕了。一份代码看不懂,他说,什么乱七八糟的,可读性真差!
    mogg
        24
    mogg  
       2023-07-08 14:44:30 +08:00
    你举的两个例子 感觉可读性都不好……

    js
    ```js
    return Boolean(condition);
    ```

    c
    ```
    uint32_t magic_header (const char* c) {
    return *(uint32_t *)c;
    }

    magic_header(p) == magic_header(MAGIC_HEADER)
    ```
    mogg
        25
    mogg  
       2023-07-08 14:49:12 +08:00
    @mogg #24
    mogg
        26
    mogg  
       2023-07-08 14:55:00 +08:00
    所谓的可读性、代码规范 之类的约束,最大的意义在于保证团队内部的一致性,本身还是取决于团队水平 和 领导者个人喜好
    iamee
        27
    iamee  
    OP
       2023-07-08 21:44:27 +08:00
    @mogg !! 和 Boolean 没有可读性好坏之分,他们是等价的东西,任何写过 JavaScript 的人都知道 !! 是在做什么。

    我并不觉得你对 C 语言的更改提升了任何可读性,不是把任何东西封装成一个函数就等于提升了可读性,而且 p 并不一定是 char * 类型。“reinterpret cast” 然后解引用对有 C 经验的人来说是一个非常常见且不需要思考的操作,你给这个操作起名叫 “magic_header” 只会让人摸不着头脑。

    另外你的代码中指针类型星号的位置都不统一。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2841 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 14:29 · PVG 22:29 · LAX 07:29 · JFK 10:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.