shenfq转载本文请联系LoveSmile的架构师公众号。MartinFowler:任何白痴都可以编写计算机可以理解的代码。一个好的程序员只能写出人类容易理解的代码。大家闭上眼睛想想什么是好的代码?也许你脑子里飘着一堆词:干净、整洁、命名规范、注释合理、高内聚低耦合……每个人都想写出好的代码,因为看好代码就像看女人一样有好的特性,心情舒畅,看烂代码就像看到腐烂的食物,同样臭气熏天。大多数人写出的代码都不能称为好代码。一方面,由于自身技能的限制,另一方面,他们可能无法区分好代码和坏代码。下面,笔者将结合日常编码实践,与大家分享常用代码。不好吃。Badtaste:LongMethod(toolongfunction)简而言之,太长的函数就是函数的长度超过标准,包括水平和垂直。为什么太长的函数有难闻的气味?如果函数横向太长,无法一眼看出这行代码的作用。你需要用鼠标慢慢拖动它。相信小屏的朋友经常会遇到这个问题。拖拽的过程会严重影响阅读代码的效率。垂直太长意味着有大功能。一个函数中的行数过多,导致函数难以阅读,也难以修改代码。那么如何解决函数过长的问题呢?关于横向过长的问题,一般都是提前在IDE中配置最大宽度,比如80个字符或者120个字符(具体根据公司内部规范设置),然后格式化代码即可解决。比如我们写Java8的流链表达式,可以很长:Listnodes=list.stream().filter().filter().map.filter().collect(Collectors.toList());//可能会很长。其实我们可以在.之前把这一行包起来,这样一目了然。Listnodes=list.stream().filter().filter().map.filter().collect(Collectors.toList());竖长的问题其实是这个方法或者函数的职责不够单一,一个函数里面堆放了太多的函数。重构的方法很简单:ExtractMethod,主动抽取函数或方法,隐藏细节,保持单一职责。恶趣味:LargeClass(太大的类)通常被称为神类(GodClass)。神级一般指维护的功能太多(违反单一职责原则),连神都看不懂你的代码。知识百科设计模式的六大原则是:SingleResponsibilityPrinciple:单一职责原则OpenClosedPrinciple:开闭原则LiskovSubstitutionPrinciple:里氏代换原则LawofDemeter:Dimit'sLawInterfaceSegregationPrinciple:InterfaceSegregationPrincipleDependenceInversionPrinciple:DependencyInversionPrinciple六个原则的首字母组合为SOLID,两个L视为一个。那么如何判断一个类是不是神类呢?一般同时满足以下三个条件的类就是神类:(1)CPFD(CapsulesProvidingForeignData)指的是来自多个不相关类(模块)的数据。(2)WOC(WeightedOperationCount)类所有函数的圈复杂度之和超过65。(3)TCC(TightCapsuleCohesion)TCC<1/3该类需要具有低内聚特性(比类中直接相关的方法占所有方法的不到1/3),即私有方法较少。为什么一个太大的类会产生难闻的气味?一个太大的类承担了太多的职责,往往有很多重复的代码,你要找到这些重复的代码并不容易。这基本上是难闻气味的开始。由子类继承的超大类会导致其他难闻的气味,例如遗产遗赠。如何解决班级过大的问题?通过观察这个过大类的属性,看看是否有一些属性关联。如果有,你可以使用ExtractClass将这些关联的属性抽象成一个新的类,并将它们与这些属性组合起来。所有相关操作都移到了新类中。通过观察这个超大类的方法,看看是否有任何函数或方法具有兄弟关联。如果有,可以使用ExtractSubclass的方法将这些方法提取到子类中,子类可以继承父类。将相似的行为方法集中在一个类中,拆分成多个类,可以进一步解耦发布调用。重复上述方法,可以将一个大类拆分成多个职责单一的小类。BadTaste:DuplicatedCode(重复代码)RobertC.Martin:重复可能是软件中万恶之源。重复代码一般是复制粘贴造成的。需求迭代过程中,为了不影响已有功能,通常是复制之前的代码修改然后匆匆上线。那么为什么重复的代码有难闻的气味呢?最直接的缺点就是如果要修改一段代码逻辑,可能会遗漏,甚至需要多次修改才能保证全部修改完成。如何解决重复代码的问题?下面结合代码实践介绍几种场景。场景一:同一个类中的两个方法包含相同的表达式重构后:classA{publicvoidmethod1(){baseMethod();logic3}publicvoidmethod2(){baseMethod();logic4}publicvoidbaseMethod(){logic1logic2}}场景二:同父类的两个子类包含相同的表达式有一个method1在公式类A中,它具有三个逻辑部分。classAextendBase{publicvoidmethod1(){logic1logic2logic3}}B类中有一个method2和三块逻辑。classBextendBase{publicvoidmethod2(){logic1logic2logic3}}重构方法:将重复的代码抽象成一个方法放在父类中,不同的部分由子类实现。重构后:classBase{publicvoidbaseMethod(){logic1logic2}}classAextendBase{publicvoidmethod1(){baseMethod();logic3}}classBextendBase{publicvoidmethod2(){baseMethod();logic3}}场景三:两个不相关的类出现重复代码如果有两个没有直接关联的类中有重复代码,可以考虑将重复代码抽象成一个独立的公共类或工具类,适用方可以组合调用。代码示例这里不再赘述,和场景一、场景二类似,相信聪明的你都能看懂。Badtaste:LongParameterList(太长的参数列表)全局变量是邪恶的东西,数据是共享的,每个线程都可以修改,太多容易导致程序不可控,所以大家都喜欢用变量作为参数传递,随着时间的推移,参数列表变得越来越长。为什么太长的参数列表有难闻的气味?方法参数过多会导致代码可读性非常差。如果有多个重载方法,它们的方法参数都非常大,写代码时很难判断调用了哪一个。当一个方法需要增加新的功能时,可能每次都会增加一个新的方法参数,这会导致调用者每次都重新适配,小心被打,老鼠尾汁。如何解决参数列表太长的难闻问题?可以将多个参数封装到一个DTO对象中,方法之间的对象通过对象传递,而不是通过太长的参数传递。数据传输对象(DTO)是一种用于在设计模式之间传输数据的软件应用系统。特别需要提醒的是,长参数在某些情况下也是合理的,因为使用参数可以避免某些依赖的产生。在编码实践中,我们可以观察到长参数方法。如果这个方法经常变化,你应该考虑重构这个方法。基本原则:不超过三个东西,三个重构。Badsmell:ShotgunSurgery(shotgunmodification)为什么shotgunmodification是一种不好的代码味道?如果你需要修改一个小的功能,你需要在很多不同的类中修改它。可能漏掉了,这种问题一般称为shotgunmodification。publicclassA{@Value("${db.mysql.url}")privateStringmysqlDbUrl;}publicclassB{@Value("${db.mysql.url}")privateStringmysqlDbUrl;}如果有多个类使用db.mysql。对于url这个变量,后面如果想把mysql转成oracle,可能会涉及到多次修改。如何解决shotgun修改的坏代码味道?可以使用MoveMethod(移动函数)和MoveField(移动字段)把所有需要修改的代码放到同一个类中。如果暂时没有合适的类,就自己创建一个。Badsmell:SpeculativeGenerality(吹嘘未来)在工作中,经常听到一些开发小伙伴说:昨天加班,修改了订单模块,以后就可以了……听到这话可以鼓掌:牛叉,advanceExtensibility是为函数模板保留的。不过先别急着崩溃,看看技术总监脸都黑了,为什么?这位小伙伴的代码可能是臭味:谈未来。为什么谈论未来是一种糟糕的代码味道?互联网需要快速迭代更新。“Futurecan”表示目前不需要。有时过度抽象和保留扩展会使系统难以理解,可能会提前进行。行李继续前进。总是在代码中谈论未来的可能性会让团队陷入困境。每次业务发生变化,开发者都会考虑未来的各种可能性,预留足够多的扩展接口,这无疑大大增加了代码的复杂度,拖慢了一个可能很快上线的需求。如何解决吹嘘未来的坏代码味道?代码架构设计中有一个原则叫做:SimpleDesign(简单设计原则)。在实现当前业务代码时,需要考虑四个原则:通过测试、揭示原理图、消除重复和最小化元素。当您需要为将来编写代码时,您可以执行以下操作:(1)删除您认为将来有用的参数、代码和方法调用。(2)修改方法名,使方法名揭示当前业务场景的意图,避免抽象的技术描述符。如果以后确实一定会发现代码改动,建议保留。未来主义的修辞更多是关于开发人员毫无根据地推测未来,导致过度设计的代码模块。恶臭:评论(评论太多)列举了一些在?中常见的评论恶臭:嘟嘟囔囔的多余评论误导性评论遵守规则评论期刊评论胡说八道的评论用评论来解释变量的含义标记位置的评论属于的评论类注释掉的代码为什么太多的注释是一种糟糕的代码味道?好的注释可以帮助开发人员快速阅读和理解代码,太多的注释或不好的注释可能会降低代码可读性的效率。在开发实践中,经常有同学修改了代码,但是注释没有同步修改。代码实现与注释内容不一致,容易误导。怎么解决评论太多的臭味?(1)如果代码块不再使用,请直接删除,不要使用注释。(2)方法和变量的名称尽量清晰,避免用注释重复解释。(3)如果较短的注释不能涵盖方法的含义,可能是这个方法的职责不单一,可以考虑重构这个方法。简介:文章列出了几种常见的不良代码味道。希望大家在工作编码中多多练习,争取大家写出好的代码,这样世界上就没有难读的代码了。