什么是编码规范?
代码规范是指程序员在编码时要遵守的规则,规范的目的就是为了让程序员编写易于阅读、可维护的代码
为什么要制定一个属于团队的编码规范?
- 规范的代码可以促进团队合作,方便大家更好的接手彼此的代码
因为几乎没有任何一个软件,在其整个生命周期中,均由最初的开发人员来维护 - 规范的代码可以降低开发和维护成本
可以让团队成员尽快地理解业务代码,更好的去开发和维护
具体的编码规范
总体约定
坚持组织应用的结构,力求:快速定位 (Locate) 代码、一眼识别 (Identify) 代码、 保持扁平结构 (Flattest) 和尝试 (Try) 遵循 DRY (Do Not Repeat Yourself, 不重复自己) 原则。
四项基本原则定义文件结构,上面的原则是按重要顺序排列的。
快速定位
坚持直观、简单和快速地定位代码。
为何?
要想高效的工作,就必须能迅速找到文件,特别是当不知道(或不记得)文件名时。 把相关的文件一起放在一个直观的位置可以节省时间。
一眼识别
坚持命名文件到这个程度:看到名字立刻知道它包含了什么,代表了什么
为何?
花费更少的时间来查找和琢磨代码,就会变得更有效率。
保持扁平结构
为何?
没人想要在过多层级的目录中查找文件。扁平的结构有利于搜索。
举一个例子
在 A 页面中需要 B , C 两个组件,而 B 又需要 D E 组件,E组件又需要F组件的支撑
错误示范
erDiagram
A ||--o{ B : contains
B ||--|{ D : contains
B ||--|{ E : contains
E ||--|{ F : contains
A ||--o{ C : contains
正确示范
erDiagram
A ||--o{ B : contains
A ||--o{ D : contains
A ||--o{ E : contains
A ||--o{ F : contains
A ||--o{ C : contains
为何?
这种结构也更有利于组件的提取,方便其他组件复用
T-DRY(尽量不重复自己)
坚持DRY(Don't Repeat Yourself,不重复自己)。
避免过度 DRY,以致牺牲了阅读性。
为何?
虽然 DRY 很重要,但如果要以牺牲 LIFT 的其它原则为代价,那就不值得了。 这也就是为什么它被称为 T-DRY。
文件结构约定
以react举例,项目文件总览如下
- api 项目中的前后端交互的接口
- component 项目中通用的组件
- hooks 项目中用到的hooks
- router 项目中的路由
- stores 项目中的数据管理
- theme 项目中的主题
- utils 项目中通用的方法,常量,正则等
页面详细分布如下:
里面包含如下信息:
- 页面SpecialFund下面有两个子业务,分别是IndexPage和NewKineticFunds
- NewKineticFunds下面的主流程在 index.js中,所需组件在components下,分别是
DataBoard 和 DataStatistics
- 在 DataBoard 中主流程在 index.js,所需常量在constant.js,所需方法在utils.js
然后在实际操作中,当我们发现有多个组件共用一个方法或常量时,我们就可以把它提取到项目根目录中的utils中
这样的话,后续过来接手的人,无论是过来开发还是维护都能够很轻松的找到要修改的地方,大大的提升开发效率和开发体验
单一职责
单一规则
坚持每个文件只定义一样东西,考虑把文件大小限制在 200 行代码以内
为何?
单组件文件非常容易阅读、维护,并能防止在版本控制系统里与团队冲突。
为何?
单组件文件可以防止一些隐蔽的程序缺陷,当把多个组件合写在同一个文件中时,可能造成共享变量、创建意外的闭包,或者与依赖之间产生意外耦合等情况
为何?
让代码更加可复用、更容易阅读,减少出错的可能性。
最好将组件及其支撑部件重新分配到独立的文件
如将组件中的常量提取到constant.js中,将组件中的方法提取到utils.js中
小函数
坚持定义简单函数,考虑限制在 30 行之内。
为何?
简单函数更易于测试,特别是当它们只做一件事,只为一个目的服务时。
为何?
简单函数促进代码复用。
为何?
简单函数更易于阅读,同时也更容易维护。
命名
总体命名
坚持所有符号使用一致的命名规则,并遵循同一个模式来描述符号的特性和类型
为何?
命名约定提供了一致的方式来查找内容,让你一眼就能找到
为何?
命名约定帮助你更快得找到想找的代码,也更容易理解它
文件命名
坚持为所有东西使用一致的命名约定,以它们所代表的东西命名。
为何?
遵循一致的约定可以快速识别和引用不同类型,方便我们快速的识别文件中有什么
如:
- constant 表示常量,则里面的内容都是常量
- utils 表示工具,里面的内容都是方法
- interceptor 表示拦截,则里面的内容都是属于接口拦截器的定义
- regex 表示正则,则里面的内容都是正则表达式
...等等
为何?
类型名可以让你轻松利用编辑器或者 IDE 的模糊搜索功能找到特定文件类型。
代码细则
组件内部涉及到异步操作,里面必须添加回调或返回promise
为何?
方便其他人在调用时,知晓异步操作何时完成,并进行后续操作
错误示范
export const loadMapScript = (funcName = 'initMap') => {
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = `https://map.qq.com/api/gljs?v=1.exp&key=${TENXUMAP_KEY}&callback=${funcName}&libraries=tools,service`;
document.body.appendChild(script);
};
正确示范
export const loadMapScriptP = (funcName = 'initMap') => {
return new Promise((resolve, reject) => {
const mapId = 'tx_map';
const mapScriptEle = document.getElementById(mapId);
if (mapScriptEle || window.TMap) {
return resolve();
}
const script = document.createElement('script');
script.type = 'text/javascript';
script.id = mapId;
script.src = `https://map.qq.com/api/gljs?v=1.exp&key=${TENXUMAP_KEY}&callback=${funcName}&libraries=tools,service`;
script.onload = () => {
resolve();
};
script.onerror = () => {
reject();
};
document.body.appendChild(script);
});
};
推荐多行注释
在编写方法时,若有必要添加注释,推荐多行注释
为何?
方便调用时,一眼看出该方法的用途,而单行注释没有被IDE更好的展示
举例
参考资料
百度前端代码规范 www.bookstack.cn/read/ecomfe…
Angular风格指南 angular.cn/guide/style…