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. “小处诚实非小事“ 有个词叫做”以小见大“。以建筑作喻,宏大建筑中最细小的部分,比如关不紧的门、未铺平的地板,甚至时凌乱的桌面,都会将整个大局的魅力毁灭殆尽,这就是整洁代码之所系。 2. 有意义…...
MacOS 如何解决无法打开 ‘xxx’,因为 Apple 无法检查其是否包含恶意软件
背景 在安装软件时,遇到“无法打开 ‘xxx’,因为 Apple 无法检查其是否包含恶意软件” 的提示,许多用户可能会感到困惑,不知道该如何处理。遇到这个问题时,按以下步骤操作即可解决。 首先,这个警告提示的出…...
Java并发学习:进程与线程的区别
进程的基本原理 一个进程是一个程序的一次启动和执行,是操作系统程序装入内存,给程序分配必要的系统资源,并且开始运行程序的指令。 同一个程序可以多次启动,对应多个进程,例如同一个浏览器打开多次。 一个进程由程…...
省市区三级联动
引言 在网页中,经常会遇到需要用户选择地区的场景,如注册表单、地址填写等。为了提供更好的用户体验,我们可以实现一个三级联动的地区选择器,让用户依次选择省份、城市和地区。 效果展示: 只有先选择省份后才可以选择…...
springboot 动态配置定时任务
要在Spring Boot中动态配置定时任务,可以使用ScheduledTaskRegistrar类来实现。 首先,创建一个定时任务类,该类需要实现Runnable接口。例如: Component public class MyTask implements Runnable {Overridepublic void run() {/…...
数据结构与算法学习笔记----求组合数
数据结构与算法学习笔记----求组合数 author: 明月清了个风 first publish time: 2025.1.27 ps⭐️一组求组合数的模版题,因为数据范围的不同要用不同的方法进行求解,涉及了很多之前的东西快速幂,逆元,质数,高精度等…...
Arouter详解・常见面试题
前言:ARouter是一个用于 Android App 进行组件化改造的路由框架 —— 支持模块间的路由、通信、解耦。 一、路由简介: 路由:就是通过互联的网络把信息从源地址传输到目的地址的活动。完成路由这个操作的实体设备就是 路由器(Rout…...
全志开发板 视频输入框架
笔记来源于百问网出品的教程。 1.VIN camera驱动框架 • 使用过程中可简单的看成是vin 模块 device 模块af driver flash 控制模块的方式; • vin.c 是驱动的主要功能实现,包括注册/注销、参数读取、与v4l2 上层接口、与各device 的下层接口、中断处…...
寒假学web--day10
简介 一些高级的反序列化 phar反序列化 phar类似于java的jar包,将多个php文件合并为独立的压缩包,不用解压就能执行里面的php文件,支持web服务器和命令行 metadata $phar->setmetadata($h); metadata可以存放一个类实例,…...
【全栈】SprintBoot+vue3迷你商城(9)
【全栈】SprintBootvue3迷你商城(9) 往期的文章都在这里啦,大家有兴趣可以看一下 后端部分: 【全栈】SprintBootvue3迷你商城(1) 【全栈】SprintBootvue3迷你商城(2) 【全栈】Spr…...
系统思考—问题分析
很多中小企业都在面对转型的难题:市场变化快,资源有限,团队协作不畅……这些问题似乎总是困扰着我们。就像最近和一位企业主交流时,他提到:“我们团队每天都很忙,但效率始终没见提升,感觉像是在…...
系统架构设计师教材:信息系统及信息安全
信息系统 信息系统的5个基本功能:输入、存储、处理、输出和控制。信息系统的生命周期分为4个阶段,即产生阶段、开发阶段、运行阶段和消亡阶段。 信息系统建设原则 1. 高层管理人员介入原则:只有高层管理人员才能知道企业究竟需要什么样的信…...
美国三种主要的个人数据产业模式简析
文章目录 前言一、个人征信(Credit Reporting)模式1、定义:2、特点:数据来源:核心功能:服务对象:代表性公司:监管框架:示例应用:二、面向垂直场景的个人数据公司(Consumer Reporting,消费者报告模式)1、定义:2、特点:数据来源:核心功能:服务对象:主要公司:监…...
js手撕 | 使用css画一个三角形 使用js修改元素样式 驼峰格式与“-”格式相互转化
1.使用css画一个三角形 借助 border 实现,在 width 和 height 都为 0 时,设置 border,便会呈现三角形。想要哪个方向的三角形,设置其他三边为 透明即可。同时,可以通过调整不同边的宽度,来调整三角形的高度…...
每日一道算法题
题目:最长递增子序列的个数 给定一个未排序的整数数组,找到最长递增子序列的个数。 示例 1 输入:nums [1,3,5,4,7]输出:2解释:有两个最长递增子序列,分别是 [1,3,4,7] 和 [1,3,5,7] 。 示例 2 输入&a…...
低代码系统-产品架构案例介绍、明道云(十一)
明道云HAP-超级应用平台(Hyper Application Platform),其实就是企业级应用平台,跟微搭类似。 通过自设计底层架构,兼容各种平台,使用低代码做到应用搭建、应用运维。 企业级应用平台最大的特点就是隐藏在冰山下的功能很深…...
论文笔记(六十三)Understanding Diffusion Models: A Unified Perspective(三)
Understanding Diffusion Models: A Unified Perspective(三) 文章概括 文章概括 引用: article{luo2022understanding,title{Understanding diffusion models: A unified perspective},author{Luo, Calvin},journal{arXiv preprint arXiv:…...
利用机器学习创建基于位置的推荐程序
推荐系统被广泛应用于不同的应用程序中,用于预测用户对产品或服务的偏好或评价。在过去的几分钟或几小时里,你很可能在网上遇到过或与某种类型的推荐系统进行过互动。这些推荐系统有不同的类型,其中最突出的包括基于内容的过滤和协作过滤。在…...
每日一题 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中,通常会向集合URI(例如 /v1/publishers/1/books )发出GET请求,获取集合中资源的列表。 面向资源设计(AIP…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
