在书中,作者还在感慨当时没有优秀的重构工具,大部分的重构工作都只能通过查找/替换来完成,幸亏有Unit的测试工具来保证质量,否则难度是不可想象的。
然而,我们现在非常幸运,在Eclipse中以及最新版本的Jbuilder中都具备了完美的重构功能,下面我们就一起来看看如何使用在Eclipse当中如何完成经典的程序重构工作。
首先,我们根据《重构》一书中的例子建立了一个名为“Refactoring”的包,在其中分别建立了名为“Movie”,“Rental”和“Customer”的类,并在其中键入最初的代码。
<!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> <v:stroke joinstyle="miter"/> <v:formulas> <v:f eqn="if lineDrawn pixelLineWidth 0"/> <v:f eqn="sum @0 1 0"/> <v:f eqn="sum 0 0 @1"/> <v:f eqn="prod @2 1 2"/> <v:f eqn="prod @3 21600 pixelWidth"/> <v:f eqn="prod @3 21600 pixelHeight"/> <v:f eqn="sum @0 0 1"/> <v:f eqn="prod @6 1 2"/> <v:f eqn="prod @7 21600 pixelWidth"/> <v:f eqn="sum @8 21600 0"/> <v:f eqn="prod @7 21600 pixelHeight"/> <v:f eqn="sum @10 21600 0"/> </v:formulas> <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/> <o:lock v:ext="edit" aspectratio="t"/> </v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" style='width:415.5pt; height:291.75pt'> <v:imagedata src="file:///D:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtml1\01\clip_image001.jpg" o:title="Snap1"/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
从上面的图中我们可以看到我们已经建立了初始的代码,下面就让我们一起使用Eclipse来对这个程序进行重构。
<!--[if !supportLists]-->(一) <!--[endif]-->分解并重组statement()
第一个需要重构的是statement()这个函数,里面的代码过长,非常不容易理解,我们首先要将其中的一部分抽取出一个方法,然后进行相关的处理。
选择整个switch语句,然后点击右键,在弹出的菜单中选择“Refactor->Extract Method”,如下图示。
<!--[if gte vml 1]><v:shape id="_x0000_i1038" type="#_x0000_t75" style='width:414.75pt;height:300pt'> <v:imagedata src="file:///D:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtml1\01\clip_image003.jpg" o:title="Snap3"/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
此时会弹出Extract Method的窗口,我们现在要建立的新方法的名字是amountFor,所以在“Method name”文本框中键入名字,在窗口的下面我们可以看到重构出来的方法的说明。
<!--[if gte vml 1]><v:shape id="_x0000_i1039" type="#_x0000_t75" style='width:366pt;height:337.5pt'> <v:imagedata src="file:///D:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtml1\01\clip_image005.jpg" o:title="Snap4"/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
如果点击“Preview”按钮,我们可以预览重构以后的代码,Eclipse非常形象的向我们展示了是如何将一个方法抽取出来的。点击“OK”按钮,Eclipse就会自动完成抽取的工作。
<!--[if gte vml 1]><v:shape id="_x0000_i1026" type="#_x0000_t75" style='width:415.5pt;height:357pt'> <v:imagedata src="file:///D:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtml1\01\clip_image006.jpg" o:title="Snap5"/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
此时方法中的参数thisAmount是我们不需要的,所以我们要修改对方法的声明。点击右键,在菜单中选择“refactor->Change Method Signature”。
<!--[if gte vml 1]><v:shape id="_x0000_i1027" type="#_x0000_t75" style='width:414.75pt;height:259.5pt'> <v:imagedata src="file:///D:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtml1\01\clip_image008.jpg" o:title="Snap6"/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
在弹出的对话框中我们可以看到当前对amountFor的定义,下面列举着当前的两个参数“thisAmount”和“each”,选择第一个参数,点击“Remove”按钮,就可以将其删除。
<!--[if gte vml 1]><v:shape id="_x0000_i1036" type="#_x0000_t75" style='width:366pt;height:310.5pt'> <v:imagedata src="file:///D:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtml1\01\clip_image010.jpg" o:title="Snap7"/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
但是现在直接删除掉这个参数会出现错误,Eclipse自动弹出了对话框,提示用户。
<!--[if gte vml 1]><v:shape id="_x0000_i1037" type="#_x0000_t75" style='width:414.75pt;height:325.5pt'> <v:imagedata src="file:///D:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtml1\01\clip_image011.jpg" o:title="Snap15"/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
我们确认要删除这个参数,所以点击“Continue”按钮继续修改。
Eclipse会自动检测出错误,并在有问题的语句下面用红色的波浪线标记出来,
<!--[if gte vml 1]><v:shape id="_x0000_i1028" type="#_x0000_t75" style='width:414.75pt;height:373.5pt'> <v:imagedata src="file:///D:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtml1\01\clip_image013.jpg" o:title="Snap16"/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
之所以提示这样的错误,是因为这个变量在方法中还没有定义,修改错误我们同样可以利用Eclipse提供的功能快速的完成。
将光标定位在thisAmount上,然后按下“ctrl-1”,Eclipse会自动弹出修改建议,在这里我们选择“创建本地变量thisAmount”,这样Eclipse就会自动为我们定义这个变量。
<!--[if gte vml 1]><v:shape id="_x0000_i1029" type="#_x0000_t75" style='width:414.75pt;height:373.5pt'> <v:imagedata src="file:///D:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtml1\01\clip_image015.jpg" o:title="Snap17"/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
但是这个时候我们依然会看到thisAmount下面有红色的波浪线,因为我们的这个变量在定义了之后还没有初始化,再次在thisAmount下面按下“Ctrl-1”,在弹出的菜单中选择“初始化变量”,这时Eclipse就会为我们自动初始化这个变量。
我们看到,我们并没有键入一个字母,只不过按了几个键,然后在菜单中进行了相关的选择,我们就已经完成了好多处理,这样不仅提高了我们编码的效率,而且避免了一些低级错误的出现。
<!--[if gte vml 1]><v:shape id="_x0000_i1030" type="#_x0000_t75" style='width:414.75pt;height:373.5pt'> <v:imagedata src="file:///D:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtml1\01\clip_image017.jpg" o:title="Snap18"/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
然后,我们发现thisAmount的类型有些问题,我们要返回的是一个Double型的数据,而系统自动定义的是一个整型的,这会在处理的时候进行自动取整的操作。所以我们需要将thisAmount的类型改变一下。
<!--[if gte vml 1]><v:shape id="_x0000_i1031" type="#_x0000_t75" style='width:414.75pt;height:373.5pt'> <v:imagedata src="file:///D:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtml1\01\clip_image019.jpg" o:title="Snap19"/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
接下来,我们发现当前我们使用的变量的名字不是很好,因为没有明确的意义。《重构》书中有这样的一句话“能编写出能够让人看懂的程序的程序员才是真正优秀的程序员”,因此我们需要再次进行重构的操作——改变变量的名字。
选择thisAmount变量,然后点击右键,在弹出的环境菜单中选择“Refactor->Rename”,将这个变量改名。
<!--[if gte vml 1]><v:shape id="_x0000_i1032" type="#_x0000_t75" style='width:414.75pt;height:373.5pt'> <v:imagedata src="file:///D:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtml1\01\clip_image021.jpg" o:title="Snap20"/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
弹出的改名的对话框非常简单,上面显示出当前的名字,接下来我们要改变这个名字。
<!--[if gte vml 1]><v:shape id="_x0000_i1033" type="#_x0000_t75" style='width:366pt;height:145.5pt'> <v:imagedata src="file:///D:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtml1\01\clip_image023.jpg" o:title="Snap21"/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
在文本框中键入我们的新名字,“Result”,点击“OK”按钮,系统就会自动在整个程序中查找与thisAmount这个变量相关的内容并将其替换。
<!--[if gte vml 1]><v:shape id="_x0000_i1034" type="#_x0000_t75" style='width:366pt;height:145.5pt'> <v:imagedata src="file:///D:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtml1\01\clip_image024.jpg" o:title="Snap22"/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
采用同样的方法,我们对each这个变量重命名为aRental,这样的意义更加明确。更改完毕的代码如下图示,这样我们就完成了第一个重构的步骤。
<!--[if gte vml 1]><v:shape id="_x0000_i1035" type="#_x0000_t75" style='width:414.75pt;height:373.5pt'> <v:imagedata src="file:///D:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtml1\01\clip_image025.jpg" o:title="Snap23"/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
过去重构工作多靠查找/替换,如今Eclipse和Jbuilder具备完美重构功能。本文以《重构》为例建立代码,详细介绍在Eclipse中对程序进行重构的过程,包括分解并重组statement函数、抽取方法、修改方法声明、处理变量错误、改变变量类型和名称等操作,提高编码效率。
1070

被折叠的 条评论
为什么被折叠?



