代码中的命名小技巧

本文首发于 造梦网

《重构: 改善既有代码的设计》的作者 Martin Fowler 在一篇博客中引用这样一段话:

There are only two hard things in Computer Science: cache invalidation and naming things.

计算机科学中只有两件难事:缓存失效和命名事物。

– Phil Karlton

由此可见,在计算机科学中命名一件事物是多么的困难。这当然也包括在代码中对变量、类型、类等进行命名。

命名的困难

第一、变量代表了一组状态,很多组状态的不断变化,构成了程序的逻辑。如何给这些状态起个又短小精准的名字,当然是比较难的。

第二、各种国产入门编程书籍从一开始就没有重视命名,书中到处都是类似于 x y 之类糟糕的命名,例如谭浩强的《C语言入门》。

第三、命名需要一定的英文功底,而国内程序员的英文水平参差不齐。有的直接把中文直译为英文来命名,有的甚至直接用拼音来命名。

种种这些都导致了在以后的大型项目中灾难式的命名方式,使得阅读和维护难如登天。

几种命名方式的建议

不要使用 abc, xyz

最经典最糟糕的例子就是使用 x y z 之类的不知所云的在数学中常用的变量来命名。

int a,b,c;
int x,y,z;

这类命名不会告诉你任何关于此变量的信息。

永远不要使用缩写

有许多国内外程序员都喜欢使用缩写。但是当你真正看到一个复杂函数使用缩写的时候,不看注释很难知道它在说什么。

public relScore(m1: Mov, mv2: Mov): number {
  const GW = 0.4;
  const YW = 0.1;
  const DW = 0.2;
  const WW = 0.3;
}

但你使用完整单词的时候,就可以轻松的读懂这段定义:这是一个关于电影评分关系的函数,那些那些变量是各种权重。

public movieRelationScore(movie1: Movie, movie2: Movie): number {
  const GENRE_WEIGHT = 0.4;
  const YEAR_WEIGHT = 0.1;
  const DIRECTOR_WEIGHT = 0.2;
  const WRITER_WEIGHT = 0.3;
}

我猜想这中现象应该是为了减少打字量而创造的,毕竟以前没有各种智能 IDE,没有代码补全。

但是都 2023 年了,古老的 Emacs 也可以自动补全了,所以请不要吝啬那一个字符。

不要将类型作为变量的前缀

如果您接触过老的 Windows 编程,那么您一定知道匈牙利命名法。它将类型作为变量名的前缀,看起来类似于这样:

int bIsValid; // bool
int iSpeed; // int32_t
int uNumUsers; // uint32_t
int szUserName; // char* 指针 

这在 C语言 的世界中非常常见,因为 C 只有最基本的几种数据类型,而类型前缀很明确的表达了它本身代表的类型。

但是目前大部分的静态类型语言都有了很丰富的类型系统,类型(type)很准确的告诉您正在查看的内容是什么。

bool bIsValid;
int32_t iSpeed;
uint32_t uNumUsers;
char* szUserName;

所以不需要再将类型作为变量名前缀了。

将单位放到变量名中

这是一个接受延迟时间的函数:

void execute(int delay)

如果 delay 以秒为单位的话,应该将此变量命名为 delaySeconds,这样用户就可以知道这里对应的是秒还是毫秒。

但是在有些语言中,时间被定义为了一种内置类型,这样以来就不必再需要将单位放到变量名中。例如在 C# 中:

void execute(TimeSpan delay)
{
  double seconds = delay.TotalSeconds;
}

但是对于像 Python 这样的动态类型语言,就不能依赖类型声明来告诉我们关于单位的信息,此时就需要将单位放到变量名中。

class Renderer:
  def __init__(self, renderIntervalSeconds):
    self.renderIntervalSeconds = renderIntervalSeconds;

不要使用Base 或 Abstract 命名一个类

这种命名方式不会出现在任何一种语言的标准库中,因为它是一种糟糕的命名方式。

作为例子,如果有一个 Truck 卡车类:

public Truck {
  private:
    double weight;
  public:
    Truck(double weight): weight(weight);
}

我想创建一个它的父类,那么我永远不会将它命名为 BaseTruck。因为这是没有意义的,BaseTruck 不能告诉我任何信息。

假如将Truck的父类命名为 Car 的话,那么在下面的函数中,可以轻松的知道它写的是什么:

public Truck : Car {
...
}

public void addContestant(Car car) {
}

此时将一个 Truck 的对象传入 addContestant的参数中,不需要任何信息就可以知道这是合理的,因为卡车是汽车的一种。

CodeIf 工具介绍

Codelf 通过搜索在线开源平台 Github , Bitbucket , Google Code , Codeplex , Sourceforge, Fedora Project 的项目源码,帮开发者从中找出已有的匹配关键字的变量名,从而帮助开发者命名变量。

搜索 用户

结语

关于命名的哲学和技巧数不胜数,这里只是列举了几种最常见的命名规范。有兴趣的话,可以阅读 Google 开源项目风格指南,英语好的可以直接看原版 Google Style Guides.


欢迎关注微信公众号:通用代码技术

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

通用代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值