If It Is Working Dont Change

Some projects and parts of project sometimes achieve a state where it is working, but it is not really done in the way we want. Many people advocate that if it is working, you should not change it. (YouArentGonnaNeedIt and IfItAintBrokeDontFixIt).

However, ReFactoring seems to mean just the opposite.

Is this an AmeliorationPattern or an AntiPattern?

-- GeraldoXexeo

You could probably leave code in a poorly-factored-but-functional state if you knew it would never change. But honestly, when does that ever happen? Code always needs to be resilient to change. Bugs are found and need to be rooted out. An existing client asks for a new feature. You get a new client who asks for a dozen new features.

Maybe some people can predict things well enough to say "This part of the code will never need to be changed or understood in the future, so let's leave it." Personally, I'd never feel safe saying such a thing. If for no other reason than that I've too often been on the other end: asked to retrofit a five-year-old chunk of code that is a mess because five years ago nobody predicted I'd need to reuse it.

Many software developers have a distorted view of the EconomicsOfRefactoring, seeing the costs and risks but not the benefits. Until the benefits become clear, IfItIsWorkingDontChange makes sense.

What about the case where you have an old bridge? An engineer says "we need to repair the bridge; it's showing its age" and the manager says "it's still working; don't change anything"?

The engineer comes back and says, "If we leave it like this, it'll fall down, and everyone will blame you."

However, software is not a bridge. It doesn't get metal fatigue, the concrete doesn't wear away, crack, and get brittle.Cynic's take: the manager says "just fill in the potholes", engineer says, "That won't make it safe", manager hunts around for someone who will just patch the potholes, bridge falls down, manager blames engineer for not working on it.

Software may require maintanence over time to reflect changes in other things; e.g., an accounting package may need to be changed to meet new tax laws. The second part is eaxctly right, however. - JayOsako

I've seen this same AntiPattern active in the larger sense of development process in addition to the micro-level of the individual project. We've actually had complaints from the business that the software being developed has three major problems:
  1. It takes too long to build.
  2. The delivered system doesn't meet the users needs.
  3. The system suffers from stability and performance issues.
These problems could very easily be addressed by the healthy application of AgileProcesses, however we are repeatedly being stonewalled by developers and development managers for the reasons that "we've been able to develop systems effectively using the current process, so why should we change to something unproven and radical?" This seems to be nothing more than IfItIsWorkingDontChange applied on a larger scale, which I suggest is predicated on an inability to view the reality of the current situation (I'm sure there's an AntiPattern for that... Perhaps RoseColoredGlasses??) --SeanMcNamara

If there are developers and managers that committed to believing that a broken process is working, it might be time to review some of the ResignPatterns.

Isn't IfItIsWorkingDontChange an AntiPattern in the sense that this seem to be working all right, we have no idea how, so lets not touch it? There might also be a political reference to the NotInventedHere AntiPattern in the sense that it's a bad thing to re-write code just because we can't understand it. --NiclasOlofsson

It could also mean that you have a schedule to adhere to that is tight and have a lot of new functionality to write, that it might be a little self-indulgent (and possibly reckless) to rewrite code that is working just because you don't understand it. Save that for when you have plenty of time, and make sure you do it on a private branch. --RobertDiFalco

Code that is working, but you don't understand how. If you don't know how it works, how do you know that anything you do to anything in the system won't break some assumption about that code? The choice is either to figure out how that code works, or ditch it for something that you understand. Pretending that everthing will be okay is not okay. Understanding is a prerequisite. --WilliamUnderwood

(see OldRulesWithForgottenReasons)

YouArentGonnaNeedIt, but still RefactorMercilessly.

The problem with IfItAintBrokeDontFixIt is that as technology changes, old solutions are no longer optimal. Therefore, what worked in the past (e.g., Cobol programming) is not necessarily a good solution in the present.

TechnicalDebt accumulates on its own, in the same way that inflation reduces the value of money stuffed under the mattress.

I assume that IfItIsWorkingDontChange is referring to the changes that one could do to code that he is actually using / enhancing. So, technology isn't exactly a thing you need to change if it is working and you aren't updating the old Cobol program. Even so, you might still use Cobol, only that some old pieces of code could need some Refactoring. There still is a Cobol programming market, you know.

An example of this is a can-opener - in spite of the technology changes in packaging, the one invented in your grandparents days is still as useful as ever at opening a can of chicken-noodle soup. Tools are shaped based on the object upon which they are to work. One invents tools when the objects to be handled have no fitting tools. IfItIsWorkingDontChange is applicable and appropriate for matching tool/objects. One needs no can-opener to open a package of dried soup in a plastic package.

Yes, but the can opener is a relatively simple tool with interfaces - human hands and the lids of 'tin' cans - which have remained more or less constant (the former because of it's inherent form, the latter to remain usable with existing can openers). Furthermore, while the basic design remains the same, can openers have been improved over time; the current designs are considerably easier to use and much less likely to cut you with either the blade or the edge of the can.

The software equivalent is a utility such as the Unix 'cat(1)' - and that, indeed, has remained more or less unchanged in over thirty years. The changes made to it are for primarily for convenience, roughly equivalent to can openers with easy-grip handles and side-cutting rotating blades. - JayOsako
"If it is working don't change" is also the first half of the PrisonersDilemma strategy "WinStayLoseSwitch?". The back half of the strategy of course would be "Do change if it is not working".
I think this concern arises from looking at refactoring in isolation from other steps.

If one is following DoTheSimplestThingThatCouldPossiblyWork, refactoring is necessary immediately after get a passing test (this also assumes one is using TestFirstDesign and ProgrammerTests to define code as "working"). The next time refactoring comes into play is when one needs to make a change (i.e., the system is no longer considered "woorking"). If someone is just refactoring for the hell of it, that person does not have enough to do.

There is no conflict between refactoring and IfItIsWorkingDontChange, when one considers refactoring in the correct context.

And what makes them so sure it's working?

Just because they don't happen to know what's wrong with it doesn't imply that it's perfect.

Complex untested code typically contains errors. I've often found and fixed serous bugs by refactoring nasty legacy code, simplifying it to the point where its logical contradictions and bugs are obvious, and then fixing them. Sometimes I've even received bug reports from the field and found that I've already fixed them: The refactoring and bug fix was already in the release cycle, awaiting production release.

So what makes these people so sure that their absence of knowledge about bugs implies that there are no bugs? -- JeffGrigg

YouArentGonnaNeedIt and Refactoring seem to pull in opposite directions, but they really don't: one refactors to the degree that it is "needed", but different individuals have different ideas of "need." The debates on these topics aren't about YouArentGonnaNeedIt vs RefactorMercilessly so much as about how one determines what is needed. IfItIsWorkingDontChange can be an AntiPattern insofar as it reflects an attitude of avoiding paying off TechnicalDebt, but it can often be the best approach if the CodeSmell is so bad that a "refactor" would really be a "rewrite" and require a project/plan/budget of its own.

See also WhatIsRefactoring, ThingsYouShouldNeverDo
CategoryPattern CategoryAntiPattern

View edit of February 27, 2012 or FindPage with title or text search