从文章"避免复制与粘贴"到文章"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 ...
随机推荐
- js修改编辑器内容、修改iframe子页内容
$('#question-stem-uploader').on('click','',function(){ //获取编辑器内容(ke-edit-iframe: 编辑器iframe的classm名称) ...
- Datediff函数 助你实现不同进制时间之间的运算
在VB开发环境中实现时间之间的加减运算有很多种方法,前不久自己无意中发现了Datediff函数,它能够比较简单.全面地实现我们比较常用的时间之间的运算,今由自己的研究,搞清了它的一些用法,拿来和大家分 ...
- tomcat install on Linux
1)下载apache-tomcat-6.0.10.tar.gz 2)#tar -zxvf apache-tomcat-6.0.10.tar.gz ://解压 3)#cp -R apache-tomca ...
- git与svn的区别-小结一下
1)Git是分布式的,SVN不是: 这 是GIT和其它非分布式的版本控制系 统,例如SVN,CVS等,最核心的区别.好处是跟其他同事不会有太多的冲突,自己写的代码放在自己电脑上,一段时间后再提交.合并 ...
- C++中this指针的使用方法.
this指针仅仅能在一个类的成员函数中调用,它表示当前对象的地址.以下是一个样例: void Date::setMonth( int mn ) { month = mn; // 这三句是等价的 thi ...
- John(博弈)
Description Little John is playing very funny game with his younger brother. There is one big box ...
- GCC 编绎选项 转
gcc提供了大量的警告选项,对代码中可能存在的问题提出警告,通常可以使用-Wall来开启以下警告: -Waddress -Warray-bounds (only with -O2) ...
- vmware9.0 安装ios10.8应该注意的地方
今天终于在我的thinkpad t400上面按照好了ios系统 我的硬件配置:cpu:p8700,内存:ddr3,6g 安装的版本:ios10.8 vmware的版本是vmware9.0 安装好的io ...
- Freemarker学习中遇到的问题
在网上找到了尚学堂的视频,同时有书和源码等资料.但是在跟着练习的过程中,代码运行报了错: 2015-7-20 22:26:40 freemarker.log.JDK14LoggerFactory$JD ...
- 加密算法 DES 3DES RSA AES 简介
数据加密的基本过程就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码,通常称为[密文],使其只能在输入相应的[密钥]之后才能显示出本来内容,通过这样的途径来达到保护数据不被非法人 ...