Home | Login | Recent Changes | Search | All Pages | Help
PlanonRefactoringFrom AgilePractices
Early in my project management career, I was concerned about refactoring late in the project. I hemmed and hawed and ate Tums, and said, "OK, go redesign it. But let me know your progress!!" Now I plan on refactoring. Otherwise we're creating a product with built-in technical debt. Have you had bad experiences with refactoring? Keith talks about a good experience on See ClimbOutOfTechDebt . -- JohannaRothman 2003.04.01 If you don't refactor the small stuff while it is easy, it becomes big stuff that is very hard to refactor... If you do a big refactor without previously telling other members of the team, there can be backlash. Suggest refactorings to the team members and get their buy-in before doing the big refactoring. KeithRay 2003.04.01 I worked on a C++ system whose initial developers thought that Microsoft's CString class (in the MFC library) was pretty poor, so they invented their own class and cleverlynamed it "CString". Later, Microsoft's MFC lirary became "desirable" but the oldest code modules were incompatable for mix'n'match use. Instead of refactoring then, they isolated the "new" modules in separate DLLs, never to mix. When I came upon the scene, the desire for other functionality from the MFC library was straining things. I pulled a "stop the presses" class & reference rename so ALL the code could coexist - I renamed the custom string classes "FString" so there were no more collisions. By defering the refactoring, they had acreted bigger debt and had limped around build dependency zanyness too long. When I swept the affected code modules and changed correspondingly, the dancing around self-inflicted wounds went away. I proposed & enforced a naming standard to avoid the classname prefix of "C" because the MFC library never shrinks, only grows to add new names that might collide with home grown over time. (Duh?) Fun. --BobLee 2003.04.02 I just realized that the way I practice IterativePlanning, I refactor project plans, based on updated knowledge. This may be pushing the metaphor too hard... JohannaRothman 2004.04.06 Heck no! I refactor my life every few weeks, at least. JerryWeinberg 2003.04.06 Long ago Ed Yourdon contrasted two approaches to dealing with new requirements (in maintenance, or discovered along the way):
The latter sounds like "refactoring" to me, adjusted for the archaic language. Yourdon suggested "incremental redesign" was necessary to maintain the conceptual integrity of a system under maintenance. I once suggested "incremental redesign" for a system after decade of use and maintenance. Something like: "Maybe we could do a little incremental redesign on this piece, as part of this change?" I was immediately the target of a barrage of vitriol about the "total redesign" I proposed. I checked with other people in the room. I didn't say that. The experience made me wonder why the mishearing, and why all the heat. I think "refactoring" like "incremental redesign" presents a paradox that's scary to some people.
I suspect that people relucatant to embrace small changes to protect from techncial debit - by whatever name - have probably had some kind of bad experience with stealth changes. They're not worried about the small change you are talking about, but the big one you're not. So they're unwilling to put possible changes on the table - once something works at all, don't touch it. They're just protecting themselves and it's not about you. This suggests that the first step to being allowed to "refactor" isn't about a technical justification, but about trust. -- JimBullock 2003.04.08 On the FrequentBuilds page, we discussed preferences for build frequency. It just occurred to me that managing refactoring which entails renaming source (and unit test) modules has some interesting effects on other copies of the source tree. When refactoring renames a file, how does one manage the "please omit the former xxxxxxx.yyy file" from your clone of the sources?
Managing this aspect of refactoring interests me because I've never done it with much tool assistance. It seems to me that managing the volatility of JUnit (or X-Unit) unit test files is an interesting problem that's probably been fairly well solved out there. BobLee 2003.06.30 I suspect Jim is right about the trust issue. "Refactoring" is often used as an excuse to rewrite or add features. Asking "Do you have unit tests in place that will demonstrate that your refactoring won't change semantics?" is some protection. I prefer to take a "the meal isn't done until the kitchen is cleaned up" approach to refactoring. A task isn't done until the loose ends are tied off, and the code has been simplified by refactoring, and there are unit tests in place to demonstrate that the new code does what it intends. Setting this as a standard reduces the need to carve out additional blocks of time for separate "cleanup" activities. --DaveSmith 2003.06.30 Reading through this, I had an epiphany. I was hired at my current job to be a refactorer. I am responsible for test automation, the heart of which dates back into the 1980's. I am the first person to have primary responsibility for this code. All past changes have been made in passing by developers. I spend considerable time shrinking what exists: removing code that is no-longer-used (VMS anyone?); removing code superceded by better features; and, most important, simplifying code that approached Rube Goldberg as each new feature was added without restructuring code underneath it. Having simplified an area, I find I am able to add a newly requested feature with very few lines. Without the simplification, the feature might take hundreds of lines to take into account all of the old mechanisms which, though no longer producing useful output, continue to operate. Mind you, I don't consider this a development problem. The developers did what they had to to get these tools to serve them in the shortest time possible. They worked hard to affect the minimum amount of existing code. The leftovers just accumulated. I'm able to refactor any part of it, because I'm responsible for all of it and can know whether a particular change can be enhanced by a restructuring. On the other hand, I do get common, "Please don't change that, we might need it again!" requests. Trust is part of it. Fear of loss seems to be a bigger part of it. "We did a lot of work there, let's not throw it away, it may be useful." Letting go is hard for us humans. MikeMelendez 2003.07.01 The heart of refactoring is: when you come across something and catch yourself thinking, "we wrote it this way, and that way would have worked better", change it so it now reads that way. If you've learned a better way, put the better way into the code. Or more succinctly: teach the code everything you learn. Also I note that we're responding to Jim's old comments rather than Bob's new question, which makes me wonder whether perhaps we're looking for a page titled RefactoringAndTools, or somesuch. LaurentBossavit 2003.07.01 (hey, tomorrow's my birthday) If you find yourself replacing an algorithm, you're rewriting, not refactoring. It might be the right thing to do, but it isn't refactoring. Martin Fowler and his predecessors (dating back to at least Ralph Johnson's group at U. Illinois, where the first refactoring browser for Smalltalk was done) are very clear that a "refactoring" is a disciplined transformation that simplifies code while preserving semantics. If we let "Refactoring" become a buzz-phrase that provides cover for programmers doing whatever they want, we lose. DaveSmith 2003.07.01 Dave, you're right. I appreciate your standing firm on precision in our terminology. The phrase that's been floating around in XP circles to make that fine distinction is "design improvement". So, the heart of design improvement, of which refactoring is itself the heart, is etc. I'm not sure I see a problem with "programmers doing what they want". People tend to do what they want, whatever I do. The trick is to find something that they want, such that their working to get that will also get me something I want. What do people want that they can get by doing more of the disciplined transformations that simplify code while preserving semantics ? LaurentBossavit 2003.07.02 (biblical age, here I come) (Three score and ten, Laurent? Happy Birthday!) Thanks David for the concise definition. It suggests that the third thing I listed is refactoring. Removing dead code, both by age and by discontinued feature doesn't fit. Can you fill it out a little more. How do you change the source without changing the algorithm? In other words, is there a sharp dividing line between refactoring and rewriting? Or is there a gray area inbetween where it could be called either? MikeMelendez 2003.07.01 Happy Birthday, Laurent! The problem with letting developers using refactoring as an excuse for taking a joyride is that eventually some manager catches on, and down comes the "No More Refactoring" edict. The distinction between refactoring and redesign, as I understand it, comes down to whether changes to working code change the way it behaves. Changing a method name or a parameter name is a simple code refactoring that doesn't change behavior. Noticing that two subclasses share a common method, and moving that method into a common superclass doesn't normally change behavior. Splitting a large subroutine into several smaller pieces won't change behavior if done carefully. Reworking complex logic to eliminate dead code might not change semantics. A simple test is whether your unit tests keep working after the refactoring. Another way to look at it is that "refactoring" is what you do to clean the code up once you've got it working, without changing the way it works. DaveSmith 2003.07.02 Okay, a test question: If I replace code with functionally identical code that runs faster, is that refactoring? Next question: If I replace code with functionally identical code that sometimes runs faster, is that refactoring? - JerryWeinberg 2003.07.02 I've been waiting for that one. -- JimBullock, 2003.07.02 Test answer: maybe. "Replace Algorithm" isn't on the official list, but several refactorings listed here could have "side-effects" affecting run-time. In particular, "replace conditional with polymorphism" can replace a long list of if-then-else-if clauses with a single virtual-function dispatch. KeithRay 2003.07.02 Answer: It depends. If you're talking about something like replacing one sorting algorithm with another (say, when both preserve order), then the answer is No. That's not refactoring, that's replacing an algorithm. It's the difference between, "I'm done, but it's not fast enough, so I'll make a few changes," and "I'm done, but there are a few things I can do to clean the code up." As with any distinction, though, there are gray areas. Some refactoring transformations do have performance implications if you look very closely. DaveSmith 2003.07.02 Oh-oh. "Replace algorithm" is not on Keith's list but "Substitute algorithm" is. From the list it seems that refactoring/rewriting is like the difference between micro/macro economics. All refactoring is local (sorry, I live in Boston). I would say, "within an interface", except that "Add parameter" is also on the list. Clearly, refactoring is agile. MikeMelendez 2003.07.03 I've written unit and acceptance tests which measured the time taken by a given operation. If you have such a test, how fast the operation is performed is part of the program's behaviour. "Functionally neutral" is not an objective characteristic of a code transformation, but must be evaluated relative to some set of requirements. To take a radical example, if the code I'm refactoring is a Quine program, I'm fairly sure that most of the "semantics-preserving" transformations in Martin Fowler's book are not in fact semantics-preserving : the program's own text falls within the purview of the program's requirements. LaurentBossavit 2003.07.03 (Not three score and ten, but old enough to be crucified) What is a Quine program? -- ShannonSeverance July 3, 2003 A quine program is one that outputs or returns its own source code when run. Quines are an interesting fringe case, but one that I'll wager you'll never run into on a real project. --DaveSmith Absolutely. And no one would want to construct the actual G�del number for a G�del sentence. Still, we do consider old Kurt's theorem to be true. I dare to hope you will grant me the more modest claim that there is no such thing as a "semantics-preserving transformation", independent of some set of requirements. Which means, I think you'll also agree, of someone's set of requirements. If you'll pardon the impudent paraphrase: if we let "Refactoring" become soulless technical jargon that provides cover for methodologists counting angels on pinheads, we lose. I'm concerned that I might be getting argumentative here. All of my comments (including this one) are meant in jiggling half-jest. No contempt of your admirable concern for preserving the beneficial qualities of refactoring is intended. No further quines, quibbles, quiddities or quidditch moves from this ardent refactorer and improver or design, I promise. LaurentBossavit 2003.07.04 Well, I suppose there's an implicit rule 0 for Refactoring that says "Understand your application, and don't do anything below if it will cause your application to break." That should cover the fringe cases (like Quines) or cases where requirements are otherwise extraordinary. DaveSmith 2003.07.04
Updated: Saturday, July 5, 2003 |