版权声明
这个大部分笔记是观看up主红桃A士
的视频记录下来的,因为本人在学习的过程中也经常出现类似的问题,并且觉得Up主的视频讲解很好,做此笔记反复学习,若有侵权请联系删除,此推荐视频地址:【改善丑陋的代码】 https://www.bilibili.com/video/BV1844y1N7S8/p=28&share_source=copy_web&vd_source=688b3f7cfe13111b787853fb99306d7b
本命名规范针对深度学习,根据我平时写代码的时候自己总结的一套规则。
全部采用小写代码,使用名词,不适用动词。
比如我自己的一个代码结构:
---- data: 数据集
---- models:模型
---- dataprocess:数据处理
---- logs:日志文件
---- utils:工具类
驼峰命名法则,开头大写,使用名字、动名词
比如我自己一个代码命名
---- ModelingAbstrct:模型训练抽象类
---- DataSetLoader:数据集加载类
---- DataProcesser: 数据预处理类
驼峰命名法,首字母小写,动词加名词
比如我自己的一个代码命名:
---- def convertWord2Token():将汉字转换成token
---- def loadOriginData():加载原始数据
---- bestMicaroF1:最优微平均
---- maxDoumentLength:最大文本长度
原因:
那么如何又能规范命名?
举一个例子:
给一段我们通常容易写的代码命名
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=false;
List<File>createFiles=new List<File>(...);
foreach(var file in createdFiles){
if(file.daysSinceModification>0){
isFileChanged=true;
break;
}
}
这是优化后的代码,是不是感觉代码的可读性瞬间提高了?
举个小例子,我们需要命名一个整数的天数和时间,看看一般人是怎么命名的,然后大佬又是怎么命名的。
int d; //菜鸡
int days;// 正常
//大佬的命名方式,将天数与用途全部写入命名中
int elapsedTimeInDays;// 流逝的时间天数
int daysSinceCreation;// 创建的时间天数
int daysSinceModdification;//修改的时间天数
int fileAgeInDays;// 文件存在时间天数
//----------------------------------------
int t;
int times;
int timesOfRequestRetry;//请求重复次数
注意点:
名副其实
对象(What)
和计量单位(Count,Time,Day,Minute,Second)
举个小例子
boolean flag; // 我想表达进程是否已经完成
boolean loaded; //我想表达页面是否加载完成
//高级表达
boolean isProcessFinished;
boolean isPageLoaded;
注意点:
前缀词(is,can,has,need)
+名词
+形容词/动词
,让变量更直观通常我在遍历集合的时候,都是用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.拷贝网上的代码用于项目中时
注意:是否有需要调整命名的地方
3.业务逻辑修改之后
注意:是否有命名和现有逻辑不匹配的地方
4.阅读自己或他人之前编写的代码的时候
注意:是否有不符合规范的地方
如果程序员只是为满足编译器或解释器的需要而写代码,就会制造麻烦。
例如:
因为同一作用范围内东西不能重名,你可能会随手改掉其中一个名称,或干脆以错误的拼写充数。
举个例子:
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作为参数名。即清晰表示了变量本身的含义,又不容易有后续命名冲突上的烦恼。
举个例子:
class Product{
...
}
class ProductInfo{
....
}
class ProductdData{
....
}
问题:
Info和Data本身意义含混,无论是否加上它们意义都基本没有区别。
无法体现类之间的不同点,会让代码阅读者抓狂。
优化:
如果打算这样命名,先问自己:
1.多次修改代码后编译一直出现错误
注意:耐心定位代码中的问题,切勿暴躁地随意修改。
2.设计、编码的思考不够
注意:命名时不仅要考虑本身的含义,还需要注意相近意义的区分。
1.研究清楚逻辑后再小心修改。
代码中有相近命名时本身就容易混淆,理解代码逻辑后再修改可以避免重构后引发问题。
2.代码是给程序员阅读和修改的,编码时应尽量从读者的角度去思考。
程序员必须避免留下掩藏代码本意的错误线索。
//通用的简写/缩写
// Get source position
GetSrcPos();
//Convert rgb to gray format
Rgb2Gray();
//可能只有自己才看的懂的
// Set data's status
SetDataSta()
//Query user address
QueryUserAdd();
问题:
优化:
//Set data's status
SetDataStatus();
//Query user address
QueryUserAddress()
1.如果要用简写,就使用通用的/大众认可的。
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
}
}
举个例子:
class Account{
......
}
Account[] accountList;
问题:
别用accountList来表示一组账号,除非它真的是List类型,List对于程序员有特殊意义。
优化:
class Account{
.....
Account[] accountGroup;
Account[] bunchOfAccounts;
Account[] accounts;
删除类型名,用更清晰的命名替代(即便容器是List,也最好别用其命名)。
举个例子:
class XYZControllerForHandlingOfStrings{
}
class XYZControllerForStorageOfStrings{
}
inta= 1;
if(O == 1){
a= O1;
else{
|= 01;
问题:
优化:
避免变量名过于相似(尤其是长变量名),避免使用易混淆字符。
注意:
避免滥用通用单词
问题:
下面就列举几个例子
GetTotalAmount();
上述的函数名是表达什么呢?
获取属性?
获取本地存储内容?
获取网络内容?
获取数据库内容?
获取计算后的内容?
…
AddCharacter();
上述函数名是想表达什么呢?
添加到头部?
添加到尾部?
从中间插入字符?
…
动词 | 用途 | 示例 |
---|---|---|
Create | 创建实例,常用于实例化方法和工厂方法的命名 | CreateInstance |
Initialize | 初始化实例的属性和设置,Initialize本身也可作为类方法用来初始化 | InitializeInstance,Initialize |
Load | 加载配置,根据配置创建内容 | LoadFromConfig |
Destroy | 销毁实例,常用语析构方法 | DestroyInstance |
Uninitialize | 清理实例的属性和设置,通常和Initialize对应 | UninitializeInstance,Uninitialize |
动词 | 用途 | 示例 |
---|---|---|
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 |
动词 | 用途 | 示例 |
---|---|---|
Reset | 强调重置(标记,状态) | ResetTimer |
Refresh | 用于命名刷新(多用于页面,缓存等) | RefreshCurrentPage |
Update | 更新(多用于配置,状态等) | UpdateUserSetting |
动词 | 用途 | 示例 |
---|---|---|
Add | 用于通用添加方法命名 | AddNewStudent |
Append | 强调在尾部添加(追加) | AppendCharacter |
Insert | 强调插入(可以在任意位置) | InsertCharacter |
Delete | 表示删除,和Remove相近 | DeleteDirectory |
Remove | 表示移除,和Delete相近 | RemoveInvalidDeals |
动词 | 用途 | 示例 |
---|---|---|
Open | 开启(多用于开启状态,打开文件等) | OpenEnhanceMode |
Start | 开始(强调开始某个流程) | StartPortListening |
Launch | 发动/启动(多用于启动程序,服务) | LaunchAssistService |
Close | 关闭(多用于关闭状态,关闭文件等) | CloseEnhanceMode |
Stop | 停止(强调流程的终止) | StopPortListening |
Pause | 暂停(强调流程的暂停,有可能后续会继续开启) | PausePageLoading |
Finish | 完成(强调流程的完成) | FinishRequesting |
动词 | 用途 | 示例 |
---|---|---|
Filter | 过滤,筛选(强调按照某些条件) | FilterByName |
Merge | 合并(有时会带上合并规则) | MergeTwoConfig |
Concat | 拼接(直接在结尾添加) | ConcatToArray |
Split | 分割 | SplitInput |
Deduplicate | 去重(去重完全相同的项) | DeduplicateList |
Reverse | 颠倒,反向排列 | ReverseRecord |
Sort | 排序(有时会带上排序规则) | SortDealsByAmount |
Fill | 填充(一般会进行覆盖) | FillAmountList |
动词 | 用途 | 示例 |
---|---|---|
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 |