⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 refactormercilessly.html

📁 极限编程 Extream Programing
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<head><title>Refactor Mercilessly</title></head><body><h1><img src="logo.gif"> Refactor Mercilessly</h1><a href="http://c2.com/cgi/wiki?RefactoringImprovingTheDesignOfExistingCode">RefactoringImprovingTheDesignOfExistingCode</a>
<p>One of the <a href="ExtremeProgramming.html">ExtremeProgramming</a> practices is to <a href="RefactorMercilessly.html">RefactorMercilessly</a>.  When you find two methods that look the same, you refactor the code to combine them.  When you find two objects with common functionality, you refactor to make there be just one. Extreme projects do not use <a href="BigDesignUpFront.html">BigDesignUpFront</a>. Therefore they upgrade their designs continuously. <a href="http://c2.com/cgi/wiki?RelentlessTesting">RelentlessTesting</a> and <a href="ContinuousIntegration.html">ContinuousIntegration</a> (<a href="UnitTests.html">UnitTests</a> synchronized with changes disseminated to other engineers) permit changes that would introduce the risk of bugs in slower projects.
<p>And you change all the users of the old capability to use the new.  In Smalltalk, that's particularly easy to do, because you can open a browser on all the senders of the old one and edit them to the new.  (There may be <a href="http://c2.com/cgi/wiki?CodeOwnership">CodeOwnership</a> issues, of course.)
<p>Since we have extensive <a href="UnitTests.html">UnitTests</a> and <a href="FunctionalTests.html">FunctionalTests</a>, we can always refactor with the confidence that we haven't broken anything.
<p>The result of these practices is that the system does not get held hostage by some old, hide-bound, ill-conceived idea from the past.  It remains fresh and new, productive and fun to work with.
<p>Since we <a href="DoTheSimplestThingThatCouldPossiblyWork.html">DoTheSimplestThingThatCouldPossiblyWork</a>, sometimes what we do needs improvement an iteration or so down the line.  We welcome these opportunities to make the system more like what it should be, and we welcome the fact that we do it in solid knowledge of what is <em>really</em> needed, not what we imagined in the past was needed.
<p>The result of this is that the system is always as simple as we can make it, which means we can understand it better, which means we can change it more rapidly while keeping it reliable.
<p>Try it, you'll like it ...
<p>--<a href="RonJeffries.html">RonJeffries</a>
<p>Please can someone show a substantial code example. See <a href="http://c2.com/cgi/wiki?PleaForXpCodeExample">PleaForXpCodeExample</a>.
<hr>
<p>Is <a href="RefactorMercilessly.html">RefactorMercilessly</a> supposed to be so mercyless to refactor across the boundaries of multiple projects and shared libraries? -- <a href="http://c2.com/cgi/wiki?HelmutLeitner">HelmutLeitner</a>
<p><em>That depends on code ownership issues.  You cannot refactor it if you don't own it.  On the other hand, why not refactor a shared library, the functionality and API shouldn't change.</em>
<p>This would mean to refactor within a single project. I asked for &quot;across the boundaries&quot; in a &quot;multiple project, multiple library&quot; situation where APIs need to be improved. <a href="http://c2.com/cgi/wiki?CollectiveCodeOwnership">CollectiveCodeOwnership</a> for all projects and libraries is assumed. Is this attempted? What is it to attempt this in Smalltalk? Do the refactoring tools still help?
<hr>
If you have refactoring tools for this, they help of course.
The prerequisite is that libraries and other projects are written in the same programming language (and that language is available in the tool).
<p>If the library used created by an open source project (REAL open source, not Apple's &quot;you may do nothing useful but read and only until we cancel the agreement&quot; - License), this is where some of the power of open source comes from: Developers that need something from a library can jump in and code it.
<p>There are also drawbacks: When a large refactoring is done, often a consensus has to be reached before a &quot;patch&quot; is included in the library, and patched that have been forgotten because they aren't &quot;sexy&quot; fall out of date.
Summary: Open Source has good potential for cross-project refactoring, but can use it only if it patches are quickly judged and integrated.
--<a href="http://c2.com/cgi/wiki?PeterSchaefer">PeterSchaefer</a>
<p><hr>
<p>&quot;<a href="http://c2.com/cgi/wiki?WaterFall">WaterFall</a>&quot; theory says only &quot;Analysis&quot; can identify the elements of a program most depended-on by others, and these must be designed and coded first, before their clients are coded.
<p><a href="RefactorMercilessly.html">RefactorMercilessly</a> says the longer your program has been committed into real source code and demonstrated performing features, the more you know about how to improve &amp; upgrade its internal structure.
<p>I'm sold.
<p>--<a href="http://c2.com/cgi/wiki?PhlIp">PhlIp</a>
<p><hr>
<p>This ain't near the bottom of the page, so only 'last edited' afficionados will get to read it.  Responding to Phil, above...
<p>Where can I read about &quot;<a href="http://c2.com/cgi/wiki?WaterFall">WaterFall</a> theory&quot;?  On these pages, <a href="http://c2.com/cgi/wiki?WaterFall">WaterFall</a> is like the Mc<strong></strong>Carthyist Communism of the 1950's -- an AcceptableThingToFear<a href="http://c2.com/cgi/wiki?edit=AcceptableThingToFear">?</a> (parody on AcceptableWayOfFailing<a href="http://c2.com/cgi/wiki?edit=AcceptableWayOfFailing">?</a>).
<p><em>I (<a href="http://c2.com/cgi/wiki?PhlIp">PhlIp</a>) am just relating my experiences reading <a href="http://c2.com/cgi/wiki?JobSecurity">JobSecurity</a>-style code. AFAIK <a href="http://c2.com/cgi/wiki?WaterFall">WaterFall</a> theory does _not_ say you write the most-depended on classes first. But that's the way everyone in <a href="http://c2.com/cgi/wiki?RealLife">RealLife</a> does it.</em>
<p>I don't know what &quot;<a href="http://c2.com/cgi/wiki?WaterFall">WaterFall</a> theory&quot; says, but Phil is right on target with the insight about the connection between analysis and refactoring (see comments toward the end of <a href="http://c2.com/cgi/wiki?WhatIsAnalysis">WhatIsAnalysis</a> and <a href="http://c2.com/cgi/wiki?AnalysisIsRefactoring">AnalysisIsRefactoring</a>).  When you are refactoring, you are analyzing.  The right time to do it cannot come from some process manual or methodology -- it's when you see an opportunity to express something more powerfully and simply.  The project phase and the medium are unimportant.  The people, their skills, and the project context are important.  And it's far more important to do it when you can than to quibble about the ideal time to do it.
<p>I fancy I'm following my own advice here, by pointing out the commonality between code refactoring and other forms of analysis.  <em>This is the essence of systems development, no matter what name you give it.</em>
<p>I guess the term &quot;analysis&quot; has some stigma associated with it (by hanging out with &quot;<a href="http://c2.com/cgi/wiki?WaterFall">WaterFall</a>&quot;, no doubt).  I've noticed that to some people, analysis is always <a href="http://c2.com/cgi/wiki?AnalysisParalysis">AnalysisParalysis</a>.  Maybe I'm just an old fashioned analyst, but I still like the word &quot;analysis&quot; and its semantic roots.  Therefore, I propose a new base class to the <a href="RefactorMercilessly.html">RefactorMercilessly</a> class: <a href="http://c2.com/cgi/wiki?AnalyzeMercilessly">AnalyzeMercilessly</a>.  <em>Do it everywhere, not just in code.</em>
--<a href="http://c2.com/cgi/wiki?WaldenMathews">WaldenMathews</a>
<p><hr>
<em>See <a href="http://c2.com/cgi/wiki?RefactoringWithCplusplus">RefactoringWithCplusplus</a> for issues and tips for XP with C/C++</em> --<a href="http://c2.com/cgi/wiki?DouglasAuclair">DouglasAuclair</a>
<hr>
On <a href="http://c2.com/cgi/wiki?SpecializationIsForInsects">SpecializationIsForInsects</a>, <a href="RonJeffries.html">RonJeffries</a> said the following about <a href="http://c2.com/cgi/wiki?ChryslerComprehensiveCompensation">ChryslerComprehensiveCompensation</a>: <em>&quot;It's no phone system, but it is complex (1800 classes, 25000 methods), and the ordinary folks who wrote it actually understand it!&quot;</em>
<p>It would be neat to see a frequency histogram of classes with given numbers of methods.  That is, number of classes with one method, number of classes with two methods...  The average of your numbers is ~13.9 methods per class.  
<p>I'd just guess that you could tell a good amount from a histogram.  I'd expect that in well-factored systems, it would have a single peak that would rise gradually and then fall off quicker.  If there are some outliers far out to the right, you could have some <a href="http://c2.com/cgi/wiki?GodObject">GodObject</a>-s.  If there are multiple large distinguished peaks, that could indicate a multitude of things: inconsistent refactoring, architectural decisions that have produced categories of classes, or a fractured team.  On the other hand, there probably isn't enough spread to see more than the most grievous cases.
<p>-- <a href="http://c2.com/cgi/wiki?MichaelFeathers">MichaelFeathers</a>
<p><hr>
<p><p>Fair enough. One problem that I have with <a href="RefactorMercilessly.html">RefactorMercilessly</a>, though, is that it seems to conflate intensional with extensional. Compare the following two statements:
<p>A:<em>These two classes implement the same piece of code (contain a similar method, whatever), and it's an essential similarity.</em> 
<p>B:<em>These two classes implement the same piece of code (contain a similar method, whatever), but it's pretty much coincidence.</em> 
<p>Now in the first case, it's clear the refactoring should take place on the classes to exploit (expose ?) the essential similarity. But in the second 
case ? You could claim that this indicates a need to refactor somewhere
else (for example: if more than one client of a server is performing the 
same sequence of operations, then maybe the server should support that 
sequence with a single method call).
<p>But I dunno. In general, especially when the code is evolving, I'm inclined 
to cut the second case a little slack. Let the functionality hang for 
a while and see if the code evolves along different paths as more functionality
is added to the system.
<p>Related notion: Anyone care to comment on the following quicktime movie 
<a href="http://www.isi.edu/isd/LOOM/loom-classifier.mov">http://www.isi.edu/isd/LOOM/loom-classifier.mov</a>
<p><a href="http://c2.com/cgi/wiki?WilliamGrosso">WilliamGrosso</a>
<p>&quot;it's pretty much coincidence&quot; - When I think this, generally it is because I don't understand. Often moving responsibility to a shared server fixes the problem. Or I have something to learn about what is similar and what is different. In any case, I don't stress about it. If the code is talking, I'd better be listening. Damned arrogant of me to think I know better. --<a href="KentBeck.html">KentBeck</a>
<p>What's the cost of getting it wrong and combining methods that &quot;should&quot; be separate? Ideally, it would just mean undoing the refactoring later on when the methods diverge. This second refactoring should be cheap, and its cost offset by the benefit of having the simpler system (with one less method) in the meantime. So you win overall by merging the methods.
<p>In a worse case you make a change to the merged method that only one use needs, and that screws up the second use. You get a side effect, and a bug in some other part of the system that you weren't working on. This risk is offset by <a href="UnitTests.html">UnitTests</a> and the like. They detect the bug straight away because they test remote parts of the system automatically, without you thinking about it. So you can pin it down to the change you just made, and figure out that you need to split the method. So this isn't something to fear, as long as you have <a href="http://c2.com/cgi/wiki?TheFullMonty">TheFullMonty</a> XP. -- <a href="http://c2.com/cgi/wiki?DaveHarris">DaveHarris</a>
<p>The crucial question is whether the second refactoring is actually cheap. If the method is called in a dozen places, you have to check each one to see which version of the method it should be calling. This requires a bit of brain-power; you need to understand what those other methods are doing. One approach might be to preserve the difference even while performing the merge. For example, leave the second method there but have it forward to the first method. Or have two factory methods that both return the same class. This would be less Extreme, but better than having two copies of the code. -- <a href="http://c2.com/cgi/wiki?DaveHarris">DaveHarris</a>
<p>The forwarding solution doesn't bother me, if I have two different things to say. It was such a revelation to me the day I understood the value of 
<p>highlight: aRectangle
<PRE>	self reverse: aRectangle
<p></PRE>OTOH, if you really can't tell the difference, squish them together and have the faith that the system will tell you different when it knows different.
--<a href="KentBeck.html">KentBeck</a>
<p>See Also: <a href="http://c2.com/cgi/wiki?CostOfRefactorCarry">CostOfRefactorCarry</a>
<p>Anyone else consider that <a href="http://c2.com/cgi/wiki?WilliamGrosso">WilliamGrosso</a> could have refactored to :
<p>These two classes implement the same piece of code (contain a similar method, whatever), -
<p>A:<em>and it's an essential similarity.</em> 
<p>B:<em>but it's pretty much coincidence.</em> 
<p>or am I just being tedious?!
<p><p>I think that's OK. The coincidental refactoring comes when you now see the common &quot;it's&quot; in those 2 choices and attempt to refactor further.
<p><PRE>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -