写代码时候的命名规则、命名规范、命名常用词汇

版权声明
这个大部分笔记是观看up主红桃A士的视频记录下来的,因为本人在学习的过程中也经常出现类似的问题,并且觉得Up主的视频讲解很好,做此笔记反复学习,若有侵权请联系删除,此推荐视频地址:【改善丑陋的代码】 https://www.bilibili.com/video/BV1844y1N7S8/p=28&share_source=copy_web&vd_source=688b3f7cfe13111b787853fb99306d7b

1.命名规则

本命名规范针对深度学习,根据我平时写代码的时候自己总结的一套规则。

1.1 路径命名规则

全部采用小写代码,使用名词,不适用动词。
比如我自己的一个代码结构:

---- data: 数据集
---- models:模型
---- dataprocess:数据处理
---- logs:日志文件
---- utils:工具类

1.2 代码文件/类命名

驼峰命名法则,开头大写,使用名字、动名词
比如我自己一个代码命名

---- ModelingAbstrct:模型训练抽象类
---- DataSetLoader:数据集加载类
---- DataProcesser: 数据预处理类

1.3 函数/变量命名规则

驼峰命名法,首字母小写,动词加名词
比如我自己的一个代码命名:

---- def convertWord2Token():将汉字转换成token
---- def loadOriginData():加载原始数据
---- bestMicaroF1:最优微平均
---- maxDoumentLength:最大文本长度

2.高可读命名规范

2.1 为什么命名这么重要

原因:

  • 第一眼被人看到,留下第一印象
  • 看不懂代码片段的时候,会结合命名进行联想
  • 获取某个范围中的关键信息时,会使用全局字符查找

那么如何又能规范命名?

  • 变量名能否看出这个变量关联什么东西
  • 变量名是否能够看出变量是用来做什么的?

举一个例子:
给一段我们通常容易写的代码命名

class File
{
int d;
}
bool flag=false;
List<File>list1=new List<File>(....);
foreach(var item in list1)
	{
	if(item.d>0){
		flag=true;
		break;
	}
}

看了这段代码是不是很熟悉,就像我们平时写的代码一样,代码中的变量没有人和语义信息,需要联系上下文才可以看出代码所表达的含义。

** 优化命名规范:**

class File
{
int daysSinceModifycation;
}

bool isFileChanged=falseList<File>createFiles=new List<File>(...);
foreach(var file in createdFiles){
	if(file.daysSinceModification>0){
		isFileChanged=true;
		break;
	}
}

这是优化后的代码,是不是感觉代码的可读性瞬间提高了?

2.2 变量的命名规范

2.2.1 整型变量命名

举个小例子,我们需要命名一个整数的天数和时间,看看一般人是怎么命名的,然后大佬又是怎么命名的。

int d; //菜鸡
int days;// 正常

//大佬的命名方式,将天数与用途全部写入命名中
int elapsedTimeInDays;// 流逝的时间天数
int daysSinceCreation;// 创建的时间天数
int daysSinceModdification;//修改的时间天数
int fileAgeInDays;// 文件存在时间天数

//----------------------------------------
int t;
int times;

int timesOfRequestRetry;//请求重复次数

注意点:

  • 1.如果命名需要注释来补充,那其本身就不算名副其实
  • 2.明确计量对象(What)计量单位(Count,Time,Day,Minute,Second)

2.2.2 布尔类型变量命名

举个小例子

boolean flag; // 我想表达进程是否已经完成
boolean loaded; //我想表达页面是否加载完成

//高级表达
boolean isProcessFinished;
boolean isPageLoaded;

注意点:

  • 1.以正逻辑为主(个人习惯), 减少反逻辑带来的可读性影响
  • 2.前缀词(is,can,has,need) +名词+形容词/动词,让变量更直观

2.2.3集合型变量命名

通常我在遍历集合的时候,都是用item作为变量,如果有多个item的时候时候,就会混淆。
举个例子:

List<File>list1=new List<File>(....) // 创件一个file list
foreach(var item in list){
........
}


//---------------规范表达--------------------
List<File>createdFiles=new List<File>(.....);
foreach(var file in createdFiles){
..........
}

注意点:

  • 1.对于自定义类型名,可以考虑作为变量名中的一部分
  • 2.加_上复数表示,可以让遍历操作的代码可读性更加直观

最后对开始的案例进行一个规范的修改:

2. 3变量命名容易出现名不副实的场景

1.使用简单代码调试之后准备正式使用的时候
注意:是否有测试时图方便而命名不规范的地方

2.拷贝网上的代码用于项目中时
注意:是否有需要调整命名的地方

3.业务逻辑修改之后
注意:是否有命名和现有逻辑不匹配的地方

4.阅读自己或他人之前编写的代码的时候
注意:是否有不符合规范的地方

2.4 比较建议的重构原则

  • 定要全局修改所有引用处,避免存在全局变量的影响
  • 只要看到不规范的地方,就可以顺手修改,避免以后忘记
  • 每一处小小的优化都是对代码质量的提升

3.对变量做有意义的区分

如果程序员只是为满足编译器或解释器的需要而写代码,就会制造麻烦。
例如:
因为同一作用范围内东西不能重名,你可能会随手改掉其中一个名称,或干脆以错误的拼写充数。

3.1 案例分析

3.1.1 数字系列命名

举个例子:

public void copyChars(char a1[],char a2[]){
	for(int i=0;i<a1.length;i++)
		a2[i]=a1[i]
	}
}

问题:
依义命名成了依数命名,这样的名称纯属误导,没有提供正确信息,对可读性带来危害。
后续如果还存在相近的变量,仍然存在命名冲突的烦恼。

优化:

public void copyChars(char sourceChars[],char destinationChars[]){
	for(int i=0;i<a1.length;i++)
		destinationChars[i]= sourceChars[i]
	}
}

使用sourceChars/source和destinationChars/destination作为参数名。即清晰表示了变量本身的含义,又不容易有后续命名冲突上的烦恼。

3.1.2 nonsense命名

举个例子:

class Product{
	...
}

class ProductInfo{
	....
}

class ProductdData{
	....
}

问题:
Info和Data本身意义含混,无论是否加上它们意义都基本没有区别。
无法体现类之间的不同点,会让代码阅读者抓狂。

优化:
如果打算这样命名,先问自己:

  • 几个类之间具体的含义/功能区别是什么,是否有必要分成多个类?
  • 如果有必要区分,是否具有更清晰的命名? (通常一一定可以找到更有区别意义的命名)

3.2 变量名容易出现无意义区分的场景

1.多次修改代码后编译一直出现错误
注意:耐心定位代码中的问题,切勿暴躁地随意修改。
2.设计、编码的思考不够
注意:命名时不仅要考虑本身的含义,还需要注意相近意义的区分。

3.3 比较建议的重构原则

1.研究清楚逻辑后再小心修改。
代码中有相近命名时本身就容易混淆,理解代码逻辑后再修改可以避免重构后引发问题。
2.代码是给程序员阅读和修改的,编码时应尽量从读者的角度去思考。

4.避免误导命名

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

4.1 误导的来源:

  • 1.缩写/简写误导
  • 2.多义词汇误导
  • 3.变量类型误导
  • 4.外形相似误导

4.2 案例分析

4.2.1 缩写/简写误导一使用的缩写/简写只有自己认知

//通用的简写/缩写
// Get source position
GetSrcPos();

//Convert rgb to gray format
Rgb2Gray();

//可能只有自己才看的懂的
// Set data's status
SetDataSta()

//Query user address
QueryUserAdd();

问题:

  • 1.使用的简写/缩写形式不一定每人都能理解,需要具体研究代码才明白。
  • 2.简写/缩写的结果不规范,出现同义词的情况。

优化:

//Set data's status
SetDataStatus();
//Query user address 
QueryUserAddress()

1.如果要用简写,就使用通用的/大众认可的。
2.不确定是否能被理解的情况下尽量用全写,这样不会有问题。

4.2.2 多义词汇误导——出现其他含义的联想

原文举例: hp、aix、 sco不该用作变量名,因为都是Unix平台的专有名称。
举个例子:

//开始时间or持续时间
public bool SetMonitorTime(){
//Set something
/Windows注册表or登记机关?
public string QueryRegistryContent(){
//Query something
}

问题:
如果没有上下文语境的提示,会有双关含义。

优化:

public bool SetMonitorStartTime(){
//Set something
}
class WindowsRegistry{
	public string QueryRegistryContent(){
	//Query something
	}
}
  • 1.添加对应上下文的语境,比如迁移到类中或者模块里,方便理解。
  • 2.更换/添加对应单词。

4.2.3 变量类型误导——一某些命名会让人误解变量的类型

举个例子:

class Account{
	......
}
Account[] accountList;

问题:
别用accountList来表示一组账号,除非它真的是List类型,List对于程序员有特殊意义。

优化:

class Account{
	.....
	Account[] accountGroup;
	Account[] bunchOfAccounts;
	Account[] accounts;

删除类型名,用更清晰的命名替代(即便容器是List,也最好别用其命名)。

4.2.4 外形相似误导一-两个命名过于相近/含有 易混淆字符

举个例子:

class XYZControllerForHandlingOfStrings{
}
class XYZControllerForStorageOfStrings{
}
	inta= 1;
	if(O == 1){
	a= O1;
	else{
	|= 01;

问题:

  • 两个命名过于相似,阅读者看到后可能产生误会。
  • O,0,o以及i, 1这样的字符很相近,容易看错。

优化:
避免变量名过于相似(尤其是长变量名),避免使用易混淆字符。

5.函数命名常见误区以及命名规则总结

5.1 动词滥用问题

注意:
避免滥用通用单词

问题:

  • 通用单词可以在很多场景下命名,但不能区分具体函数职责。
  • 当函数本身的实现途径不同时,难以从函数名得到足够的信息

下面就列举几个例子

5.1.1 万能的Get

GetTotalAmount();

上述的函数名是表达什么呢?

获取属性?
获取本地存储内容?
获取网络内容?
获取数据库内容?
获取计算后的内容?

5.1.2 万能的Add

AddCharacter();

上述函数名是想表达什么呢?

添加到头部?
添加到尾部?
从中间插入字符?

5.2 各类函数命名动词详细总结

5.2.1 创建/销毁

动词 用途 示例
Create 创建实例,常用于实例化方法和工厂方法的命名 CreateInstance
Initialize 初始化实例的属性和设置,Initialize本身也可作为类方法用来初始化 InitializeInstance,Initialize
Load 加载配置,根据配置创建内容 LoadFromConfig
Destroy 销毁实例,常用语析构方法 DestroyInstance
Uninitialize 清理实例的属性和设置,通常和Initialize对应 UninitializeInstance,Uninitialize

5.2.2 获取/设置

动词 用途 示例
Get 常用于取属性的类方法命名,也可作为通用获取方法命名 GetStartTime
Fetch 通过网络请求获取内容 FetchAllUsers
Calculate 通过计算获取内容 CalculateTotalAmount
Read 读取(多用于文件,配置等) ReadFile,ReadConfig
Query 查询 QueryRemainingAmount
Find 查找(多用于数据库,集合等),和search相似 FindOrder
Receive 接收(多用于文件,消息等) ReceiveNewMessage
Pull 拉取 PullLastestSourceCode
Set 常用于设置属性的类方法命名,也可作为通用设置方法命名 SetStartTime
Write 写入(文件/配置等) WriteFile,WriteConfig
Put 放入 PutUserWithId
Push 存入,推送(通知) PushNotification

5.2.3 更新

动词 用途 示例
Reset 强调重置(标记,状态) ResetTimer
Refresh 用于命名刷新(多用于页面,缓存等) RefreshCurrentPage
Update 更新(多用于配置,状态等) UpdateUserSetting

5.2.4 添加/移除

动词 用途 示例
Add 用于通用添加方法命名 AddNewStudent
Append 强调在尾部添加(追加) AppendCharacter
Insert 强调插入(可以在任意位置) InsertCharacter
Delete 表示删除,和Remove相近 DeleteDirectory
Remove 表示移除,和Delete相近 RemoveInvalidDeals

5.2.5 启动/停止

动词 用途 示例
Open 开启(多用于开启状态,打开文件等) OpenEnhanceMode
Start 开始(强调开始某个流程) StartPortListening
Launch 发动/启动(多用于启动程序,服务) LaunchAssistService
Close 关闭(多用于关闭状态,关闭文件等) CloseEnhanceMode
Stop 停止(强调流程的终止) StopPortListening
Pause 暂停(强调流程的暂停,有可能后续会继续开启) PausePageLoading
Finish 完成(强调流程的完成) FinishRequesting

5.2.6 集合类型相关数据处理

动词 用途 示例
Filter 过滤,筛选(强调按照某些条件) FilterByName
Merge 合并(有时会带上合并规则) MergeTwoConfig
Concat 拼接(直接在结尾添加) ConcatToArray
Split 分割 SplitInput
Deduplicate 去重(去重完全相同的项) DeduplicateList
Reverse 颠倒,反向排列 ReverseRecord
Sort 排序(有时会带上排序规则) SortDealsByAmount
Fill 填充(一般会进行覆盖) FillAmountList

5.2.7 通用业务数据处理

动词 用途 示例
Parse 解析(解析成某些格式,解析提取某些内容) ParseFromJson,ParseResult
Analyse 分析(不一定能通过简单的方式获取) AnalyseLocation
Convert 类型转换(通常用于从一个类型转换到另一种类型) ConvertToString
Format 格式化数据 FormatToLocaleString
Validate 合法性/有效性的校验 ValidateUserInputs
Ensure 期待值的校验 EnsureUserAge
Compose 组成(一般由多项内容组成一个结果) ComposeMessage
Encode 编码(依赖约定的编码格式) EncodeUrl
Decode 解码(依赖约定的解码格式) DecodeUrl
Encrypt 数据加密(依赖约定的加密算法) EncryptContent
Decrypt 数据解密(依赖约定的解密算法) DecryptContent
Backup 备份(需要注意拷贝方式,避免误导) BackupUserSettings
Restore 恢复 RestoreUserSettings
Import 导入(通常用于按照特定格式的文件转换) ImportFromFile
Export 导出(通常用于转换成特定格式的文件) ExportToFile
Compress 压缩(依赖约定的算法) CompressOversizedFile
Decompress 解压缩(依赖约定的算法) DecompressOversizedFile

你可能感兴趣的:(#,设计模式,代码命名规范)