重构技巧-提炼函数

这是《重构-改善既有代码的设计》这本书的原文

动机

        提炼函数是我最常用的重构之一。(在这儿我用了“函数/function”这个词,但换成面向对象语言中的“方法/method”,或者其他任何形式的“过程/procedure”或者“子程序/sybroutine”,也同样适用)我会浏览一段代码,理解其作用,然后将其提炼到一个独立的函数中,并以这段代码的用途为这个函数命名。    对于“何时应该把代码放进独立的函数”这个为题,我曾经听过多种不同的意见,有的观点从代码的长度考虑,认为一个函数应该能在一屏中显示。有的观点从复用的角度考虑,认为只要被用过不止一次的代码,就应该单独放进一个函数;只用过一次的代码则保持内联(inline)的状态。但我认为最合理的观点是“将意图与实现分开”:如果你需要花时间浏览一段代码才能弄清楚它到底在干什么,那么就应该将其提炼到一个函数中,并根据他所做的事为其命名,以后再读到这段代码时,你一眼就能看到函数的用途,大多数的时候根本不需要关心函数如何达成其用途(这是函数体内干的事)。

        一旦接受了这个原则,我就逐渐养成一个习惯:写非常小的函数----通常只有几行的长度。在我看来,一个函数一段超过六行,就开始散发臭味。我甚至经常会写一些只有一行代码的函数。Kent beck曾向我展示最初的Smalltalk系统中的一个例子,从那时起我就接受了“函数名的长度不重要”的观念。那时运行Smalltalk的计算机只有黑白屏显示器,如果你想高亮凸显默写文本或图像,就需要翻转视频的现实。为此,Smalltalk用于控制图像显示的类有一个叫做highlight的方法,其中的实现就只是调用reverse方法。在这个例子里,highlight方法的名字比实现还长,但这并不重要,因为在这个方法中,代码的意图与实现之间有着相当大的差距。

       有些人担心段函数会造成大量函数调用,因而影响性能。在我尚且年轻时,有时确实会有这个问题;但如今“由于函数调用影响性能”的情况已经非常罕见了。短函数常常能让编译器的优化功能运转更良好,因为段函数可以更容易地被缓存。所以,应该始终遵循性能优化的一般指导方针,不用过早担心性能问题。

       小函数得有个好名字才行,所以你必须在命名上花心思。起好名字需要练习,不过一旦你掌握了其中的技巧,就能写出很有自描述性的代码。

       我经常会看见这样的情况: 在一个大函数中,一段代码的顶上放着一句注释,说明这段代码要做什么。在把这段代码提炼到自己的函数中时,这样的注释往往会提示一个好名字。

做法

        创造一个新函数,根据这个函数的意图来对它命名(以它“做什么”来命名,而不是以它“怎么做”命名)。

        如果想要提炼的代码非常简单,例如只要新函数的名称能够以更好的方式昭示代码意图,我还是会提炼它。不过,我不一定非得马上想出最好的名字,有时在提炼的过程中好的名字才会出现。有时我会提炼一个函数,尝试使用它,然后发现不太合适,再把它内联回去,这完全没问题。只要在这个过程中学到了东西,我的时间就没有白费。

         如果编程语言支持潜逃函数,就把新函数嵌套在源函数里,这能减少后面需要处理的超出作用于的变量个数。我可以稍后再使用《搬移函数》把它从源函数中搬移出去。    将带提炼的代码从源函数复制到新建的目标函数中。仔细检查提炼出的代码,看看其中是否引用了作用于限于源函数、在提炼出的新函数中访问不到的变量。若是,一参数形式将它们传递给新函数。

         如果提炼出的新函数嵌套在源函数的内部,就不存在变量作用于的问题了。

         这些“作用域限于源函数”的变量通常是局部变量或者源函数的参数。最通用的做法是将它们都作为参数传递给新函数。只要没有提炼部分对这些变量赋值,处理起来就没有什么难度。              如果某个变量是在提炼部分之外声明但只在提炼部分被使用,就把变量声明也搬移到提炼部分代码中去。

         如果变量按照传递给提炼部分又在提炼部分被赋值,就必须多加小心。如果只有一个这样的变量,我会尝试将提炼出的新函数变成一个查询,用其返回值给该变量赋值。

         但有时在提炼部分被赋值的局部变量太多,这是最好先放弃提炼。这种情况下,我会考虑先使用别的重构手法,例如拆分变量或者以查询取代临时变量,来简化变量的使用情况,然后再考虑提炼函数。所有变量都处理完之后,编译。如果编程语言支持编译期检查的话,在处理完所有变量之后再做一次编译是很有用的,编译器经常会帮你找到没有被恰当处理的变量。在源函数中,将被提炼代码段替换为对目标函数的调用。

         测试。

        查看其他代码是否有与被提炼的代码段相同或者相似之处。如果有,考虑使用以函数调用取代内联代码令其调用提炼出的新函数。有些重构工具直接支持这一步。如果工具不支持,可以快速搜索一下,看看别处是否还有重复代码。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容

  • 这是《重构-改善既有代码的设计》这本书的原文 动机 提炼函数是我最常用的重构之一。(在这儿我用了“函数/func...
    还仙阅读 431评论 0 0
  • 《重构》读书笔记 总览 第一部分 第一章从实例程序出发,展示设计的缺陷,对其重构可以了解重构的过程和方法。 第二部...
    白桦叶阅读 2,371评论 2 5
  • 可以先看【推荐】:https://www.jianshu.com/p/d6ff54d72afb原文:http://...
    郭某人1阅读 1,831评论 0 0
  • (一)重构原则 1、何谓重构 对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低...
    小村医阅读 2,237评论 7 14
  • 弟子规中,“丧尽礼,祭尽诚”。 这句话是说,对死者也要怀有真诚之心,对待失去的人,就像对待生者一样。如果父母活着的...
    历宁阅读 768评论 0 5