refactormercilessly.html
来自「极限编程 Extream Programing」· HTML 代码 · 共 266 行 · 第 1/2 页
HTML
266 行
Base = "These two classes implement the same piece of code (contain a similar method, whatever), -
[name]: [join] it's [clause]."
A:Base = {join="and" clause="an essential similarity"}
B:Base = {join="but" clause="pretty much coincidence"}
<p></PRE>--<a href="http://c2.com/cgi/wiki?DaveWhipp">DaveWhipp</a>
<hr>
<p>William: please offer one example of coincidental implementation of the same piece of code that seems to you not to suggest refactoring. Thanks. --<a href="RonJeffries.html">RonJeffries</a>
<p>Suppose I've got two classes, each with one instance variable, and each class has an "initialize" method that sets the variable to zero. If I renamed one of the variables to be same as the other, I could give them a common superclass and just implement "initialize" once.
<p>In practice, humans don't have much problem with these false positives. Although I'm sure someone made that refactoring at some time or other, most developers are smart enough to know better. Automated refactoring tools are not, however. This is one of the reasons that I think that tools should
always be under the direction of humans, and not decide whether or not to
perform a refactoring. --<a href="http://c2.com/cgi/wiki?RalphJohnson">RalphJohnson</a>
<p><hr>
<p>I like Ralph's example a lot. It makes me think, a good trick in itself. I was thinking of duplications with just a <em>bit</em> more processing, such as maybe
<p><PRE> 1 to: array size do: [ :index | array at: index put: zero ]
<p></PRE>which might lead one to wonder whether collections should have a method named, e.g. #atAllPut: or #zeroize. No conclusion yet, except that I think the human should look at duplications carefully to see whether they are saying something important about the program. A good tool like [Small]lint can help by discovering candidates for consideration. --<a href="RonJeffries.html">RonJeffries</a>
<p><hr>
<p>If you've got two classes, each with one instance variable, and you find out that the one and only instance variable plays exactly the same role in both of those classes and thus needs to be named the same, you might want to look at merging more than just that initialize method. --<a href="DonWells.html">DonWells</a>
<p><hr>
<p>Okay, here's the thing I've been trying to figure out about how to
<a href="RefactorMercilessly.html">RefactorMercilessly</a>: Suppose in the code I want to refactor I have a
class A with a method x. If x is part of the public interface of A. Or
perhaps a better example would be if it's semi-public, meaning it's
not going to be used by normal client programmers but it is used by
other classes in *my* code. At any rate, I probably have a <a href="http://c2.com/cgi/wiki?UnitTest">UnitTest</a>
that calls x and makes sure it behaves properly. Now I'm refactoring
and I decide that x's behavior needs to change or maybe the behavior
stays the same but it really belongs in some other class. So I fire up
my browser (or wish I had one in Java and do it the hard way) and find
all the callers and fix them. But the only way I can make the test
work is to change the test itself. But now it seems there's a hole in
the safety net that my <a href="http://c2.com/cgi/wiki?UnitTest">UnitTest</a> was giving me--since both the code and
the test changed I could have broken the code and also broken the test
so it's not really equivalent to the old test. Voila, I've got a
regression. I realize that some (maybe most) refactorings will leave
the surface API the same so the tests don't change but are there
strategies for dealing with this harder case? --<a href="http://c2.com/cgi/wiki?PeterSeibel">PeterSeibel</a>
<p><hr>
<p>Perhaps "this harder case" is largely illusory. For the problem described to occur, it would be necessary to inject a defect in the refactoring (which isn't impossible, but if it's really a refactoring, it's difficult), and then inject a corresponding but exactly opposite defect in the test. Flaws in a <a href="http://c2.com/cgi/wiki?UnitTest">UnitTest</a> generally produce false positives, indications of errors that aren't, not false negatives. There are exceptions ... but they're rare enough that I'd not worry about it. --<a href="RonJeffries.html">RonJeffries</a>
<p>Hmm.. I'm not sure about this assertion. I guess it depends how you code your unit tests. I'll admit up front that I don't use any of the UT frameworks discussed here, but I have found the occasional false-negative due to cut-and-paste errors :- a test may accidentally end up just a copy of a similar test; or expression-bracketing issues which don't actually execute the real
code. <a href="PairProgramming.html">PairProgramming</a> would help to overcome this, but it's hard for me at home on my own. I do worry that I'm missing the point sometimes, though, as I seem to need to refactor the unit tests every time I refactor the main code. --<a href="http://c2.com/cgi/wiki?FrankCarver">FrankCarver</a>
<p>Refactoring is changing implementation without changing interface. It should be rare for <a href="UnitTests.html">UnitTests</a> to need changing under refactoring. Perhaps you are changing interface, not refactoring? In that case, yes, the <a href="UnitTests.html">UnitTests</a> will have to change, just as they do when you add or remove functionality. It's the price of knowing that your changes work. False negatives are OK, they point themselves out, you look at them and fix them. False positives are bad, but they're rare by the above argument. --<a href="RonJeffries.html">RonJeffries</a>
<p>Refactoring must surely encompass changing interface sometimes....
<p>Looking at <a href="http://c2.com/cgi/wiki?MartinFowler">MartinFowler</a>'s page
[ <a href="http://www2.awl.com/cseng/titles/0-201-89542-0/refactor/index.html">http://www2.awl.com/cseng/titles/0-201-89542-0/refactor/index.html</a> ]
<p>I can see a few "refactorings" that involve moving methods or changing classes and adjusting all references....
<p>Is his book incorrectly named ? :-)
<p>--<a href="http://c2.com/cgi/wiki?AlanFrancis">AlanFrancis</a>
<p><em>Not necessarily - moving methods doesn't change (system) functionality. Of course it changes the functionality of one class, but not of the cluster of classes involved in the refactoring. -<a href="RonJeffries.html">RonJeffries</a></em>
<p>Yes, from what I understood from the book refactoring is about changing the implementation without changing the functionality. <a href="RonJeffries.html">RonJeffries</a> comment raises issues about which parts of your system are interfaces. Since SubSystem<a href="http://c2.com/cgi/wiki?edit=SubSystem">?</a> or ComponentModelling<a href="http://c2.com/cgi/wiki?edit=ComponentModelling">?</a> don't form a part of XP there is no level of interface higher than the interface to a class.
<p>One question I have with <a href="RefactorMercilessly.html">RefactorMercilessly</a> is how to make sure people are refactoring. Some people I've worked with the past can barely manage to get there systems functioning at all never mind making them well factored.
<p>--<a href="http://c2.com/cgi/wiki?GlenStampoultzis">GlenStampoultzis</a>
<p><em>Are you saying you can't trust your team to do what they have agreed to do? What does this tell you about the place where you are? --rj</em>
<p>(Sorry, Ron, I have only most rarely seen people do what they agreed to do. Most people "agree" out loud because it is expected and less tiring than disagreeing. But that doesn't mean they agree inside, and even if they agree inside, it still doesn't mean they'll have the energy to follow through the next day or two weeks later. So on most projects, Glen's question is meaningful --<a href="http://c2.com/cgi/wiki?AlistairCockburn">AlistairCockburn</a>)
<p>I'm saying that I've worked in a number of different environments and that the quality level of varies significantly. Many people I know I would have complete confidence in but there are also plenty of people out there who write complete spagetti and get away with it. Luckily the people I'm working with at the moment are quite competent and conscientious but I expect it wont be the last time I come across programmers from hell.
<p>Let me rephrase my question: How do you encourage people to <a href="RefactorMercilessly.html">RefactorMercilessly</a>?
<p>--<a href="http://c2.com/cgi/wiki?GlenStampoultzis">GlenStampoultzis</a>
<p>It's one of the team practices. They have promised to follow the practices. If they don't, we get to kill them. Makes a good example for the others.
<p>I've never once worked with programmers who were not conscientious, and who did not want to do the right thing. If somehow I fell in with a batch of such people, and they didn't instantly convert to giving a ****, I'd desert them. --rj
<p>I think you have to do some <a href="PairProgramming.html">PairProgramming</a> with them, refactor something, and let them see that it is not so difficult, doesn't break the system, and they feel better afterwards. For a group who don't <a href="RefactorMercilessly.html">RefactorMercilessly</a>, I would expect each person would need at least three such sessions to get the feeling. I don't think ordering someone to do something they don't understand is effective. --<a href="http://c2.com/cgi/wiki?AlistairCockburn">AlistairCockburn</a>
<p>People who are trying to do good are just fine and you can work with them. I refer above specifically to a group who are not conscientious and do not care whether they do the right thing. I don't think such people are thick on the ground. If I found a bunch, I wouldn't want to be there. --rj
<p>I suspect that Ron is just trying to make a point. I know Ron and I can not imagine him just abandoning a project. He has the tenacity of a bulldog. --<a href="DonWells.html">DonWells</a>
<p><a href="http://c2.com/cgi/wiki?XpIsNotaSilverBullet">XpIsNotaSilverBullet</a> -- <a href="http://c2.com/cgi/wiki?JohnBrewer">JohnBrewer</a>
<p><p><hr>
<p>Okay, I'm very intrigued by what I've read so far. I like iterative design and I'd love to give <a href="BigDesignUpFront.html">BigDesignUpFront</a> the boot and refactor like mad, but there's one thing standing in my way: the relational database. I read stories about people changing their classes as they go and it sounds great but I keep thinking, "How does he get his DBA to change the schema every 10 minutes?" Most of us aren't using <a href="http://c2.com/cgi/wiki?GemStone">GemStone</a> for persistence (or <a href="http://c2.com/cgi/wiki?SmallTalk">SmallTalk</a>, but that's a different matter). Are we just out of luck with XP?
-- <a href="http://c2.com/cgi/wiki?PerrinHarkins">PerrinHarkins</a>
<p><em>See <a href="http://c2.com/cgi/wiki?RefactoringWithRelationalDatabases">RefactoringWithRelationalDatabases</a></em>
<hr>
<p>Unfortunately, <a href="RefactorMercilessly.html">RefactorMercilessly</a> (and some of the other <a href="ExtremeProgramming.html">ExtremeProgramming</a> methods) does not seem like a good match when you're an <a href="http://c2.com/cgi/wiki?OperatingSystem">OperatingSystem</a> or ToolsAndLibraries<a href="http://c2.com/cgi/wiki?edit=ToolsAndLibraries">?</a> vendor. Once you have a shipping library that third parties depend on, <a href="http://c2.com/cgi/wiki?BinaryCompatibility">BinaryCompatibility</a> becomes an essential goal, and the <a href="http://c2.com/cgi/wiki?FragileBaseClassProblem">FragileBaseClassProblem</a> becomes your enemy. Note that all languages that let a derived class expose anything from a base interface/class suffer from some form of FBCP, although some (C++) more than others (<a href="http://c2.com/cgi/wiki?SmallTalk">SmallTalk</a>).
<p>Also, trying to write complete <a href="UnitTests.html">UnitTests</a> for an OS or library would mean that you actually implement all the applications that third parties would implement, and verify that it is possible and runs with good performance.
<p>Thus, I can see how this all would work for something like an end-of-the-line application on which nothing else has binary dependencies, but it seems less well adapted to other kinds of development. Unfortunately, when you are earlier in the food chain, an error affects so many more people (ALL the users of ALL the applications using your library).
<hr>
<em>Also, trying to write complete <a href="UnitTests.html">UnitTests</a> for an OS or library would mean that you actually implement all the applications that third parties would implement, and verify that it is possible and runs with good performance.</em>
<p>I don't see this at all. <a href="UnitTests.html">UnitTests</a> are discrete tests of interface members. How does this require you to figure out every possible use of your framework or library? Without <a href="UnitTests.html">UnitTests</a>, you have to wait for the 3rd party to tell you about bugs in your interfaces. Very bad. --<a href="http://c2.com/cgi/wiki?RobertDiFalco">RobertDiFalco</a>
<hr>
What constitutes <a href="http://c2.com/cgi/wiki?DuplicateCode">DuplicateCode</a>?
<hr>
<a href="http://c2.com/cgi/wiki?TopicGlossaryXp">TopicGlossaryXp</a>, <a href="http://c2.com/cgi/wiki?CategoryRefactoring">CategoryRefactoring</a>
<hr>
See Also: <a href="http://c2.com/cgi/wiki?WhenToStopRefactoring">WhenToStopRefactoring</a>.
<hr><hr><a href="http://c2.com/cgi/wiki?edit=RefactorMercilessly">EditText</a> of this page (last edited March 30, 2001)<br><a href="http://c2.com/cgi/wiki?FindPage&value=RefactorMercilessly">FindPage</a> by browsing or searching<p><font color=gray size=-1>This page mirrored in <a href="index.html">ExtremeProgrammingRoadmap</a> as of March 31, 2001</font></body>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?