当前位置: 首页 > news >正文

clean code阅读笔记——如何命名?

命名的原则

1. “小处诚实非小事“

有个词叫做”以小见大“。以建筑作喻,宏大建筑中最细小的部分,比如关不紧的门、未铺平的地板,甚至时凌乱的桌面,都会将整个大局的魅力毁灭殆尽,这就是整洁代码之所系。

2. 有意义的命名

选个好名字,省下来的时间比花掉的多。一旦发现有更好的名字,就换掉旧的名字。

2.1 名副其实

变量、函数和类的名字应该告诉读者:它为什么存在、它做什么事、它应该怎么用。如果名称需要注释来补充,那就不算是名副其实。

举例:

int d;	// 消逝的时间,以日计

上例中,变量d只能暗示这是一个表示day-天数的变量,但没有“消逝”的含义。我们应该明确指明计量对象和计量单位的名称:

int elapesdTimeInDays;
int daysSinceCreation;
int daysSinceModification;
int fileAgeInDays;

再举一个例子:

std::list<vector<int>> *getThem()
{auto *list1 = new std::list<vector<int>>;for (auto &x : theList){if (x[0] == 4)list1->push_back(x);}return list1;
}

上例中getThem、x[0] == 4、theList等,都比较模糊。可以改成这样:

list<vector<int>> *getFlaggedCells()
{auto *flaggedCells = new list<vector<int>>;for (auto &cell : gameBoard){if (cell[STATUS_VALUE] == FLAGGED)flaggedCells->push_back(cell);}return flaggedCells;
}

还可以更进一步,不用vector<int>来表示单元格,而是用一个对象来表示,并做好封装:

list<Cell> *getFlaggedCells()
{auto *flaggedCells = new list<Cell>;for (auto &cell : gameBoard){if (cell.isFlagged())flaggedCells->push_back(cell);}return flaggedCells;
}

与第一个版本比起来,这里明显更容易理解了。

2.2 避免误导

程序员必须避免留下掩藏代码本意的错误线索。

  • 避免使用特定平台专有名称。如hp、aix、sco。
  • 避免物理数据结构名称与变量名不同的情况。例如AccountList,其内部是用list存储的吗?
  • 避免使用不同之处较小的名称。
  • 避免l、o这种外观有歧义的名称。

2.3 做有意义的区分

对于编译器或者解释器来说,只要名称中有一个字符的不同就不会出错,但是对于读者来说,我们不仅需要名称不同,还要对名称做出有意义的区分。

举例来说,对于a1, a2, a3,…这样的区分方式,任何人不结合上下文的情况下看了都会一头雾水。还有类似getActiveChannel, getActiveChannels, getActiveChannelInfo这样的命名方式,也不容易看出它们的区别。

另外,我们也要尝试抛弃变量命中没有意义的部分,例如NameString,不如改为Name,除非Name还可以不用String来表示。

2.4 使用读的出来的名称

读的出来的名称一方面便于程序员间的交流,另一方面也利用了人类大脑的语言功能,便于理解和记忆。

比较下面两个例子:

class DtaRcrd102
{
private:Date genymdhms;Date modymdhms;const string pszqint = "102";
};
class Customer
{
private:Date generationTimestamp;Date modificationTimestamp;const string recordId = "102";
};

2.5 使用可搜索的名称

可搜索性还是在强调名称要具有区分度。所以坚持这个原则:长名称胜于短名称(除非短名称已足够精确),搜得到的名称胜于用自造编码代写的名称

单字母名称仅适用于短方法中的本地变量。名称长短应与其作用域大小相对应

2.6 避免使用编码

尽量避免将对象的类型和作用域编码进名称中,因为这会增加不必要的负担。现代的编译器和静态分析器能够帮助我们检查对象的类型。

看一下有哪些反例:

  • 匈牙利标记法(Hungarian Notation, HN)
  • 成员前缀m_

有一个例外是对接口和实现的编码,例如对于抽象工厂模式,可以将接口类命名为ShapeFactory,而将具体类命名为ShapeFactoryImpl。

2.7 避免思维映射

不应当让读者在脑中把你的名称翻译为他们熟知的名称。这种问题经常出现在选择是使用问题领域术语还是解决方案领域术语时。

我们应该尽量让名称明确,而不是自以为是的认为一种名称与某个对象之间存在一种映射关系。例如以r代表url。最终目的是编写让他人能轻易理解的代码。

2.8 类名

类名和对象名应该是名词或者名字短语,如Customer, WikiPage, Account和AddressParser。避免使用Manager, Processor, Data, Info这种缺少实际意义的词。类名不应当是动词。

2.9 方法名

方法名应当是动词或动词短语,如postPayment、deletePage或save。

重载构造器时,使用描述了参数的静态工厂方法名。例如,

Complex fulcrumPoint = Complex.FromRealNumber(23.0);

通常好于

Complex fulcrumPoint = new Complex(23.0);

2.10 别扮可爱

名字不要太耍宝,毕竟别人不一定有你的幽默感。宁可明确,毋为好玩。

2.11 每个概念对应一个词

给每个抽象概念一个词,并且一以贯之。例如不要混用fetch、retrieve和get。在同一堆代码中有controller,manager和driver,它们的区别是什么?

2.12 别用双关语

避免将同一单词用于不同目的。如果同一术语用于不同的概念,那么它基本上就是双关语了。

我们要遵循“一词一义”规则,例如对于add方法,如果它出现在多个类中,我们要保证这些add方法的参数和返回值在语义上等价。具体地说,如果在一个类中。add方法通过增加或连接两个现存值来获得新值并返回。现在要写一个新类,需要一个方法能够把参数添加道容器中,那么就不能把这个方法叫做add,因为这样做的话,add就变成了双关语。可以使用insert、append之类地词。

2.13 使用解决方案领域名称

我们的读者都是程序员,所以如果可以尽量使用计算机科学中的术语、算法名、模式名和数学术语。例如,对于熟悉访问者(VISITOR)模式的程序员来说,AccountVisitor富有意义。

2.14 使用源自所涉问题领域的名称

如果真的不能用程序员所熟悉的术语来命名,那就采用问题涉及领域的名称吧。至少,负责维护代码的程序员知道该去请教谁。

优秀的程序员和设计师,其工作之一就是分离解决方案领域和问题领域的概念。与所涉问题更为贴近的代码,应当采用源自问题领域的名称。

2.15 添加有意义的语境

单单一个名称能够说明的信息还是太过有限。我们需要有良好命名的类、函数或者名称空间来放置名称,给读者提供语境。如果没有这么做,那么给名称添加前缀就是最后一招了。

那么如何添加语境呢?举例来说,可以从一个复杂的函数体中拆分出多个步骤,然后给这些子函数命上合适的名字,从而提供更多语境,告诉读者整个函数的逻辑。

不要添加没用的语境

只要现有的代码已经足够清楚,就没必要拆分出不同的子函数。只要短名称足够清楚,就比长名称好。

相关文章:

clean code阅读笔记——如何命名?

命名的原则 1. “小处诚实非小事“ 有个词叫做”以小见大“。以建筑作喻&#xff0c;宏大建筑中最细小的部分&#xff0c;比如关不紧的门、未铺平的地板&#xff0c;甚至时凌乱的桌面&#xff0c;都会将整个大局的魅力毁灭殆尽&#xff0c;这就是整洁代码之所系。 2. 有意义…...

MacOS 如何解决无法打开 ‘xxx’,因为 Apple 无法检查其是否包含恶意软件

背景 在安装软件时&#xff0c;遇到“无法打开 ‘xxx’&#xff0c;因为 Apple 无法检查其是否包含恶意软件” 的提示&#xff0c;许多用户可能会感到困惑&#xff0c;不知道该如何处理。遇到这个问题时&#xff0c;按以下步骤操作即可解决。 首先&#xff0c;这个警告提示的出…...

Java并发学习:进程与线程的区别

进程的基本原理 一个进程是一个程序的一次启动和执行&#xff0c;是操作系统程序装入内存&#xff0c;给程序分配必要的系统资源&#xff0c;并且开始运行程序的指令。 同一个程序可以多次启动&#xff0c;对应多个进程&#xff0c;例如同一个浏览器打开多次。 一个进程由程…...

省市区三级联动

引言 在网页中&#xff0c;经常会遇到需要用户选择地区的场景&#xff0c;如注册表单、地址填写等。为了提供更好的用户体验&#xff0c;我们可以实现一个三级联动的地区选择器&#xff0c;让用户依次选择省份、城市和地区。 效果展示&#xff1a; 只有先选择省份后才可以选择…...

springboot 动态配置定时任务

要在Spring Boot中动态配置定时任务&#xff0c;可以使用ScheduledTaskRegistrar类来实现。 首先&#xff0c;创建一个定时任务类&#xff0c;该类需要实现Runnable接口。例如&#xff1a; Component public class MyTask implements Runnable {Overridepublic void run() {/…...

数据结构与算法学习笔记----求组合数

数据结构与算法学习笔记----求组合数 author: 明月清了个风 first publish time: 2025.1.27 ps⭐️一组求组合数的模版题&#xff0c;因为数据范围的不同要用不同的方法进行求解&#xff0c;涉及了很多之前的东西快速幂&#xff0c;逆元&#xff0c;质数&#xff0c;高精度等…...

Arouter详解・常见面试题

前言&#xff1a;ARouter是一个用于 Android App 进行组件化改造的路由框架 —— 支持模块间的路由、通信、解耦。 一、路由简介&#xff1a; 路由&#xff1a;就是通过互联的网络把信息从源地址传输到目的地址的活动。完成路由这个操作的实体设备就是 路由器&#xff08;Rout…...

全志开发板 视频输入框架

笔记来源于百问网出品的教程。 1.VIN camera驱动框架 • 使用过程中可简单的看成是vin 模块 device 模块af driver flash 控制模块的方式&#xff1b; • vin.c 是驱动的主要功能实现&#xff0c;包括注册/注销、参数读取、与v4l2 上层接口、与各device 的下层接口、中断处…...

寒假学web--day10

简介 一些高级的反序列化 phar反序列化 phar类似于java的jar包&#xff0c;将多个php文件合并为独立的压缩包&#xff0c;不用解压就能执行里面的php文件&#xff0c;支持web服务器和命令行 metadata $phar->setmetadata($h); metadata可以存放一个类实例&#xff0c;…...

【全栈】SprintBoot+vue3迷你商城(9)

【全栈】SprintBootvue3迷你商城&#xff08;9&#xff09; 往期的文章都在这里啦&#xff0c;大家有兴趣可以看一下 后端部分&#xff1a; 【全栈】SprintBootvue3迷你商城&#xff08;1&#xff09; 【全栈】SprintBootvue3迷你商城&#xff08;2&#xff09; 【全栈】Spr…...

系统思考—问题分析

很多中小企业都在面对转型的难题&#xff1a;市场变化快&#xff0c;资源有限&#xff0c;团队协作不畅……这些问题似乎总是困扰着我们。就像最近和一位企业主交流时&#xff0c;他提到&#xff1a;“我们团队每天都很忙&#xff0c;但效率始终没见提升&#xff0c;感觉像是在…...

系统架构设计师教材:信息系统及信息安全

信息系统 信息系统的5个基本功能&#xff1a;输入、存储、处理、输出和控制。信息系统的生命周期分为4个阶段&#xff0c;即产生阶段、开发阶段、运行阶段和消亡阶段。 信息系统建设原则 1. 高层管理人员介入原则&#xff1a;只有高层管理人员才能知道企业究竟需要什么样的信…...

美国三种主要的个人数据产业模式简析

文章目录 前言一、个人征信(Credit Reporting)模式1、定义:2、特点:数据来源:核心功能:服务对象:代表性公司:监管框架:示例应用:二、面向垂直场景的个人数据公司(Consumer Reporting,消费者报告模式)1、定义:2、特点:数据来源:核心功能:服务对象:主要公司:监…...

js手撕 | 使用css画一个三角形 使用js修改元素样式 驼峰格式与“-”格式相互转化

1.使用css画一个三角形 借助 border 实现&#xff0c;在 width 和 height 都为 0 时&#xff0c;设置 border&#xff0c;便会呈现三角形。想要哪个方向的三角形&#xff0c;设置其他三边为 透明即可。同时&#xff0c;可以通过调整不同边的宽度&#xff0c;来调整三角形的高度…...

每日一道算法题

题目&#xff1a;最长递增子序列的个数 给定一个未排序的整数数组&#xff0c;找到最长递增子序列的个数。 示例 1 输入&#xff1a;nums [1,3,5,4,7]输出&#xff1a;2解释&#xff1a;有两个最长递增子序列&#xff0c;分别是 [1,3,4,7] 和 [1,3,5,7] 。 示例 2 输入&a…...

低代码系统-产品架构案例介绍、明道云(十一)

明道云HAP-超级应用平台(Hyper Application Platform)&#xff0c;其实就是企业级应用平台&#xff0c;跟微搭类似。 通过自设计底层架构&#xff0c;兼容各种平台&#xff0c;使用低代码做到应用搭建、应用运维。 企业级应用平台最大的特点就是隐藏在冰山下的功能很深&#xf…...

论文笔记(六十三)Understanding Diffusion Models: A Unified Perspective(三)

Understanding Diffusion Models: A Unified Perspective&#xff08;三&#xff09; 文章概括 文章概括 引用&#xff1a; article{luo2022understanding,title{Understanding diffusion models: A unified perspective},author{Luo, Calvin},journal{arXiv preprint arXiv:…...

利用机器学习创建基于位置的推荐程序

推荐系统被广泛应用于不同的应用程序中&#xff0c;用于预测用户对产品或服务的偏好或评价。在过去的几分钟或几小时里&#xff0c;你很可能在网上遇到过或与某种类型的推荐系统进行过互动。这些推荐系统有不同的类型&#xff0c;其中最突出的包括基于内容的过滤和协作过滤。在…...

每日一题 429. N 叉树的层序遍历

429. N 叉树的层序遍历 /*class Solution { public:vector<vector<int>> levelOrder(Node* root) {queue<Node*> que;que.push(root);vector<vector<int>> ans;if(root nullptr){return ans;}while(!que.empty()){int sizeQue que.size();vec…...

AIP-132 标准方法:List

编号132原文链接AIP-132: Standard methods: List状态批准创建日期2019-01-21更新日期2022-06-02 在许多API中&#xff0c;通常会向集合URI&#xff08;例如 /v1/publishers/1/books &#xff09;发出GET请求&#xff0c;获取集合中资源的列表。 面向资源设计&#xff08;AIP…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...

数据结构:递归的种类(Types of Recursion)

目录 尾递归&#xff08;Tail Recursion&#xff09; 什么是 Loop&#xff08;循环&#xff09;&#xff1f; 复杂度分析 头递归&#xff08;Head Recursion&#xff09; 树形递归&#xff08;Tree Recursion&#xff09; 线性递归&#xff08;Linear Recursion&#xff09;…...

Python训练营-Day26-函数专题1:函数定义与参数

题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一个名为 calculate_circle_area 的函数&#xff0c;该函数接收圆的半径 radius 作为参数&#xff0c;并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求&#xff1a;函数接收一个位置参数 radi…...

Vue3中的computer和watch

computed的写法 在页面中 <div>{{ calcNumber }}</div>script中 写法1 常用 import { computed, ref } from vue; let price ref(100);const priceAdd () > { //函数方法 price 1price.value ; }//计算属性 let calcNumber computed(() > {return ${p…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter

java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用&#xff08;Math::max&#xff09; 2 函数接口…...

Python爬虫实战:研究Restkit库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的有价值数据。如何高效地采集这些数据并将其应用于实际业务中,成为了许多企业和开发者关注的焦点。网络爬虫技术作为一种自动化的数据采集工具,可以帮助我们从网页中提取所需的信息。而 RESTful API …...

【PX4飞控】mavros gps相关话题分析,经纬度海拔获取方法,卫星数锁定状态获取方法

使用 ROS1-Noetic 和 mavros v1.20.1&#xff0c; 携带经纬度海拔的话题主要有三个&#xff1a; /mavros/global_position/raw/fix/mavros/gpsstatus/gps1/raw/mavros/global_position/global 查看 mavros 源码&#xff0c;来分析他们的发布过程。发现前两个话题都对应了同一…...