美文网首页
编写可读代码的艺术:初·代码审美

编写可读代码的艺术:初·代码审美

作者: sunnyaxin | 来源:发表于2017-04-16 17:14 被阅读101次

    前言:人生有很多第一次,作为一只不谙世事的小程序媛,第一次踏出校门,开始实习,感触良多,其中,颇为震撼的一点是,原来一直给人印象邋里邋遢的程序猿们,竟然在写代码上有那么多讲究,原来科学看待程序媛的方法真的不是“以貌取人”,而是“以代码取人”。本文为《编写可读代码的艺术》一书的读书笔记,并加上一些个人理解,用于记录,也用于分享共勉。为了编写可读代码,本书主要从四个方面对代码进行提升改进,此文主要记录第一部分,即更多的是对代码表明的一些改进,如名字命名,注释的书写等,并建立代码审美意识。之后还会有同系列的文章用来继续记录后面三部分内容。


    编写可读代码何以称作艺术?

    相信不少道行尚浅的小程序猿们如我一样,在技术的海洋里混乱遨游之际,只追求写出能够运行的代码,然后窃喜以为已然顿悟,但过一段时间回来再看,即使是自己的亲儿子代码,依旧不知所云。为什么呢?这里就要说到代码对人的友好性和可读性,优秀的代码具备良好的可读性,编写的代码要使其他人(或者一段时间后的自己)能在最短的时间内理解才行。写代码不仅要在乎宏观架构和整体设计,同时也要注重细节,可以说每个程序员每天更多接触的是是代码的细枝末节,有时一个不小心整个工程就会在一个不起眼的小错误中纠结度过。因此,这样看来,编码,不仅仅是一种技术,也是一门艺术

    如何编写可读代码

    1. 简化命名、注释和格式的方法,使每行代码都言简意赅。
    2. 梳理程序中的循环、逻辑和变量来减小复杂度并理清思路。
    3. 在函数级别解决问题,例如重新组织代码块,使其一次只做一件事。
    4. 编写有效的测试代码,使其全面简洁,同时可读性更高。

    起名字的学问

    写代码如同写文章,每个函数每个变量都会有一个名字,以便需要时进行调用,好的名字能够让人一目了然,将信息装到名字里,把名字当做一条小小的注释,能够使得代码更加精简清晰。那么如何起名字,才能携带更多的信息呢?

    1.选择专业的词

    eg:GetPage(url)函数用于获取页面
    Q:从本地缓存获取?从数据库获取?从互联网获取?
    ---> 从互联网获取:FetchPage()或者 DownloadPage()

    2.找到更有表现力的词

    可以从同义词中寻找,多思考。

    单词 更多选择
    send deliver, dispatch, announce, distribute, route
    find search, extract, locate, recover
    start launch, create, begin, open
    make create, set up, build, generate, compose, add, new
    3.避免像tmp和retval这样泛泛的名字
    • 好的名字应当描述变量的目的,或者它承载的值。
      eg:sum 变量,代表累加平方值
      Q: 谁的和?累加和?平方和?
      ---> sum_squares
    • 有时泛泛的名字也有意义,只在有特殊意义时使用,如 tmp 名字只应用于短期存在且临时性为其主要存在因素的变量。
    • 循环迭代器的升级
      eg: 像 i、j、k 这样的名字常被用于做索引或循环迭代器
      Q: 很容易在使用时写错,如 i 写成 j
      ---> 变量名_循环迭代器 eg:club_i, member_j, user_k
    4.用具体的名字代替抽象的名字

    eg:ServerCanStart() 函数,检测服务器是否可以监听某个给定的TCP/IP端口
    Q: 名字太抽象,范围大
    ---> CanListenOnPort() 直接描述方法做的事情

    5.为名字附带更多信息
    • 带单位的值
      eg1:包含十六进制的字符串id ---> hex_id
      eg2:如果变量是度量(时间长度或字节数)---> start_ms, delay_secs, size_mb, max_kbps, degrees_cw
    • 附带其他重要属性
    情形 变量名 better变量名
    一个“纯文本”格式的密码,需要加密后才能进一步使用 password plaintext_password
    一条用户提供的注释,需要转义后才能用于显示 comment unescaped_comment
    已转换为 UTF-8 格式的 html 字节 html html_utf8
    以“uml方式编码”的输入数据 data data_urlenc
    6.利用名字的格式来传递含义

    对下划线、连字符和大小写的使用方式可以把更多的信息装到名字中。对不同的实体使用不同格式就像语法高亮显示的形式一样,能够帮助更容易阅读代码。例如:

    格式 意义
    CamelCase 表示类名
    lower_separated 表示变量名
    kConstantName 表示常量
    MACRO_NAME 表示宏
    offset_ 表示类成员变量

    名字应该有多长

    1. 在小的作用域里可以使用短的名字。
      如果一个标识符有较大的作用域,那么它的名字就要包含足够的信息以便含义更清楚。
    2. 长名字也不用担心------编辑器上自动补全功能。
    3. 首字母缩略词和缩写的使用。
      原则:团队新成员能够理解名字含义。
    4. 丢掉没用的词
      eg: ConvertToString() ---> ToString()

    准确命名(没有歧义)

    1. 使用 min 和 max 来表示(包含)极限
      eg:CART_TOO_BIG_LIMIT 是个二义性名字导致“大小差一”问题
      ---> MAX_ITEMS_IN_CART 表示包含极限的最大值

    2. 用 first 和last 来表示包含的范围


    3. 用 begin 和 end 来表示包含/排除范围


    4、给布尔值命名
    (1)通常来讲,加上像 is、has、can 或 should 这样的词,可以把布尔值变得更加明确
    eg:bool read_password = ture;
    Q: 需要读取密码?已经读取了密码?
    ---> need_password 或者 user_is_authenticated
    (2)避免使用反义名字
    eg:bool disable_ssl = false;
    ---> bool use_ssl = true;

    代码审美-组织代码

    三条原则:
    (1)使用一致的布局,让读者很快就习惯这种风格;
    (2)让相似的代码看上去相似;
    (3)把相关的代码行分组,形成代码块;
    

    整洁的代码能够提升浏览速度,和使用程度,相反如果代码结构凌乱,很影响代码的阅读和进一步重构。根据三条原则,可以总结出以下几条提高代码审美的Tips:

    1. 重新安排换行来保持一致和紧凑。
    2. 用方法来整理不规则的东西。如果多个代码块做相似的事情,尝试让他们有同样的剪影。
    3. 需要时使用列对齐。按列对齐可以让代码更加容易阅读。
    4. 选一个有意义的顺序,始终一直使用它。如:变量定义的顺序,如果一段代码中提到 A、B、C,那么另一段中使用同样的顺序。
    5. 把声明按块组织起来。不要把所有的方法都放到一个巨大的代码块中,应当用空行按逻辑把他们分组。
    6. 个人风格与一致性:一致的风格比“正确”的风格更重要。

    注释的使用

    什么地方需要注释?

    注释的目的是尽量帮助读者了解的和作者一样多。当程序员写代码时,脑海中会有很多有价值的信息;当其他人阅读代码时,这些信息已经丢失,所见到的只是眼前的代码。

    什么地方不需要注释?

    (1)能从代码本身中迅速推断的事实。
    (2)不要给不好的名字加注释-----应该把名字改好:一个好的名字比一个好的注释更重要,因为在任何用到这个函数的地方都能看到它。也就是好代码>坏代码+好注释

    注释作用:记录你的思想

    记录写代码时有过的重要想法。以下几种情况建议写注释:

    1. 对于为什么代码写成这样而不是那样的内在理由。
      eg:防止做无谓的优化而浪费时间; 解释为什么代码不那么整洁;
    2. 给常量加注释。是什么?为什么是这个值?通过阅读注释,有了调整这个值的指南。但有些常量不需要注释,名字本身已经很清楚了(eg: SECONDS_PER_DAY)
    3. 为代码中的瑕疵写注释。即代码需要改进时,或代码没有完成时。
    标记 通常的作用
    TODO 还没有处理的事情
    MAYBE_LATER 方法有次要的缺陷
    FIXME 已知的无法运行的代码
    HACK 对一个问题不得不采用的比较粗糙的解决方案
    XXX 危险!这里有重要的问题
    加注释:站在读者的角度

    想象代码对于外人来讲看起来是什么样子的,这个人并不熟悉项目,这对于发现什么地方需要注释尤其有用。

    1. 用注释总结代码块,不致迷失在细节中 ---> 在包含大块的长函数中使用。
    2. 在文件/类的级别上使用“全局观”注释 ---> 熟悉代码库。解释所有的部分是如何一起工作的,迅速了解代码,比自己读源代码快很多。
    //这个文件包含一些辅助函数,为我们文件系统提供了更便利的接口
    //它处理了文件权限及其他基本的细节。
    

    写注释的学问

    1. 注释保持紧凑
    2. 避免使用不明确的代词,如 it,this
    3. 润色粗糙的句子
    4. 精确地描述函数的行为
      eg:统计行数 ----> 统计换行符(/n)
    5. 用输入/输出例子来说明特别的情况
    6. 声明代码的意图:表达写代码时的想法,不是描述字面上的意思
    7. 使用嵌入的注释:大多数函数不需要,这样可以方便紧凑地解释看上去难以理解的参数
      eg:Connect(10, false); --->
      Connect(/*timeout_ms = */ 10, /*use_encryption = */ false);
    8. 用含义丰富的词来使注释简洁:如果感觉一段注释太长了,可以使用一个典型的编程场景来描述。
      eg1:
    // This class contains a number of members that store the same information as in the 
    // database, but are stored here for speed. When this class is read from later, those
    // members are checked first to see if they exist, and if so are returned; otherwise the 
    // database is read from and that data stored in these field for next time.
    
    

    可以简单的说:

    This class acts as a caching layer to the database.
    

    eg2:

    // Remove excess whitespace from the street address, and do lots of other cleanup
    // like turn "Avenue" into "Ave." This way, if there are two different street addresses
    // that are typed in slightly differently, they will have the same cleaned-up version and 
    // we can detect that these are equal.
    

    可以简单的说:

    Canonicalize the street address (remove extra spaces, "Avenue" -> "Ave.", etc.)
    

    相关文章

      网友评论

          本文标题:编写可读代码的艺术:初·代码审美

          本文链接:https://www.haomeiwen.com/subject/nouaattx.html