当前位置: 首页 > 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…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...