阅读 59

可读代码编写炸鸡二(上篇) - 命名的长度

大家好,我是多选参数的一员 —— 大炮。

在上一篇 可读代码编写炸鸡一 中,我主要做了 可读代码编写 这个系列的开篇,目前是从代码命名角度入手,讲述了可读性代码编写的一些思路。

上一篇炸鸡中,主要的讲述思路是:

假设以前从没考虑过代码命名对于代码可读性编写的贡献,那么尝试往命名中增加更多的信息。

那么如果这一步已经做到,那么自然会考虑到下一个问题:

编写者有意识地在代码命名中添加更多的信息,有一定概率导致了 命名的长度命名歧义 的问题。

所以,本篇炸鸡便从 命名的长度命名的歧义 两个方面来提供一些代码命名的建议。

由于篇幅的限制,这两个方面将拆分为两篇炸鸡。

命名的长度

编写者在代码命名上添加了过多的信息,可能导致命名的长度过长:

-- 从远程数据库获得密码
function ActivityConfig.getPasswordFromRemoteDatabaseByIpAndPort(ip, port)
    ...
    ...
end
复制代码

看到如上的函数,想必你已经在用手拖动代码块了,这边是命名过长带来阅读上的障碍。

丢弃无用词汇

造成命名过长的第一个原因,应该就是词汇过多。那么就需要丢弃掉一些无用且占地方的词汇。例如 translate2string 完全可以直接写成 toString

上文举的例子中,函数的参数已经表达了 ByIpAndPort 的含义,所以我们可以丢弃一些无用词汇:

-- 从远程数据库获得密码
function ActivityConfig.getPasswordFromDatabase(ip, port)
    ...
    ...
end
复制代码

短范围配短名字

如果代码范围不是很大,例如一个函数的行数并不是太多,涉及的变量命名和函数命名便可以更加短小一些:

if (dbconf.DEBUG) then
    local ret = {}
    fetchAllyKingdomList(ret)
    print(ret)
end
复制代码

很明显,很小的范围内,再加上函数命名的信息,阅读者是很容易知晓一个变量的含义的,便不需要太多的信息使得命名冗长。

如果不太明白范围的含义,我再举个例子。如果这个 ret 是在一个很长的函数体的传入参数,亦或者它是一个全局变量的时候:

function xxx()
    ...
    ...
    ...
    if (dbconf.DEBUG) then
        fetchAllyKingdomList(ret)
        print(allyKingdomList)
    end
    ...
end
复制代码

这下由于代码范围过大,你要追溯 ret 需要不断地上下翻看,好不麻烦,这个时候就不是 短范围 了,就不要吝啬你的词汇,好好命名它。

而且你可以发现上述代码中调用的函数,其名称是很具体的。因为此函数的定义已经离这个调用很远,甚至是跨文件,已经是 长范围,需要更多的信息描述它。

使用经典的缩写

命名太长,第一个想到的便是缩短它。上文已经提到了丢弃无用词汇,但还有一个方法便是使用缩写

其实程序员缩写应用应该是挺广泛的,但编写者只需要遵从一个原则就好了:

你和你的团队,或者你的代码共同维护者,是否能理解所写的含义。

这个原则其实包含两个方面。

首先,是大家都约定俗成和理解的缩写:

缩写 完整
str string
doc document
eq equal

其次,便是你的团队约定的一些含义。就例如我所在的小组,写一些全局枚举,都是使用 ss 这个命名:

ss.xxxx = {}
复制代码

这样便一定程度上保证了缩写的可读性,从而削减命名的长度。

使用代码命名的格式传递含义

我们拿一个类来举例子。假设我们有一个商店基类,由于类常被其他处使用,为了表明这是一个类,我们起名为: shopClass

class shopBaseClass():
    def __init__():
        ...
复制代码

那么其实我们知道,一般类名都是 首字母大写的驼峰法 命名:

class ShopBase():
    def __init__():
        ...
...
...

shop = ShopBase() # 一看便是类的实例化
复制代码

一比较,的确是缩短了命名。

这样的例子还有常量。

一般常量都是以大写 + 下划线来命名的。例如我们要一个常量来表达商店数量上限,MAX_SHOP_COUNT 不仅比 CONST_MAX_SHOP_COUNT 长度更短,表达的意思还一样准确。

所以,利用代码本身的命名格式来传递信息,一定程度上减少了一些命名上的词汇增加。

当然,我这里埋个小坑留到下一篇:

这里为啥不用 SHOP_COUNT_LIMIT 呢?

总结

编写者为了往命名添加更多的信息,往往尺度把握不住,导致命名长度过长的问题。

为了缩短命名同时保持阅读性,本篇炸鸡提供了四个建议。

  • 丢弃无用词汇。toString 总比 translate2string 更省地方。

  • 短范围配短命名,长范围配长命名。

    if (..) then
        -- 就这么几行,简略的命名不影响阅读
        local x = 9 
        lookForEqualItem(x)
    end
    复制代码
  • 使用经典的缩写。不仅是约定俗成的 doceq 等缩写;还有团队中约定的固定缩写,例如 ss

  • 利用代码命名格式传递更多含义,从而减小长度,例如类的命名格式,常量的命名格式。

    # 首字母大写的驼峰法
    class ShopBase():
        ....
    复制代码
    -- 商店数上限
    MAX_SHOP_COUNT
    复制代码

最后吟唱

本文使用 mdnice 排版