从文章"避免复制与粘贴"到文章"Extract Method"的反思(2)
好了.在上一篇里面讲了讲怎么把临时变量应该从函数里面剔除去.这个过程叫做从临时变量变成查询
那么接下来我们聊聊把代码提炼成函数,有叫做用函数对象取代函数
那么,问题来了:在函数中什么样的代码是需要被提炼出来单独成为函数的? 一般而言 代码里面的注释会指出 代码用途 和 实现手法直接的语义距离. 这里就暗示着如果代码前方有一行注释的话就以为这这里是需要提炼成函数的,并且可以在代码的基础上给这行代码命名(所以啊,这里的函数名很重要,因为他还承担了注释的作用,要让人看了这个函数名就能知道这个函数在干神马). 就算是一行代码,如何需要用注释来说明的话,也是有必要提炼成函数的.
----->
这里还有一些现场的规则来指导我们怎么做:
做法:
1、创造一个新函数,根据这个函数的意图对它命名(以它“做什么“命名,而不是以它“怎样做”命名)。
即使你想要提炼的代码非常简单,例如只是一条消息或一个函数调用,只要新函数的名称能够以更好方式昭示代码意图,你也应该提炼它。但如果你想不出一个更有意义的名称,就别动。
2、将提炼出的代码从源函数复制到新建的明白函数中。
3、仔细检查提炼出的代码,看看其中是否引用了“作用域限于源函数”的变量(包括局部变量和源函数参数)。
4、检查是否有“仅用于被提炼代码段”的临时变量。如果有,在目标函数中将它们声明为临时变量。
5、检查被提炼代码段,看看是否有任何局部变量的值被它改变。如果一个临时变量值被修改了,看看是否可以将被提炼代码处理为一个查询,并将结果赋值给修改变量。如果很难这样做,或如果被修改的变量不止一个,你就不能仅仅将这段代码原封不动提炼出来。你可能需要先使用Split Temporary Variable (分解临时变量),然后再尝试提炼。也可以使用 Replace Temp with Query (以查询取代临时变量)将临时变量消灭掉。
6、将被提炼代码段中需要读取的局部变量,当做参数传给目标函数。
7、处理完所有局部变量后,进行编译。
8、在源函数中,将被提炼代码段替换给对目标函数的调用。
如果你将如何临时变量移到目标函数中,请检查它们原本的声明式是否在被提炼代码段的外围。如果是,现在可以删除这些声明式了。
9、编译,测试。
函数中的条件表达式和循环也是提炼的信号. 循环没什么好言明的,应该讲循环和循环内部的代码提炼成一个函数. 接下来讲讲 条件表达式的提炼 官方叫做分解条件表达式
所谓的条件表达式就是下面的形式
if
.......
then
.......
else
......
分解条件表达式的动机:复杂的条件逻辑是程序复杂度上升点之一.因为你必须编写代码来判断不同的条件,而不同的条件下有做不同的事情.因为就会得到一个相当大的函数了.相当大的函数本身就意味着可读性的降低而条件逻辑则会使代码更难阅读。在带有复杂条件逻辑的函数中,代码(包括检查条件分支的代码和真正实现功能的代码)会告诉你发生的事,但常常让你弄不清为什么会发生这样的事
而我们分解条件表达式就是为了能够突出条件的逻辑结构.
看下面的例子吧:
------>
实际工作中,要一步一步的进行每一次的条件表达式的提炼,并在每次提炼之后编译并测试。这里需要注意的是,一般条件下我们程序员可能都不会去提炼条件,可能是因为这些条件非常短[指的是if(xxx)--->这里的xxx].但是尽管可能很短,很可能在代码意图和代码自身之间存在很大的差距.就像上面的例子 notSummer(data) 就要比 date.before(SUMMER_START) || date.after(SUMMER_END)这样的逻辑条件跟好的表达出代码的用途来,从而看起来就像是注释一样的清晰明了.
看完例子我们再回头聊一聊,条件表达式应该怎么具体操作:
1、将if段落提炼出来,构成一个独立函数。
2、将then和else段落提炼出来,各自构成一个独立函数。
好吧其实意思就是把if{代码1}then{代码2}else{代码3}中的代码1,代码2,代码3都最好搞成独立函数.而且看看if的条件是不是表达的很清晰,否则也搞成函数..
在牛人的关于提炼条件表达式的简洁中有下面的一句话
如果发现嵌套的条件逻辑,先观察是否可以使用Replace Nested Conditional with Guard Clauses (以卫语句取代嵌套条件表达式)。如果不行,才开始分解其中的每个条件。
针对这句话,在展开一个交流点
好吧,上面这句话中的什么叫做 嵌套的条件逻辑, 我承认我没弄明白. 不过没影响.这里要聊聊的是 以卫语句取代嵌套条件表达式 .还是看例子吧.有的时候文字看着晕乎,还不如直接看例子.再返回头看文字,就理解了..
一般而言条件表达式有两种形式
第一种:所有条件都是正常流程
例如:对人的身高的判断
if(中国人) ....
else if (美国人) ....
else if(欧洲人) .....
第二种:所有条件中只有一种正常形式,其他都是不常见或者异常的情况
例如: 对人的特征的判断
if(是人) ....
else if( 是动物) ... //异常
else if(是植物) .... //异常
对于第一种情况而言我们就要用正常的if then else
对于第二种情况而言就应该单独检查该条件,这种单独检查就被称为“卫语句”(guard clauses).意思是一个一个的用if拆开,而不要用if then else来搞了.. 看下面例子吧
例如:

解析来就进入主题,讲一讲 在代码开发中药避免复制和粘贴..看下一个篇幅吧
从文章"避免复制与粘贴"到文章"Extract Method"的反思(2)的更多相关文章
- 从文章"避免复制与粘贴"到文章"Extract Method"的反思(3)
在牛人的博客中提到了..如果你的代码可以copy-past的时候,那么久证明你的代码出现了重复.而这种重复仅仅是虚假的代码行的增加而不是像其他的代码复用那样降级成本. copy-pase代码意味着你违 ...
- 从文章"避免复制与粘贴"到文章"Extract Method"的反思(1)
看了一个比我牛的人的博客园的博文"避免复制和粘贴".里面提到了重构手法Extract Method. 所以又搜了一下Extract Method. 这里先自我理解Extract ...
- 如何在eclips下将一段代码抽取为方法Extract Method
最近读了读关于重构的文章,做了个小总结(在编程思想目录下<从文章"避免复制与粘贴"到文章"Extract Method"的反思 系列>). 然后因为 ...
- Laravel大型项目系列教程(四)显示文章列表和用户修改文章
小编心语:不知不觉已经第四部分了,非常感谢很多人给小编提的意见,改了很多bug,希望以后能继续帮小编找找茬~小编也不希望误导大家~这一节,主要讲的 是如何显示文章列表和让用户修改文章,小编预告一下(一 ...
- 用python+selenium登录cnblog后新增文章后再次删除该文章
目的:登录cnblog后新增文章后再次删除该文章并验证 代码如下: #coding: utf-8 from selenium import webdriver from time import sle ...
- dedecms文章页调用地址(当前文章URL)如何操作?
我们在建站时经常会在文末加一个本文地址,那么dedecms文章页如何调用当前文章URL呢?这样做的好处是增加文章的唯一标识,更进一步的做法是在head中加个cannacial标签,告诉搜索引擎url的 ...
- VS Extract Method
前言 看重构6.4Replace Temp with Query(以查询取代临时变量)中提到Replace Temp with Query往往是你运用Extract Method之前必不可少的一个步骤 ...
- 『重构--改善既有代码的设计』读书笔记----Extract Method
在编程中,比较忌讳的一件事情就是长函数.因为长函数代表了你这段代码不能很好的复用以及内部可能出现很多别的地方的重复代码,而且这段长函数内部的处理逻辑你也不能很好的看清楚.因此,今天重构第一个手法就是处 ...
- Refactoring #001 Extract Method
Example public void startup() { ServerSocket serverSocket = null; try { serverSocket = new ServerSoc ...
随机推荐
- php 生成mysql数据字典代码
由于项目开发用了比较多的表 ,为了快速获取数据字典,通过php代码的方式来获取表结构和表注释.代码如下: <?php /** * 生成mysql数据字典 */ header ( "Co ...
- 后台action处理数据传递给前台界面
package com.renmai.util; import java.io.IOException; import javax.servlet.http.HttpServletResponse; ...
- Jsp的内置标签和jstl标签
1.内置标签(动作标签) 内置标签不需要再jsp页面导入标签 1).forward:请求的转发,格式如下 <%-- 作用与这个相同 <%request.getRequestDispatch ...
- java +bootstrap table 完整例子
需求:现在常用的table 插件很多, 比如 jquey datatables ,不过操作挺 麻烦, 看到推荐的bootstrap 自带的 table,就用到项目来,先看效果:
- c#类的初始化顺序
本文转载:http://www.cnblogs.com/ybhcolin/archive/2010/09/24/1834219.html c#类的初始化顺序 类在初始化时的执行顺序,依次如下: 1: ...
- ACM 关于数据输入加速
转载请注明出处:http://blog.csdn.net/a1dark 分析:我们都知道运行时间对我们来说很重要.有时候不惜用大量的内存去换取一点时间.有些人可能都比较关注这个问题.首先时间上:cin ...
- NSURLSessionDownloadTask 断点下载
#import "ViewController.h" #import "ASIHTTPRequest.h" #import <AFNetworking/A ...
- 【转】copy 和 mutablecopy (深拷贝和浅拷贝)
阅读本文之前首先了解copy与retain的区别,如果有不正确的地方望大家多多指教: copy与retain的区别: copy是创建一个新对象,retain是创建一个指针,引用对象计数加1.Copy属 ...
- oracle授权另外一个用户访问自己创建的数据对象
oracle安装好之后,有一个默认的scott用户,该用户有一个默认的emp表,怎样让新创建的用户也能够访问这个表呢? 授权xiaoming这个用户访问emp表,但是xiaoming只有select权 ...
- Oracle 插入数据效率对比
oracle插入数据有多种方式: 将从多个表中查出来的数据插入到临时表中 数据行数 5189597 1.传统方式:直接将数据插入到表中 insert into LLB_BASIC_USER_D_TEM ...