当前位置: 首页 > Web前端 > CSS

代码质量管理——如何写出优雅的代码

时间:2023-03-30 22:12:23 CSS

作为一个刚刚写代码的菜鸟,半年多的工作让我更加认识到提高代码质量的重要性。以前只专注于实现功能,慢慢开始关注性能。在这个阶段,我发现其实有很多细节(比如可读性、易用性、可维护性和一致性)是提高代码质量的关键。“实现功能”和“优雅地实现功能”是两件不同的事情。注:大部分内容整理自网络,对多篇文章的观点进行了归纳处理,也综合了一些个人观点。原则单一职责原则易用性原则可读性原则复杂性守恒原则:不管你怎么写代码,复杂性都不会消失注意:如果逻辑复杂,那么代码就应该看起来复杂。如果逻辑简单,代码应该看起来简单。单一职责原则是面向对象设计模式的五个基本原则之一。也就是说,一部分代码应该只用于特定的功能,不应该与其他功能耦合。假设你的一个函数同时实现了函数a和函数b,后来需求发生变化,你需要修改函数a,但是因为这两个函数在一个函数里,所以你要确认是否会影响到函数b.这会产生不必要的成本。如下,我总结了三个拆分代码的原则:“and”原则当你在方法命名的时候不得不加“and”的时候,就要考虑是否拆分方法了。“100”原则当你的一个函数超过一百行时,就必须拆分。注意:这里的100个可能有点多,但对我个人而言,100个是我的极限。简而言之,永远不要把函数写得太长。命令和查询拆分原则我们开发中的大部分操作都可以概括为“命令”和“查询”。比如写入cookies、修改数据、发送post请求都可以称为“命令”,而读取cookies、ajax获取数据则认为是“命令”。是“查询”操作。在函数式编程中,强调“数据不变性”,即:只有没有副作用的纯函数才是合格函数。副作用:调用函数时,除了返回函数值外,还会对主调用函数产生额外的影响。比如修改全局变量(函数外的变量)或者修改参数。优点是它使开发更容易、可跟踪、测试友好,并减少任何可能的副作用。拆分“command”和“query”其实是函数式编程思想的一部分,参考下面的代码:firstName=firstName.toLowerCase();setCookie("名字",名字);如果(firstName===null){返回“”;}returnfirstName;}varactiveFirstName=getFirstName();从名字上看,这个方法是用来获取名字的,但实际上还设置了cookie,这是我们没有想到的。对于一个“查询”方法,它不应该有任何在方法外修改变量的行为,即“副作用”。更好的写法如下:}returnfirstName;}setCookie("firstName",getFirstName().toLowerCase());一眼看去,getFirstName只返回firstName,设置cookie的操作是在它之外进行的。易用性的原则很简单。这里的简单主要归结为函数的一些设计原则,包括以下几点:调用简单、易于理解、减少内存开销、参数处理。如下,只是想修改dom的颜色,宽度等属性,原生代码如下:document.querySelector('#id').style.color='red'document.querySelector('#id').style.width='123px'document.querySelector('#id').style.height='456px'封装后:functiona(selector,color,width,height){document.querySelector(selector).style.color=colordocument.querySelector(selector).style.width=widthdocument.querySelector(selector).style.height=height}a('#a','red')变得简单易用~不过还是有一个这种方法的问题,就是命名太抽象了。..不看源码,除了开发者自己,任何人都不可能一眼就看出这个方法a做了什么。然后让我们重写方法名称,使其更容易理解:.querySelector(selector).style.height=height}这样我们就可以一目了然这个方法的作用了~不过还有优化的空间。谁能记住这么长的方法名?为了减少内存开销,更改名称:selector).style.height=height}OK,到目前为止这个方法已经完成了它的职责并且运行良好,但仍然感觉很奇怪。这一堆参数太突兀了。..functionsetElement(selector,opt){const{color,width,height}=optcolor&&document.querySelector(selector).style.color=colorwidth&&document.querySelector(selector).style.width=widthheight&&文档。querySelector(selector).style.height=height}组合多个参数,内部进行兼容性处理。这种方法更容易使用。即使不传第二个参数,也不会有副作用。一致性假设有这样一个方法可以获取歌曲列表并将其设置到div的innerText中:})}这违反了方法的内外一致性,也违反了上面单一职责原则中的命令和查询拆分原则,因为它不仅获取了歌曲列表,还修改了innerText使其更合理:要么改名字,要么拆分成两种方法低耦合耦合是衡量一个程序单元对其他程序单元的依赖程度。应尽可能避免耦合(或高耦合)。如果您发现自己复制和粘贴代码并进行小的更改,或者因为在其他地方进行了更改而重写代码,这就是高耦合的标志。耦合会严重影响代码的复用性和可扩展性,以至于后人在维护时不得不修改甚至重写这部分代码,不仅浪费时间,还会导致仓库中出现另一段类似的代码,即容易混淆人。同时,在修改耦合度较高的代码时,往往会牵一发而动全身。如果在修改时不理清这些耦合关系,后果可能不堪设想,尤其是对于需求变更较多、人员较多的情况。协同开发和维护的项目,修改一个地方就会导致已经稳定运行的模块出现错误,严重时会导致恶性循环。问题永远不会得到纠正。用户满意度降低,成本增加,对用户和开发者的影响非常恶劣,各种风险不言而喻。高内聚不应该把没有关系的东西堆在一起。凝聚力是衡量类中变量和方法之间联系强度的指标。高凝聚力是可取的,因为这意味着类可以更好地完成工作。低内聚性不好,因为它表明类中的元素很少相互关联。每种方法也应该是高度内聚的。大多数方法只执行一个功能。不要向该方法添加“额外”说明。这样会导致方法执行更多的功能,也违反了上面的单一职责原则。低内聚的迹象:如果一个属性没有被类中的多个方法使用,这可能是低内聚的迹象。同样,如果一个方法不能在几种不同的情况下重用,或者如果一个方法根本没有被使用,这也可能是低内聚的标志。高内聚有助于缓解高耦合,这是需要高内聚的标志。但是,如果同时存在两个问题,则应选择聚合方法。对于开发人员来说,高内聚通常比低耦合更有帮助,尽管两者通常可以一起完成。ErrorhandlingForeseeableerrors:ajax回调、函数参数等问题很容易解决。开发过程中只需要多走一步,就可以兼容各种极端情况。不可预见的错误:类似兼容性问题,开发时无法准确预见的错误,可以准备抛出错误,console.error/log/warn,最后给程序留点余地:try...catch。可读性原则命名命名应该保证别人一眼就能知道这个变量持有什么或者这个方法是用来干什么的。常用变量和属性使用名词如下:varperson={name:'Frank'}varstudent={grade:3,class:2}bool变量和属性使用(形容词)or(be动词)or(情态动词)or(hasX),如下:varperson={dead:false,//如果是形容词,前面不用加is,比如isDead就是废话canSpeak:true,//情态动词包括can,should,will,need等,情态动词后接动词isVip:true,//be动词包括is,was等,后跟名词hasChildren:true,//has加号名词}普通函数和方法以(verbs):varperson={run(){},//不及物动词drinkWater(){},//及物动词eat(foo){},//及物动词加参数(参数是名词)}callback,hookfunction:varperson={beforeDie(){},afterDie(){},//orwillDie(){}dead(){}//这与bool冲突,只要你不暴露booldead和function同时死掉,怕冲突就用上面的afterDie}button.addEventListener('click',onButtonClick)varcomponent={beforeCreate(){},created(){},beforeMount(){}}命名一致性顺序一致性:比如updateContainerWidth和updateHeightOfContainer的顺序很别扭时候一致性:有可能随着代码的变化,变量的含义与其原来的含义不同。这时候就需要及时更改变量的名称。这个是最难做的,因为写代码容易,改起来难。如果代码组织不好,很可能会牵一发而动全身(比如全局变量很难改变)。注释不需要花哨,只要功能和用法描述清楚即可。一个方法的标准注释应该如下:/***[function_namedescription]*@param{[type]}argument[description]*@return{[type]}[description]*/functionfunction_name(argument){//身体。..}把方法的参数和返回值写清楚。我目前使用的IDE非常出色。使用Docblockr插件可以自动生成格式化评论,非常方便。我们在BadSmell项目中经常会遇到这种代码。它们仍然可用,但它们“发臭”了。这种代码在国外有个统称,就是“臭味”。下面这种代码可以说是很“臭”了:长得不像的代码,过时的注释逻辑很简单,但是看起来很复杂的代码,重复的代码,相似的代码,总是这样的代码一起出现,没有使用的代码,不同的依赖风格的代码风格规范正确命名:类必须用“-”来写,而不是驼峰式和下划线。正确嵌套:一般情况下,类嵌套必须关闭,否则相当于添加到全局,如果有重复的命名类,就会受到影响。拒绝照搬:如果想复用已有的样式,可以直接用“,”语法把原来的类分割开来,然后套用即可。不要复制另一种样式,这两种样式都将应用。你必须考虑样式覆盖问题,非常不友好。滥用类:不要添加不需要的类。添加每个类应该有一个明确的原因。类的滥用可能会导致样式覆盖,在不该应用的地方使用了这种样式。谨慎使用!important,它会强行覆盖所有具有相同属性的样式,一旦使用,会使代码难以维护。在开发过程中切勿依赖此方法。一些使用!important的经验总结如下:一定要优化并考虑优先使用样式规则来解决问题,而不是只在需要覆盖整个站点或外部css的特定页面使用!important(例如引用ExtJs或YUI)!important可以用来解决紧急的在线问题,但之后尽快以可维护的方式替换回代码永远不要在站点范围的css上使用它!important永远不要在你的插件中使用它!important说起来容易做起来难打破窗口效应。该学说认为,如果任由环境中的不良现象存在,就会诱发人们效仿,甚至愈演愈烈。以一栋有几扇窗户破损的建筑物为例,如果那些窗户不修好,可能会有更多的窗户被破坏者破坏。最终他们甚至会闯入建筑物,如果发现无人居住,可能会在那里定居或放火烧毁它们。一堵墙,如果有一些涂鸦没有清理掉,很快就会被乱七八糟、不堪入目的东西覆盖;有一点五彩纸屑的人行道很快就会有更多的垃圾,最终人们会忽略它。把垃圾扔在地上是理所当然的事。这种现象,犯罪心理学中的破窗效应,在编程领域也同样存在。要做:只要代码经过你的手,就会比以前更好。参考文章:javascript的api设计原则CodingwithClarityDon'tleavebrokenwindowsstartswithJSobjects,talkabout"immutabledata"andfunctionalprogrammingrefactoring-codeoptimizationtechniqueshowandwhentouseCSS!importantcsspriority