代码质量管理,老程序员教你写出优雅,容错率高,可读性强的代码

2023-06-01 0 679

那时的该文是纯控制技术纯文档的,没有意思相片,控制技术党复本,阿宝提升复本,读要学的重定向variations也有社会福利。

代码质量管理,老程序员教你写出优雅,容错率高,可读性强的代码

提升标识符产品质量的关键性有,时效性,可用性,可移植性,连续性。“与此同时实现机能”跟“典雅的与此同时实现机能”是有区别的。

准则

单一职能准则可用性准则时效性准则繁杂性能量守恒准则(注:方法论繁杂,标识符看上去就如果很繁杂,方法论单纯,标识符也相较单纯)

单个职能准则

程序语言四大程序语言基本上准则众所周知。即一小部分标识符只如果用作某三个某一机能,不如果与其它机能谐振在一同。

假定你的三个function与此同时与此同时实现了机能a和机能b,后市场需求更改,你须要修正机能a,但即使三个机能都在三个function里,你就不得已再去证实与否会负面影响到机能b。这就造成了无谓的生产成本。

如下我总结三个拆分标识符准则:

“and”准则

当你为你的方法命名时不得已加上“and”时,就如果考虑考虑是不是要把这个方法拆分一下。

“100”准则

当你的三个function超过一百行时,一定要进行拆分了。(注:100可能有点多,这是我个人而言,100算是我的极限,总之就是绝对不要将三个函数写太长。)

命令,查询拆分准则

我们开发中大部分操作可以总结为“命令”和“查询”,如写cookie,修正

函数式编程中讲究“数据不可变”,即:只有纯的没副作用的函数,才叫合格函数(副作用:指当调用函数时,除了返回函数值之外,还对主调用函数产生附加的负面影响。例如修正全局变量(函数外的变量)或修正参数)。

好处是使得开发更加单纯,可回溯,测试友好,减少了任何可能的副作用。

将“命令”与“查询”拆分实际上就是函数式编程思想的部分体现,参考如下标识符:

function getFirstName(){var firstName = document.querySelector(“#firstName”).value;firstName = firstName.toLowerCase();setCookie(“firstName”, firstName);if(firstName ===null){return””;}return firstName;}var activeFirstName = getFirstName();

e,这是我们没预料的,对于三个“查询”方法,它不如果有任何修正方法外变量的行为,即“副作用”。更好的写法如下:

function getFirstName(){var firstName = document.querySelector(“#firstName”).valueif(firstName ===null){return””;}return firstName;}setCookie(“firstName”, getFirstName().toLowerCase());

一目了然,getFirstName只返回firstName,而设置cookie操作在它之外进行。

可用性准则

单纯

这里的简单,主要归结为function的一些设计准则,有如下几点:调用单纯、易理解、减少记忆生产成本、参数处理。

如下,仅仅想与此同时实现修正dom颜色、宽度等属性,原生标识符如下:

document.querySelector(#id).style.color =reddocument.querySelector(#id).style.width =123pxdocument.querySelector(#id).style.height =456px

而封装过后:

function a(selector, color, width, height){document.querySelector(selector).style.color = colordocument.querySelector(selector).style.width = widthdocument.querySelector(selector).style.height = height}a(#a,red)

瞬间变得单纯可用了 ~

但该方法还存在三个问题,那就是命名太抽象了。。。除了开发者自己以外不可能有人在不看源码的情况下一眼看出这个方法a是干嘛的。那么咱再把这个方法名改写得更易理解一点:

function letSomeElementChange(selector, color, width, height){document.querySelector(selector).style.color = colordocument.querySelector(selector).style.width = widthdocument.querySelector(selector).style.height = height}

这样我们就能一目了然该方法的作用 ~ 不过仍有可优化的地方。这么长的方法名谁记得住,要减少记忆生产成本啊,再改个名:

function setElement(selector, color, width, height){document.querySelector(selector).style.color = colordocument.querySelector(selector).style.width = widthdocument.querySelector(selector).style.height = height}

OK,目前这个方法已经满足它的职能并且很好用了,但还觉得怪怪的。这一坨参数太碍眼。。。

function setElement(selector, opt){const{ color, width, height }= optcolor && document.querySelector(selector).style.color = colorwidth && document.querySelector(selector).style.width = widthheight && document.querySelector(selector).style.height = height}

把多个参数合并一下,并在内部做兼容处理,这个方法便易用多了。即使不传第二个参数也不会有任何副作用。

连续性

中:

function getSongs(){return $.get(/songs).then((response) {div.innerText = response.songs})}

这就违背了方法

低谐振

谐振是衡量三个程序单元对其它程序单元的依赖程度。谐振(或高谐振)是如果极力避免的。如果你发现自己正在复制和粘贴标识符并进行小的更改,或者重写标识符,即使其它地方发生了更改,这就是高谐振的体现。

谐振会严重负面影响标识符的复用性及可扩展性,让后人维护时不得已修正甚至重写这部分代码,不仅浪费时间还会导致仓储中又多出一块类似的标识符,很容易让人迷惑。

与此同时,修正谐振度高的标识符时经常会牵一发而动全身,如果修正时没理清这些谐振关系,那么带来的后果可能会是灾难性的,特别是对于市场需求变化较多以及多人协作开发维护的项目,修正三个地方会引起本来已经运行稳定的模块错误,严重时会导致恶性循环,问题永远改不完,开发和测试都在各种问题之间奔波劳累,最后导致项目延期,用户满意度降低,生产成本也增加了,这对用户和开发商负面影响都是很恶劣的,各种风险也就不言而喻了。

高内聚

不如果将没任何联系的东西堆到一同。

内聚是三个类中变量与方法连接强度的尺度。高内聚是值得要的,即使它意味着类可以更好地执行一项工作。低内聚是不好的,即使它表明类中的元素之间很少相关。每个方法也如果高内聚,大多数的方法只执行三个机能,不要在方法中添加‘额外’的指令,这样会导致方法执行更多的函数,与此同时也违反了上文的单个职能准则。

低内聚的体现:如果属性没被类中的多个方法使用,这可能是低内聚的标志。同样,如果方法在几种不同的情况下不能被重用,或者如果三个方法根本不被使用,这也可能是低内聚的三个标志。

高内聚有助于缓解高谐振,高谐振是须要高内聚的标志。但,如果三个问题与此同时存在,应当选择内聚的方式。对于开发者来说,高内聚通常比低谐振更有帮助,尽管两者通常可以一同完成。

错误处理

可预见的错误:诸如ajax回调、函数参数,这类问题很好解决,只需在开发时多考虑一步,对各种极端情况做好兼容即可。不可预见的错误:类似兼容性问题,这类问题无法在开发时准确预见的错误,可以准备好抛错,console.error/log/warn,最后你还可以为自己的程序留些后路: try…catch。

时效性准则

命名

命名如果保证别人通过名称一眼就能知道这个变量保存的是什么,或者这个方法是用来做什么的。

普通变量、属性用名词如下:

var person ={name:Frank}var student ={grade:3,class:2}

bool变量、属性用(形容词)或者(be动词)或者(情态动词)或者(hasX),如下:

var person ={dead:false,// 如果是形容词,前面就没必要加 is,比如isDead 就很废话canSpeak:true,//情态动词有 can、should、will、need 等,情态动词后面接动词isVip:true,// be 动词有 is、was 等,后面一般接名词hasChildren:true,// has 加名词}

普通函数、方法用(动词)开头:

var person ={run(){},// 不及物动词drinkWater(){},// 及物动词eat(foo){},// 及物动词加参数(参数是名词)}

回调、钩子函数:

var person ={beforeDie(){},afterDie(){},// 或者willDie(){}dead(){}// 这里跟 bool 冲突,你只要不与此同时暴露 bool dead 和函数 dead 就行,怕冲突就用上面的 afterDie}button.addEventListener(click, onButtonClick)var component ={beforeCreate(){},created(){},beforeMount(){}}

命名连续性

顺序连续性:比如 updateContainerWidth 和 updateHeightOfContainer 的顺序就令人很别扭时间连续性:有可能随着标识符的变迁,三个变量的含义已经不同于它一开始的含义了,这个时候你须要及时改掉这个变量的名字。

这一条是最难做到的,即使写标识符容易,改标识符难。如果这个标识符组织得不好,很可能会出现牵一发而动全身的情况(如全局变量就很难改)

注释

不须要多花哨,只要把作用、用法描述清楚即可。方法的标准注释如果如下:

/*** [function_name description]* @param {[type]} argument [description]* @return {[type]} [description]*/function function_name(argument){// body…}

将方法的参数与返回值都写清楚,我目前用的IDE是sublime,使用Docblockr插件可以自动生成格式化注释,很方便。

Bad Smell

项目中我们经常能够遇这类标识符,它们仍可用,但很“臭”,国外管这类标识符有三个统称,即“bad smell”。如下这类标识符可以说是很“臭”了:

表里不一的标识符过时的注释方法论很单纯,但看上去很繁杂的标识符重复的标识符相似的标识符总是一同出现的标识符未使用的依赖不同风格的标识符

样式规范

正确命名:class必须用“-”写法,不要用驼峰和下划线。正确嵌套:正常情况下一定要将class嵌套闭合,否则就相当于添加到全局,如果有重复命名的class就会受负面影响。拒绝copy:如果想复用已有的样式,直接在原有class上用“,”语法分割,就能应用,不要再copy一份样式,会让两份样式都被应用,就要考虑样式覆盖的问题,很不友好。滥用class:没必要加的class不要加,每个class的添加都如果有明确理由。滥用class的话可能会导致样式覆盖,不该应用这个样式的地方用了这个样式。慎用 !important,会强行覆盖所有同属性样式,一旦使用后会让标识符难以维护,开发过程中绝对不要依赖该方法。如下总结了一些使用 !important的经验:

一定要优化考虑使用样式规则的优先级来解决问题而不是 !important只有在须要覆盖全站或外部 css(例如引用的 ExtJs 或者 YUI )的某一页面中使用 !important解决紧急线上问题可以使用,但后也要尽快用可维护的方式将标识符替换回来永远不要在全站范围的 css 上使用 !important永远不要在你的插件中使用 !important

说得容易,做起来难

破窗效应

此理论认为环境中的不良现象如果被放任存在,会诱使人们仿效,甚至变本加厉。一幢有少许破窗的建筑为例,如果那些窗不被修理好,可能将会有破坏者破坏更多的窗户。最终他们甚至会闯入建筑内,如果发现无人居住,也许就在那里定居或者纵火。一面墙,如果出现一些涂鸦没被清洗掉,很快的,墙上就布满了乱七八糟、不堪入目的东西;一条人行道有些许纸屑,不久后就会有更多垃圾,最终人们会视若理所当然地将垃圾顺手丢弃在地上。这个现象,就是犯罪心理学中的破窗效应,在编程领域同样存在。

要做到:只要是经过你手的标识符,都会比之前好一点。

讲了这么多,现在推荐一套视频《标识符简洁之道》,还有附带我职业生涯整理总结的全套前端教学视频,从浅到深都讲得很详细。评论或私信“领资料”。即可

代码质量管理,老程序员教你写出优雅,容错率高,可读性强的代码
举报/反馈

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务