📄 lib0130.html
字号:
<html>
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<head>
<title>Common Refactoring Techniques</title>
<link rel="STYLESHEET" type="text/css" href="images/xpolecat.css">
<link rel="STYLESHEET" type="text/css" href="images/ie.content.css">
</head>
<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/teamlib.gif" width="62" height="15" border="0" align="absmiddle" alt="Team LiB"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href="LiB0129.html"><img src="images/previous.gif" width="62" height="15" border="0" align="absmiddle" alt="Previous Section"></a>
<a href="LiB0131.html"><img src="images/next.gif" width="41" height="15" border="0" align="absmiddle" alt="Next Section"></a>
</div></td></tr></table>
<br>
<div class="chapter">
<a name="ch20"></a>
<div class="section">
<h2 class="first-section-title"><a name="639"></a><a name="ch20lev1sec4"></a>Common Refactoring Techniques</h2><p class="first-para">Refactory has been the topic of entire books, within which are dozens of refactoring techniques. Here I concentrate on the most commonly used techniques. Readers interested in delving deeper into the topic should see <a href="LiB0131.html#653" target="_parent" class="chapterjump">Fowler (2000)</a> and <a href="LiB0131.html#652" target="_parent" class="chapterjump">Alur et al. (2003)</a>.</p>
<div class="section">
<h3 class="sect3-title">
<a name="640"></a><a name="ch20lev2sec1"></a>Extract and Delegate</h3>
<p class="first-para">Common code identified in multiple classes calls for the extract-and-delegate method of refactoring. The common code is extracted and placed in a <a name="641"></a><a name="IDX-268"></a>separate class. The new class then serves as a delegate and is called within any class needing it. Many of the static utilities in CementJ were created because common code existed in many classes and needed to be centralized.</p>
<p class="para">For example, it is common for JDBC-related classes to close <span class="fixed">ResultSets</span>, <span class="fixed">Statements</span>, and <span class="fixed">PreparedStatements</span> in a finally block. Unfortunately, closing one of these objects can throw an <span class="fixed">SQLException</span>, which is a checked exception. As shown in lines 9 through 18 of <a class="internaljump" href="#ch20list01">listing 20.1</a>, this causes nested try/catch logic in the finally block, which is usually identical everywhere.</p>
<div class="example">
<span class="example-title"><span class="example-titlelabel">Listing 20.1: </span>Sample Candidate for the Extract-and-Delegate Method of Refactoring</span><a name="642"></a><a name="ch20list01"></a>
<div class="formalbody">
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="Start example" border="0"></b></font></td>
</tr>
</table>
<pre class="literallayout">
1:PreparedStatement pStmt = null;
2:try
3:{
4: pStmt = connection.prepareStatement(sqlText);
5: // JDBC Code here
6:}
7:finally
8:{
9: if (pStmt != null)
10: {
11: try {pStmt.close()}
12: catch (SQLException q)
13: {
14: Logger.logWarning(
15: "Error closing PreparedStatement",
16: q)
17: }
18: }
19:}
</pre>
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="End example" border="0"></b></font></td>
</tr>
</table>
<table class="BlankSpace" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td height="16"></td>
</tr>
</table>
</div>
</div>
<p class="para">Although the nested try/catch isn't complicated, it's verbose and makes JDBC code harder to read. <a class="internaljump" href="#ch20list02">Listing 20.2</a> illustrates how extracting that code into a separate utility class shortens the code quite a bit.</p>
<div class="example">
<span class="example-title"><span class="example-titlelabel">Listing 20.2: </span>Using the Extract-and-Delegate Technique (Refactoring of Listing 20.1)</span><a name="643"></a><a name="ch20list02"></a>
<div class="formalbody">
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="Start example" border="0"></b></font></td>
</tr>
</table>
<pre class="literallayout">
1:PreparedStatement pStmt = null;
2:try
3:{
4: pStmt = connection.prepareStatement(sqlText);
5: // JDBC Code here
6:}
7:finally<a name="644"></a><a name="IDX-269"></a>
8:{
9: DatabaseUtility.close(pStmt);
10:}
</pre>
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="End example" border="0"></b></font></td>
</tr>
</table>
<table class="BlankSpace" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td height="16"></td>
</tr>
</table>
</div>
</div>
<p class="para">One argument I usually get from the copy-and-paste advocates is that the central utility created by the extract-and-delegate technique is more complex than the original. This can be true, but the result is much less code to maintain. Further, a central utility is usually the most tested because it's used most often. In <a class="internaljump" href="#ch20list02">listing 20.2</a>, for example, the source for the utility method isn't much more complex than the original. <a class="internaljump" href="#ch20list03">Listing 20.3</a> provides the source for <span class="fixed">DatabaseUtility.close()</span>.</p>
<div class="example">
<span class="example-title"><span class="example-titlelabel">Listing 20.3: </span>DatabaseUtility Source Extract</span><a name="645"></a><a name="ch20list03"></a>
<div class="formalbody">
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="Start example" border="0"></b></font></td>
</tr>
</table>
<pre class="literallayout">
1: public static void close(PreparedStatement pStmt)
2: {
3: if (pStmt == null) return;
4: try {pStmt.close();}
5: catch (SQLException e)
6: {
7: LogManager.getLogger().logWarning(
8: "Prepared statement close error", e);
9: }
10: }
</pre>
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="End example" border="0"></b></font></td>
</tr>
</table>
<table class="BlankSpace" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td height="16"></td>
</tr>
</table>
</div>
</div>
<p class="last-para">Common code isn't always a static utility but comprises common characteristics shared among multiple classes. To centralize this code, you would use the extract-and-extend technique.</p>
</div>
<div class="section">
<h3 class="sect3-title">
<a name="646"></a><a name="ch20lev2sec2"></a>Extract and Extend</h3>
<p class="first-para">This refactoring technique is used when classes share the same characteristics and methods. Ideally, you will identify such classes in design, but sometimes the commonality becomes apparent only after construction. <span class="fixed">ValueObject</span> from CementJ is a good example of applying the extract-and- extend technique. In fact, I created <span class="fixed">ValueObject</span> after noticing a lot of common code with value object classes for one of my applications.</p>
<p class="para">Often value object classes need functions such as producing a textual description of themselves or implementing <span class="fixed">hashcode()</span> and <span class="fixed">equals()</span> so they can be effectively used in hash constructs. <span class="fixed">ValueObject</span> makes these kinds of functions common so they do not have to be coded in multiple value object classes individually. To benefit from <span class="fixed">ValueObject</span>, all you need do is extend it. <span class="fixed">ValueObject</span> is covered extensively in <a href="LiB0067.html#300" target="_parent" class="chapterjump">chapter 10</a>.</p>
<a name="647"></a><a name="IDX-270"></a>
<p class="last-para">A combination of the extract-and-delegate and extract-and-extend techniques is also commonly used.</p>
</div>
<div class="section">
<h3 class="sect3-title">
<a name="648"></a><a name="ch20lev2sec3"></a>Extract and Decouple with Interface</h3>
<p class="first-para">You use this refactoring technique when classes in your application have the same function but do not have common code. This technique is a combination of the two techniques previously described.</p>
<p class="para">One example can be drawn from ProjectTrak and its ability to use multiple scheduling algorithms. As discussed in <a href="LiB0089.html#429" target="_parent" class="chapterjump">chapter 13</a>, ProjectTrak users can specify the algorithm used to produce a project schedule to facilitate testing and refinement of the scheduling feature. Some of these algorithms may have common characteristics and share common code, but others may not. Not all scheduling algorithms can usefully extend <span class="fixed">AbstractAlgorithm</span>. By decoupling with the interface <span class="fixed">Scheduler</span> as illustrated in <a class="internaljump" href="#ch20fig01">figure 20.1</a>, the user can implement any algorithm without adversely affecting other parts of the application.</p>
<div class="figure">
<a name="649"></a><a name="ch20fig01"></a><span class="figuremediaobject"><a href="images/fig287%5F01%5F0%2Ejpg" NAME="IMG_46" target="_parent"><img src="images/fig287_01.jpg" height="253" width="350" alt="Click To expand" border="0"></a></span>
<br style="line-height: 1">
<span class="figure-title"><span class="figure-titlelabel">Figure 20.1: </span>Sample Interface Decoupling</span>
</div>
</div>
</div>
</div><br>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/teamlib.gif" width="62" height="15" border="0" align="absmiddle" alt="Team LiB"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href="LiB0129.html"><img src="images/previous.gif" width="62" height="15" border="0" align="absmiddle" alt="Previous Section"></a>
<a href="LiB0131.html"><img src="images/next.gif" width="41" height="15" border="0" align="absmiddle" alt="Next Section"></a>
</div></td></tr></table>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -