代码开发规范
前言
学习开发也有些年头,长久以来,深刻体会到编码规范对于一个程序员来说是极其重要的事情。对于一个项目来说,几乎80%的精力都是花费在维护上,因此便于维护是一个项目好坏的重要标准。
即使是自己开发的项目,一段时间过后,再回过头去维护,倘若代码一团糟,也是相当让人抓狂的事情(由指自己)。因此,其实平时有在严格要求自己有一个良好的代码开发规范,但是总觉得有一些问题,只是自己一时并无法找到是什么问题,如何去解决。
今天作为前端,写了一个需要后端返回一个前端要用的数据结构,写了一个json的配置文件,里面的字段作为一个模块的基本信息。组长让我把数据结构写完发给他,让他看看。随后组长便改了一版发给我,而且还挨个讲了改动的原因。真的是听君一席话胜读十年书,顿时感觉之前自己开发的时候出现的一些问题原因找到了。因此在这里作为记录。
基本命名规范
由于我是以前端入门,后面接触了一些python后端。因此这里暂时基本规范的时候,以前端代码为例。其余语言也可作为参考。
在前端开发项目中涉及到命名的地方有很多:目录名,项目名,文件名,函数名,变量名,常量名,参数名,class名,id名等。不同的地方应当结合应用场景采取不同的命名方式,以此达到最佳效果。
不规范的命名
首先先罗列几种不规范的命名。不规范的命名在开发的时候遇到是很头秃的事情,遇到过挺多种,简单罗列几种:
1. 单字母
xxxxxxxxxx
let a = 1;
let b = 2;
2. 数字法
xxxxxxxxxx
<div class="box1"></div>
<div class=“box2”></div>
<div class=“box3”></div>
3. 拼音法
xxxxxxxxxx
function qiandao(){
console.log(“签到成功”)
}
function denglu(){
console.log(“登录成功”)
}
4. 单词拼错
xxxxxxxxxx
function excelImportant(){
console.log(“导入excel文件”)
}
function showErro(){
console.log(“显示错误”)
}
正确的应为:excelImport、showError.
5. 混用法
xxxxxxxxxx
let comment-list = []
let commentList = []
let comment_list = []
“规范”的命名
究其根由,其实并不存在什么真正规范的命名方式。所谓的规范,也只是大多数人都认可的,且新人容易且愿意接受的方式。正如鲁迅所说:世上本没有路,走的人多了,也便成了路。因此,下方罗列的规范,绝非代表了标准,仅仅是本人喜好并且认可的一种命名方式,无需过于计较细枝末节。
1. 目录命名
- 全小写
- 多单词用下划线 "_" 进行连接
- 支持复数
xxxxxxxxxx
scripts, styles, images, data_models
2. 项目名
- 全小写
- 多单词用中划线 "-" 进行连接
xxxxxxxxxx
my-first-project
3. 文件名
HTML文件:
小驼峰式
例:apiUtil.html
CSS文件:
小驼峰式
例:apiUtil.css
JS文件:
小驼峰式
例:apiUtil.js
图片文件:
下划线式
例:login_bg.png
中划线式
例:login-bg.png
注:公司目前用中划线,本人实则喜欢用下划线。
Vue文件:
大驼峰式
例:ApiUtil.vue
注:遵循官网,官网使用的即是大驼峰。
其余文件:
- 小驼峰式
4. JS 命名
函数名
小驼峰式
若有通用的缩写可用缩写,否则务必拼全
确保单词拼写正确
应当由动名词组命名
常用动词约定
动词 含义 can 判断是否可执行某个动作 exist 判断某个值是否存在 get 获取某个值 has 判断是否含有某某个值 load 加载某个数据 is 判断是否为某个值 set 设置某个值
xxxxxxxxxx
// 是否可阅读
function canRead() {}
// 获取名称
function getName() {}
// 是否存在该用户
function existUser() {}
变量名
- 小驼峰式
- 形容词开头
- 若有通用的缩写可用缩写,否则务必拼全
- 确保单词拼写正确
xxxxxxxxxx
let maxCount = 0;
let minCount = 0;
常量名
- 全大写
- 下划线"_"隔开
- 若有通用的缩写可用缩写,否则务必拼全
- 确保单词拼写正确
xxxxxxxxxx
const MAX_COUNT = 0;
类名
- 大驼峰(首字母大写)
xxxxxxxxxx
Class Person() {}
私有属性
全小写
前缀为下划线 "_"
例:_name
5. CSS命名
class名
- 全小写
- 用中划线"-"隔开
xxxxxxxxxx
<div class="main-title"></div>
id名
- 小驼峰式
xxxxxxxxxx
<div id="mainTitle"></div>
实例
今天给需要给后端一份前端需要的接口数据结构,给后端之前给组长审阅了一下,组长修改后返回来了一份新的,并与我挨个讲解修改成这样的原因,听完之后觉得十分有道理,在此记录下来。
原字段结构
xxxxxxxxxx
let reportInfo = {
reportName: "报价单",
leftSubtitle: "左侧标题",
rightSubtitle: “右侧标题”,
templateTitle: “模板标题”,
templateDesc: “模板描述”,
isModuleNewPage: true, // 模块新页面开始
isLayoutNewPage: true, // 排版新页面开始
layoutLists: [ // 排版列表-所有的多个不同种类的排版
{
// layoutCode: "A0001", // 排版的编码
moduleLists: [ // 排版下的模块列表
{
name: “partsInfo”, // 模块名
chinese: “零件信息”, // 模块的中文名
type: “table”, // 模块的类型:table, image, grid, code
checked: false, // 用于前端显示,是否为选中状态,默认为false
isMergeTable: false, // 表格中是否有 合并行/ 合并列, 默认false
partsCount: 30, // 零件数量
partsType: 10, // 零件种类
fieldLists: [ // 字段
{
name: ‘cuttingLen’,
chinese: ‘切割长度’,
isUserAdd: false, // 是否是用户添加
tipText: “”, // 用于前端显示,字段提示信息,默认为空
checked: false, // 用于前端显示,是否为选中状态,默认为false
}, {
name: ‘leadLen’,
chinese: ‘引线长度’,
isUserAdd: false, // 是否是用户添加
tipText: “”, // 用于前端显示,字段提示信息,默认为空
checked: false, // 用于前端显示,是否为选中状态,默认为false
}, {
name: ‘flagLen’,
chinese: ‘打标长度’,
isUserAdd: false, // 是否是用户添加
tipText: “”, // 用于前端显示,字段提示信息,默认为空
checked: false, // 用于前端显示,是否为选中状态,默认为false
}
],
data: [ // 模块下的数据,key与fieldLists中的name相对应
{
cuttingLen: ’30mm’,
leadLen: ’30mm’,
flagLen: ’30mm’,
},
{
cuttingLen: ’30mm’,
leadLen: ’30mm’,
flagLen: ’30mm’,
},
{
cuttingLen: ’30mm’,
leadLen: ’30mm’,
flagLen: ’30mm’,
}
]
}
]
}
]
}
修改后字段结构
xxxxxxxxxx
let reportInfo = {
reportName: "报价单",
leftSubtitle: "左侧标题",
rightSubtitle: “右侧标题”,
templateTitle: “模板标题”,
templateDesc: “模板描述”,
isModuleNewPage: true, // 模块新页面开始
isSheetNewPage: true, // 排版新页面开始
moduleList: [ // 排版下的模块列表
{
moduleCode: "partsInfo", // 模块的编码
moduleTitle: "零件信息", // 模块的标题
moduleDisplayType: “table”, // 模块的类型:table, image, grid, code
isModuleChecked: false, // 用于前端显示,是否为选中状态,默认为false
existMergeTable: false, // 表格中是否有 合并行/ 合并列, 默认false
partQuantityAmount: 30, // 零件数量
partTypeAmount: 10, // 零件种类
fieldList: [ // 字段
{
fieldCode: ‘cuttingLen’,
fieldFormula: ‘cuttingLen+leadLen+flagLen*0.2’,
fieldTitle: '切割长度',
isCustomField: false, // 是否是用户添加
hint: "", // 用于前端显示,字段提示信息,默认为空
isFieldChecked: false, // 用于前端显示,是否为选中状态,默认为false
}, {
fieldCode: ‘leadLen’,
fieldFormula: ‘cuttingLen+leadLen+flagLen*0.2’,
fieldTitle: '引线长度',
isCustomField: false, // 是否是用户添加
hint: "", // 用于前端显示,字段提示信息,默认为空
isFieldChecked: false, // 用于前端显示,是否为选中状态,默认为false
}, {
fieldCode: ‘flagLen’,
fieldFormula: ‘cuttingLen+leadLen+flagLen*0.2’,
fieldTitle: '打标长度',
isCustomField: false, // 是否是用户添加
hint: "", // 用于前端显示,字段提示信息,默认为空
isFieldChecked: false, // 用于前端显示,是否为选中状态,默认为false
}
]
}
]
}
修改地方
isLayoutNewPage => isSheetNewPage
修改原因:
- Sheet在此处比Layout更符合项目背景
layoutLists => moduleList
fieldsList => fieldList
修改原因:
- module比layout更符合项目背景
- 变量中尽量不用复数
S
,对于不可数名词,不加S
会产生歧义,加S会让某些编译器语法检测出现错误提示。非要体现出复数形式,则可以考虑加List
或者Arr
。 - 对于List,Array这种语义上就显然是复数的变量,加
S
没必要。
name => moduleCode
name => fieldCode
修改原因:
- 不要使用通用性很高的名字来命令变量,层级复杂的情况下,会分不清归属关系。
-
尽量不要使用
name
,过于笼统,可用具体一些的Title,Code代替。
chinese => moduleTitle
chinese => fieldTitle
修改原因:
- 属性信息添加上归属的前缀,辨识度高,可读性强。
type => moduleDisplayType
修改原因:
- 通用性很高,归属性不强。加上归属前缀。
- 尽量具体,用于显示的类型,因此加上
display
。
checked => isModuleChecked
checked => isFieldChecked
修改原因:
- 对于布尔类型的数据,最好在前面加上约定好的前缀,易读性更高。
- 通用性很高,归属性不强。加上归属前缀。
isMergeTable => existMergeTable
修改原因:
- 对于判断是否存在的布尔类型变量,使用
exist
前缀易读性更高。
- 对于判断是否存在的布尔类型变量,使用
partsCount => partQuantityAmount
修改原因:
- part代表零件,在这里加不加S,实际效果并不是很强,因此去掉为佳。
- 表示数量时,amount为佳,count在某些编程语言中属于关键字。
isUserAdd => isCustomField
tipText => hint
修改原因:
- 在程序员的世界里,已经有了约定俗成的代表用户区域的通用变量命名,该点属于经验累积。
- 同理,已经有了约定俗成的代表提示语句的通用变量命名。
前端代码规范
很多时候,由于浏览器的兼容性,即使前端代码中存在不规范的地方,但是依旧不会当做错误处理,甚至不会打印报错信息,但约定一些代码规范,可读性更强,辨识度也会更高。
HTML代码
标签
自闭合(self-closing)标签,无需闭合。
xxxxxxxxxx
Bad: <img src="xxx" alt=""></img>
Good: <img src="xxx" alt=""/>
Bad: <br></br>
Good: <br/>
Bad: <input></input>
Good: <input/>
可选的闭合标签(closing tag),需闭合
xxxxxxxxxx
Good: <li></li>
Good: <head></head>
Good: <body></body>
尽可能减少标签数量
Favicon
在未指定 favicon 时,大多数浏览器会请求 Web Server 根目录下的 favicon.ico 。为了保证 favicon 可访问,避免404,必须遵循以下两种方法之一:
- 在 Web Server 根目录放置 favicon.ico 文件;
- 使用 link 指定 favicon。
xxxxxxxxxx
<link rel="shortcut icon" href="path/to/favicon.ico">
语义化
没有 CSS 的 HTML 是一个语义系统而不是 UI 系统。通常情况下,每个标签都是有语义的。
所谓语义就是你的衣服分为外套, 裤子,裙子,内裤等,各自有对应的功能和含义。所以你总不能把内裤套在脖子上吧。
此外语义化的 HTML 结构,有助于机器(搜索引擎)理解,另一方面多人协作时,能迅速了解开发者意图。
xxxxxxxxxx
<html>
<head></head>
<body>
<header></header>
<main></main>
<footer></footer>
</body>
</html>
属性顺序
HTML 属性应该按照特定的顺序出现以保证易读性。
xxxxxxxxxx
id
class
name
data-xxx
src, type, href
title, alt
aria-xxx, role
CSS代码
书写顺序
- 位置属性(position, top, right, z-index, display, float等)
- 大小(width, height, padding, margin)
- 文字系列(font, line-height, letter-spacing, color- text-align等)
- 背景(background, border等)
- 其他(animation, transition等)
xxxxxxxxxx
Bad:
.example {
color:red;
z-index:-1;
background-color:#9e0;
display:inline-block;
font-size:1.5em;
}
Good:
.example {
z-index:-1;
display:inline-block;
font-size:1.5em;
color:red;
background-color:#9e0;
}
使用CSS缩写属性
CSS有些属性是可以缩写的,比如padding,margin,font等等,这样精简代码同时又能提高用户的阅读体验。
xxxxxxxxxx
Bad:
.list-box {
border-top-style: none;
font-family: serif;
font-size: 100%;
line-height: 1.6;
padding-bottom: 2em;
padding-left: 1em;
padding-right: 1em;
padding-top: 0;
}
Good:
.list-box {
border-top: 0;
font: 100%/1.6 serif;
padding: 0 1em 2em;
}
不要随意使用id
id在JS是唯一的,不能多次使用,而使用class类选择器却可以重复使用,另外id的优先级优先与class,所以id应该按需使用,而不能滥用。
xxxxxxxxxx
Bad:
#title {
font-size: 16px;
}
Good:
.title {
font-size: 16px;
}
为选择器添加状态前缀
有时候可以给选择器添加一个表示状态的前缀,让语义更明了,比如下图是添加了“.is-”前缀。
xxxxxxxxxx
Bad:
.active {
background-color: #ccc;
}
Good:
.is-active {
background-color: #ccc;
}
Javascript代码
命名规范
前缀为形容词
函数前缀为动词, 以此来区分函数和变量
xxxxxxxxxx
// 好的命名方式
let maxCount = 10;
let tableTitle = '啦啦啦';
// 不好的命名方式
let setConut = 10;
let getTitle = '啦啦啦';
注释规范
单行注释
xxxxxxxxxx
// 设置标题
setTitle()
多行注释
xxxxxxxxxx
/*
* 代码执行到这里后会调用setTitle()函数
* setTitle():设置title的值
*/
setTitle();
函数 & 方法注释
xxxxxxxxxx
/**
* 函数说明
* @关键字
**/
注:在webstorm中,在函数名前一行先输入 /*
,随后直接回车便可自动补全对应函数参数注释
至此,代码规范暂告一段落,日后若有补充,会进行更新。