大道至简--API设计的美学
1.前言
对于前端开发而言,肯定会和API打交道,大家也都会想过怎么设计自己的API。优秀的 API 之于代码,就如良好内涵对于每个人。好的 API 不但利于使用者理解,开发时也会事半功倍,后期维护更是顺风顺水。至于怎么设计API,今天就提下我自己的一些建议。如果大家有什么好的想法,欢迎指点。
2.命名
良好的一个命名习惯,就是效率开发的第一步。如果命名规范,对自己而言,文件整理有很大的帮助,后期修改文件、可以快速的定位文件,命名规范,也显得自己专业。对团队而言,如果有统一的规范命名,交接时可以减少大量的学习和沟通成本。
关于命名,下面提点几个小建议
2-1.正确拼写
这个应该说是命名的一个底线了,经常性出现,单词拼写错误,搞得自己或者团队的人都一头雾水的情况不再少数。我遇到情况比较深刻的有
中文大意期望实际表单formfrom报名sign-upsign-in采纳adoptadept内容contentcontend测试testtext联系contactcontract高度heightheigth宽度widthwidht移动mobilemoblie标签tabtap
这些单词,如果是拼写错误还好,至少编辑器都会提醒。但是如果写错了,但是单词又是正确的单词就可大可小了(表单,报名,采纳,内容这些例子,单词写错了,意思变了,但是单词是正确的,编辑器都不会提醒)。
试过挖坑比较深的一次就是:一个活动,有报名,有签到的功能!处理方法如下
获取已报名用户信息:getSignUpUserList,
重置报名的数据:resetSignUpUser,
提交报名操作:signInDo
获取已签到用户信息:getSignInUserList,
重置签到的表单数据:resetSignInUser,
提交签到的操作:signUpDo
修改bug的时候,完全懵逼了,原因大家懂的。
2-2.注意单复数
所有涉及遍历,操作对象,数组,集合的函数,建议都采用复数。
对于展现复数,不同公司有不同的习惯,但是得统一,比如产品列表-productList。这里用了list表示复数,再其它地方,就不建议使用products这种方式表示复数了
2-3.用词准确
这个主要的两方面的内容
2-3-1.单词意思搞错
比如弹窗上面的信息,有些时候见到,使用包含notice的字样,但是实际上,notice的中文意思,准确的应该是‘公告,告示,声明’之类。
一个弹窗这样的会话消息,建议使用message这个字样。notice应该像‘公告,告示,声明’之类的情况使用。
2-3-2.正反词义单词错用
比如关闭弹窗的方法,的方法是closeDialog,然后显示弹窗用的又是showDialog。show的意思是‘显示’,反义词应该是hide‘隐藏’。而close意思是关闭,反义词应该是open。
附常用反义词组(有些带缩写)
inoutonoffprevnextshowhidecloseopensuccessfailbeforeafterbeginend
2-4.命名意义
这一块,本来打算放在2-2里面讲的,因为命名如果有意义也是一个底线。但是最后放在这里,是因为这个情况在函数里面出现得不多,更多应该出现在普通变量里面(相信很多人会遇到过这样的命名:var n1,n2,n3;)。关于命名,还是建议大家要起有意义名称,不使用没意义的命名。
遇到最多的情况,就是图标的命名方面。
比如下面的图标(选自某平台的底部导航栏),点击不同的图标出发不同的方法。
很多人喜欢下面的命名
//版本1function handle1(){ }function handle2(){ }//版本2function handleA(){ }function handleB(){ }//版本3function handleOne(){ }function handleTwo(){ }
这样的命名,别人函数了,就算是元素的 class 。这样的命名在后期维护绝对增加了难度。甚至可能导致重构。
建议的姿势
function handleHome(){ }function handleCollect(){ }
2-5.命名格式
文章说的API,主要针对的是函数,但是在这一小块里面,也列举一下其它的目标的建议命名方式。
待命名对象推荐名称图片‘-’ ‘_’ 分割class,id‘-’ 分割文件,变量驼峰命名临时变量‘_’ 开头,驼峰命名
2-6.处理中文拼音
对于中文拼音,应该说只有一种情况,被中国人创造出来,没有英文翻译的。
命名含义taobao淘宝weibo微博zongzi粽子pinyin拼音
在一年多以前,遇到一个中二的命名-dengluDo。当时一直不知道是什么玩意,后来向那个人打听才知道,是执行登录的操作,denglu是中文拼音,do又是英文,这样的命名。后期如果维护,他不哭,算我输。
2-7.命名潜规则
有些情况,给特定的对象命名,还要用特定的名字,可以说是潜规则吧。印象最清楚的就是给按钮命名要么全拼,要么写btn。很清楚的记得我一个老师说过:写but,bto的程序也能正常运行,也没人说你错,但是我做面试官,就是不录用你,就说你不专业。
待命名对象推荐名称错误示范按钮btnbut bto背景bgback background模板tpltem提示信息msgmes标签栏tabtit网站大图(广告宣传图)bannerban注册registersign-in
3.参数
对于函数而言,参数是用户设置最频繁,也是最关心的部分,合理设计函数参数,这一步很重要,直接影响函数的使用。
3-1.const入参
这个应该说是一个习惯吧,不要直接改变入参的值。这个规则的初衷是解决函数副作用问题。如果参数是一个引用类型的数据,如果在函数内修改了参数,到时候将会使得原本的数据发生改变,往往会发生难以追踪的问题。
3-2.控制参数数量
参数的数量,个人建议就是,超过3个,使用对象进行封装。因为如果API参数越多,那么使用对于这个API的记忆成本就越大,易用性也很受影响。
比如下面的例子:
encryptStr: function (str, regArr, type, replacement) { var regtext = '', Reg = null, _type=type||0, replaceText = replacement || '*'; //ecDo.encryptStr('18819322663',[3,5,3],0) //result:188*****663 //repeatStr是在上面定义过的(字符串循环复制),大家注意哦 if (regArr.length === 3 && type === 0) { regtext = '(\w{' + regArr[0] + '})\w{' + regArr[1] + '}(\w{' + regArr[2] + '})' Reg = new RegExp(regtext); var replaceCount = this.repeatStr(replaceText, regArr[1]); return str.replace(Reg, '$1' + replaceCount + '$2') } //ecDo.encryptStr('asdasdasdaa',[3,5,3],1) //result:***asdas*** else if (regArr.length === 3 && type === 1) { regtext = '\w{' + regArr[0] + '}(\w{' + regArr[1] + '})\w{' + regArr[2] + '}' Reg = new RegExp(regtext); var replaceCount1 = this.repeatStr(replaceText, regArr[0]); var replaceCount2 = this.repeatStr(replaceText, regArr[2]); return str.replace(Reg, replaceCount1 + '$1' + replaceCount2) } //ecDo.encryptStr('1asd88465asdwqe3',[5],0) //result:*****8465asdwqe3 else if (regArr.length === 1 && type === 0) { regtext = '(^\w{' + regArr[0] + '})' Reg = new RegExp(regtext); var replaceCount = this.repeatStr(replaceText, regArr[0]); return str.replace(Reg, replaceCount) } //ecDo.encryptStr('1asd88465asdwqe3',[5],1,'+') //result:"1asd88465as+++++" else if (regArr.length === 1 && type === 1) { regtext = '(\w{' + regArr[0] + '}$)' Reg = new RegExp(regtext); var replaceCount = this.repeatStr(replaceText, regArr[0]); return str.replace(Reg, replaceCount) } }
大家可以看上面的注释,就知道这段代码的具体作用了,如果想想就找个参数,我必须要除了记得4个参数的作用,还要记得参数的顺序。
如果使用对象记录参数,用户只需要记得4个参数的作用,不需要记参数的顺序。
encryptStr: function (obj) { var _default={ type:0, replacement:'*' }; for(var key in obj){ _default[key]=obj[key]; } },//调用方式ecDo.encryptStr({str:'18819266335',regArr:[5],type:0,replacement:'-'});
这样还有一个好处就是,比如像刚才的函数,type这个参数,我想保留默认值,偷懒不传。原来的方案,就得这样传。
ecDo.encryptStr('1asd88465asdwqe3',[5],'','+');
这样肯定是会激起不少有代码洁癖的开发者,比如我。如果使用对象,就很好避免了。
ecDo.encryptStr({str:'18819266335',regArr:[5],replacement:'-'});
3-3.前置相关性高的参数
这个应该没什么可能,就一个意思:必填重要的参数前置,可省略的参数后置。
比如下面的例子
/格式化处理字符串//ecDo.formatText('1234asda567asd890')//result:"12,34a,sda,567,asd,890"//ecDo.formatText('1234asda567asd890',4,' ')//result:"1 234a sda5 67as d890"//ecDo.formatText('1234asda567asd890',4,'-')//result:"1-234a-sda5-67as-d890"formatText: function (str, size, delimiter) { var _size = size || 3, _delimiter = delimiter || ','; var regText = '\B(?=(\w{' + _size + '})+(?!\w))'; var reg = new RegExp(regText, 'g'); return str.replace(reg, _delimiter); },
调用大家都看得出来。如果API这样设计
作者:守候i
链接:https://www.imooc.com/article/44524