如何给程序中的变量起个好名字?

2019 年 9 月 25 日

如何给程序中的变量起个好名字?

对一个人来说,名字很重要,俗语说“人如其名”。对程序中的变量而言,名字同样非常重要。



作为开发人员,你要花费大量的敲代码时间来创建变量和考虑给变量起个名字。 名字无处不在。 你可以命名文件、类、方法和变量。而命名的不同导致有的是好代码,有的是糟糕的代码,最终这会严重影响代码维护的成本。


由于我们花费大量时间命名变量,因此做好它非常重要。 在本文中,我将向你展示一些简单的规则,你可以遵循这些规则来创建名字。


在代码中起名本身就是一门艺术!


1、名字要显示真正意图


这说起来容易做起来难。 你多久遇到一次变量名,而这些变量名没有告诉你有关变量的真实信息?


一个好的经验法则是:如果一个名字需要注释,那么它并不是真实意图的命名。


编程大师Robert C. Martin在《Clean Code》中说道:“使用注释是为了弥补我们代码表意上的不足。”


这句话意味着如果你的代码需要添加注释,就说明你的代码还不够好。同时,这也说明如果不能在单纯的代码中展示你对问题或算法的理解,这是非常失败的,你只能依靠一些注释说明你的想法,而不能仅用代码。


优秀的代码可以让人在没有注释的情况下看懂并理解,好的编程习惯也是让所有必要的信息都在代码中展示出来。


以下代码段是一个变量,它不能揭示真正的意图:


<?php    private $s; // Time in seconds
复制代码


变量 $s 没有显示任何意义。


它不会看到任何时间流逝的含义。最好选择一个名称,该名称指定要测量的内容以及该测量的单位。因此,很重要的一点就是,程序员要用代码准确的表达出自己的思想,从而让其他人明白程序的含义。


下面的示例中的变量名会更好,任选其一。


<?php    private $days_since_creation;  private $elapsed_time_in_seconds;  private $seconds_since_last_modified;
复制代码


选择显示意图的名称可以使理解一段代码变得更加容易,因此也易于维护。


选择名字需要时间,但是比起维护代码,整体节省时间要多得多。


让我们看一下以下示例:


<?php    function getList() {      $list1 = [];            foreach ($this->the_list as $x) {          if ($x % 2 != 0) {              $list1[] = $x;          }      }            return $list1;  }    function getOddNumbers() {      $odd_numbers = [];            foreach ($this->numbers as $number) {          if (isOdd($number)) {              $odd_numbers[] = $number;          }      }            return $odd_numbers;  }
复制代码


为什么 getList 函数的作用这么难辨别?它并没有复杂的表达式。代码已缩进并正确格式化。只使用了三个变量,没有花里胡哨的东西。


再看一下 getOddNumbers 函数。你是否看到该函数与 getList 函数完全相同?


注意,代码的复杂度没有改变。它仍然具有完全相同数量的运算符和变量,以及完全相同数量的嵌套逻辑。唯一改变的是代码命名变得更加明确。


通过简单的名称重构,我们很容易分辨出这段代码的功能。


2、使用某一领域背景中有意义的名字


程序员写的所有代码都是和某一领域背景相关的,为了让写出的代码可以让个更多的人理解,最好使用该领域背景下的名字。


不好的代码示范:


public class  EntitiesRelation{Entity o1;Entity o2;}
复制代码


当你在编写针对某个领域的代码时,你应该使用领域背景相关的名字。如果以后有另外的人(不仅是程序员,也许是测试人员)接触你的代码时,他能轻松的理解你写背景相关的代码含义。


所以,程序员首先应该考虑的是领域背景问题,之后才是如何出解决方案。


清晰的代码示例:


public class  ProductWithCategory{Entity product;Entity category;}
复制代码


3、避免误导信息


你应该避免留下掩盖代码含义的错误提示。


避免误导其含义与预期含义有所差异的词。例如,不要将产品分组称为 productList,除非它实际上是 List 类型的对象。这可能导致错误的结论。命名为 products 更好。


Product[] products;
复制代码


你可能选择的最差的变量名称是大写的 O 和小写的 L。这是因为它们看起来很像 0 和 1。


当心使用名称变化很小的名称。发现一个文件中的 SomeMethodForEfficientHandlingOfFiles 和另一个文件中的 SomeMethodForEfficientStorageOfFiles 之间的细微差别需要多长时间?乍一看,这些名称看起来相同。


导致误解的信息比没有信息更糟糕,有些程序员喜欢“隐藏”一些重要信息,但更糟的是,他们有时会写出一些让人误解的代码。


命名混淆:一个词不要表示多种概念


定义场景中的概念很难,在软件开发过程中,程序员需要花费很多时间去分析某一场景,并命名场景中的各种元素,这样的工作永远都是让程序员头疼的事情。


不好的代码示例:


//1.void  LoadSingleData();void  FetchDataFiltered();void  GeteAllData();//2.void  SetDataToView();void  SetObjectValue(int value);
复制代码


在第一段代码中,这个程序员想表达“获取数据”这个概念,但他用了很多不同的词”load”,”fetch”, ”get”。在一个场景下,应该用一个统一的词表示这个概念。


在第二段代码中,”set”一词被用作了两个概念,第一个是“取出数据显示”,第二个是“为一个对象赋值”,应该用不同的词表示这两个不同的概念。


清晰的代码示例:


//1.void  GetSingleData();void  GetDataFiltered();void  GetAllData();
//2.void LoadDataToView();void SetObjectValue(int value);
复制代码


4、做出有意义的区分


数字系列命名不是一个命名的好方法。这样的名称是非信息性的,因为它们没有提供代码作者意图的任何提示。


让我们看下面的例子:


<?php    public function duplicateArray($arr1, &$arr2) {    foreach ($arr1 as $key => $value) {      $arr2[$key] = $value;    }  }
复制代码


当将 arr2 重命名为 destination 时,此代码将更好地阅读。


5、使用可以发音的单词


如果不能说出名字,那么你就不能在听起来像个白痴的情况下讨论它。这实际上很重要,因为编程的一部分工作是社交活动,每个人都有很大的机会知道自己无法发音的变量名称。


假设我们有一个名为 $xsq 的变量名,这对贵公司来说是一个非常重要的缩写。想象一下与同事的对话:


“嘿,那可变的 eks ess kjew 呢?”


“你是说访问队列?”


一些开发人员将尝试将变量发音为一个单词。其他人会拼出这个词。


变量命名:使用在上下文有意义的名字


代码里的名字都有自己的上下文,上下文对于理解一个代码是很重要的,因为它能提供额外的信息。我们来看一个典型的“地址”上下文:


不好的代码示例:


string addressCity;string addressHomeNumber;
> string addressPostCode;
复制代码


在大多数情况中,“邮政编码”(PostCode)是地址的一部分,很显然,邮政编码不能单独使用(除非你是在开发一个专门处理邮编的应用)。


所以,没有必要在“PostCode”的前面加上“address”。而且,所有的这些信息都应该有一个上下文环境,在面向对象编程中,这里应该用一个“Address”类来表达这个地址信息。


清晰的代码示例:


class Address{string city;string homeNumber;string postcode;
> }
复制代码


6、使用可搜索的名称


由一个字母组成的名称,可能存在难以定位的问题。


数字常量也是如此。数值常量可以用常量变量代替。搜索代码时,数字 8 可能会给你带来很多麻烦。


但是,用常量 MAX_BLOCKS_DISPLAYED 替换它会使它变得更容易。


单字母名称的唯一用例是简短方法中的局部变量。


7、命名前缀


不要使用前缀。


例如,某些开发人员习惯在所有私有成员前面加上下划线。别,你的类和方法应该足够短小,以至于不需要任何这些前缀。


或者,你可以使用 IDE(或安装插件),该 IDE 根据变量的范围会为变量着色。


结论


这样,你可以在代码中创建更有意义的名称。


作为一名程序员你应该:


1、起的名字有意义,可以表达一个概念

2、要考虑名字的长度,名称中只有必要信息

3、符合“编码规范”,有助于理解

4、一个概念不要多个名字混用

5、使用在背景领域和上下文中都有意义的名字


本文的灵感来自罗伯特·C·马丁(Robert C. Martin)所著的《清洁代码》(Clean Code),我强烈建议你仔细阅读。


英文原文:


How To Create Meaningful Names In Code


2019 年 9 月 25 日 10:454466
用户头像
王文刚 Instagram 营销专家

发布了 37 篇内容, 共 17.6 次阅读, 收获喜欢 50 次。

关注

评论 1 条评论

发布
用户头像
"本文的灵感来自罗伯特·C·马丁(Robert C. Martin)所著的《清洁代码》(Clean Code)"
文章很好,但是,基本就是对《Clean Code》的读书笔记(甚至举的例子就是原书上的)
2019 年 09 月 25 日 12:09
回复
没有更多评论了
发现更多内容

为什么从蚂蚁离职?base拉胯,高潜也被倒挂,就是酸,忍不了

Java架构师迁哥

linux后台开发必知的linux系统内存知识总结

linux大本营

c++ Linux 后台开发 架构师 内存管理

浅谈互斥锁与进程间的通信(举例说明)

ShenDu_Linux

Linux 程序员 架构师 进程线程区别

区块链技术应用打造智慧物流

13828808769

区块链技术应用开发

从零做网站开发:基于Flask和JQuery,实现表格管理平台

华为云开发者社区

jquery flask 框架

技术应用丨DWS 空间释放(vacuum full) 最佳实践

华为云开发者社区

内存 存储 磁盘

架构师 3 期 3 班 -week2- 总结

zbest

总结 week2

深入了解进程间通信:System V信号量+共享内存

ShenDu_Linux

Linux 进程 内存管理 通信协议

中国CRM突围指南

ToB行业头条

CRM

在K8S/OpenShift上开发应用程序的14种最佳实践

东风微鸣

Kubernetes 最佳实践 k8s最佳实践 openshift

OPPO技术开放日第六期丨OPPO安全解析“应用与数据安全防护”背后的技术

OPPO安全

OPPO安全

LeetCode题解:455. 分发饼干,贪心while循环,JavaScript,详细注释

Lee Chen

算法 LeetCode 前端进阶训练营

同步与异步,回调与协程

Linux服务器开发

线程 协程 后端开发 底层应用开发 Linux服务器开发

《迅雷链精品课》第九课:区块链P2P网络

迅雷链

区块链

「云原生上云」后的聚石塔是如何应对 双11 下大规模应用挑战的

阿里巴巴云原生

阿里云 云原生

关于物联网规则引擎技术,你想要知道的都在这儿!

华为云开发者社区

数据 联动 iotda

区块链在国际贸易领域应用的法律问题

CECBC区块链专委会

区块链

数字货币将带来怎样的“革命”

CECBC区块链专委会

数字货币 货币

精彩回顾 | 一张图读懂OPPO应用与数据安全防护

OPPO安全

OPPO安全

当居住空间被智能包裹:OTA智能社区改变了什么?

脑极体

大企软件系统问题多?归乡名企工程师:解决很简单,分分钟做个新系统

Learun

敏捷开发 快速开发 企业开发 CRM 企业应用

你敢信?就是这个Netty的网络框架差点把我整疯了,哭jj

小Q

学习 编程 面试 Netty 网络

年轻人快来学习TCP 协议如何解决粘包、半包问题!

程序员小灰

c++ Linux TCP 后台开发 Linux服务器开发

爆买剁手之后,我们的快乐为什么越来越贬值?

脑极体

王者荣耀如何使用UDP做到低延迟

linux亦有归途

设备常用网管配置举例

网络技术平台

测试过程中如何快速定位一个bug

测试人生路

软件测试

cncf serverless 所有项目全解读

coldTea214

云计算 Serverless 容器云 cncf

Serverless 应用引擎的远程调试和云端联调

阿里巴巴云原生

Java Serverless 云原生 后端

进一步深挖工业数据价值

CECBC区块链专委会

数据安全;工业互联网

架构师 3 期 3 班 -week2- 作业

zbest

作业 week2

如何给程序中的变量起个好名字?-InfoQ