Featured image of post 《重构》-代码的坏味道

《重构》-代码的坏味道

神秘命名

整洁代码最重要的一环就是好的名字,所以我们会深思熟虑如何给函数、模块、变量和类命名,使他们能清晰表面自己的功能和用法。

  • 需要考虑取一个好的名字

重复代码

如果你在一个以上的地点看到相同的代码结构,那么可以肯定:设法将它们合而为一,程序会变得更好。

  • 抽取重复代码,使之能够复用

过长函数

据我们的经验,活得最长、最好的程序,其中的函数都比较短。

短的函数具有更好的阐释力、更易于分享、更多的选择。

函数越长,就越难理解。

每当感觉需要以注释来说明点什么的时候,我们就把需要说明的东西写进一个独立函数中,并以其用途(而非实现手法)命名。

条件表达式和循环常常也是提炼的信号。

  • 可以考虑使用横屏显示器进行开发,这样潜意识里就不会把一个函数写的过长

过长的参数列表

过长的参数列表本身也经常令人迷惑。

如果可以向某个参数发起查询而获得另一个参数的值,那么就可以使用以查询取代参数去掉第二个参数。

使用类可以有效地缩短参数列表。

  • Go中可以使用struct的方式,来传入较多的参数

全局数据

全局数据是最刺鼻的坏味道之一。

一次又一次,全局数据造成了哪些诡异的bug,而问题的根源却在遥远的别处,想要找到出错的代码难于登天。

良药与毒药的却别在于剂量。有少量的全局数据或许无妨,但数量越多,处理的难度就会指数上升。

  • 尽量少使用全局变量

可变数据

对数据的修改经常导致出乎意料的结果和难以发现的bug。

如果可变数据的值能在其他地方计算出来,这就是一个特别刺鼻的坏味道。

发散式变化

一旦需要修改,我们希望能够跳到系统的某一点进行修改,只在此处进行修改。如果不能做到这一点,你就能嗅出两种紧密相关的刺鼻味道中的一种了。

  • 一个类受多种变化的影响

散弹式修改

如果遇到某种变化,你都必须在许多不同的类内做出许多小修改,你所面临的坏味道就是散弹式修改。

  • 一种变化引发多个类对应改动

依恋情结

所谓模块化,就是力求将代码分出区域,最大化区域内部的交互、最小化跨区域的交互。

如果一个函数跟另一个模块的函数或者数据交流格外频繁,远胜于在自己所处模块内的交流,这就是依恋情结的典型情况。

  • 函数对某个类的兴趣高过对自己所处类的兴趣

数据泥团

你常常可以在很多地方看到相同的三四项数据:两个类中相同的字段、许多函数签名中相同的参数。

  • 两个类中同样的字段、很多函数签名中同样的參数
  • 这种情况汪汪和历史遗留问题相关

基本类型偏执

大多数编程环境都大量使用基本类型,即整数、浮点数和字符串等。

一个有趣的现象:很多程序员不愿意创建对自己的问题域有用的基本类型。

字符串是这种坏味道的最佳培养皿,比如,电话号码不只是一串字符。

重复的switch

我们现在更关注重复的switch:在不同的地方反复使用同样的switch逻辑(可能是以switch/case语句的形式,也可能是以连续的if/else语句的形式)。应该以多态取代条件表达式消除掉。

  • 例如可以使用策略模式等方式

循环语句

函数作为一等公民以及得到广泛的支持,因此我们可以使用以管道取代循环来让这些老古董退休。

管道操作(如 filter和map)可以帮助我们更快地看清被处理的元素以及他们的动作.

冗赘的元素

程序元素(如类和函数)能给代码增加结构,从而支持变化、促进复用或者哪怕只提供更好的名字也好,但有时我们真的不需要这层额外的结构。

  • 可能有这样一个函数,他的名字就跟实现代码看起来一模一样。
  • 可能有这样一个类,根本就是一个简单的函数。

夸夸其谈通用性

如果函数或类的唯一用户是测试用例,这就飘出了这个坏味道。 如果发现这样的函数或类,可以先删掉测试用例,然后移除死代码。

临时字段

某个字段仅为某种特定情况而设。这样的代码让人不易理解,因为你通常认为对象在所有时候都需要它的所有字段。在字段未使用的情况下猜测当初设置它的目的,会让你发疯。

过长的消息链

如果你看到用户向一个对象请求另一个对象,然后再向后者请求另一个对象,然后再请求另一个对象——这就是消息链。

在实际代码中你看到的可能是一长串取值函数或者一长串临时变量。

中间人

对象的基本特征之一就是封装——对外部世界隐藏其内部细节。

封装往往伴随着委托。

但是人们可能过度运用委托。你也许会看到某个类的接口有一半的函数都委托给其他类,这样就是过度运用。

内幕交易

如果两个模块总是窃窃私语,就应该用搬移函数和搬移字段减少它们的私下交流,把这种交易都放到明面上来。

如果两个模块有共同的兴趣,可以尝试再新建一个模块,把这些公用的数据放在一个管理良好的地方。

过大的类

如果想利用单个类做太多事情,其内往往就会出现太多字段。一旦如此,重复代码也就接踵而至了。

异曲同工的类

使用类的好处之一在于可以替换:今天用这个类,未来可以换成另一个类。

纯数据类

所谓纯数据类是指:他们拥有一些字段,以及用于访问(读写)这些字段的函数,除此之外一无长物。

如果发生这种情况,你应该在别人注意到之前,立刻运用封装记录将他们封装起来。

被拒绝的遗赠

子类应该继承超类的函数和数据。但如果他们不想或不需要继承,又该怎么办呢?他们得到所有礼物,却只从中挑选几样来玩!

这种情况就不要虚情假意地糊弄继承体系,应该运用委托取代子类或者委托取代超类彻底划清界限。

注释

别担心,不是说你不该写注释。

有写注释存在是因为代码很糟糕,这种情况的发生次数之多,实在令人吃惊。

注释可以带我们找到本章先前提到的各种坏味道。

当你感觉需要撰写注释时,请先尝试重构,试着让所有注释都变得多余。 如果你需要注释来解释一块代码做了什么,试试提炼函数。如果函数已经提炼出来,试试用改变函数声明为它改名,再或者引入断言。如果你实在不知道该做什么,这才是注释的良好运用时机。

除了用来记述将来的打算之外,注释还可以用来标记你并无十足把握的区域,比如你可以在注释里写下自己“为什么做某某事”。这类信息可以帮助将来的修改者,尤其是那些健忘的家伙。

其他

本文笔记原链接:https://blog.csdn.net/u014779536/article/details/107309260 其内容也主要出自《重构-改善既有代码的设计》

Owner Rainbowly
Total [] user views [] site views [] page views
Built with Hugo
主题 StackJimmy 设计