A number of patterns recommend centralizing this or that functionality, responding to various specific forces. I am coming to suspect that OnceAndOnlyOnce is a very basic pattern, a "generating" pattern, that directs the emergence of the specific pattern.
In ContainerManagedPersistence, for example, the developers of the app that uses serialization for persistence are dismayed when they have to make mass changes all over to remove serialization and replace it with something else. (Relatedly, a project I know of at a US auto company has code "all over" putting objects into an RDB.)
The "real" bug is that the code to do one thing is "all over". The commonality almost certainly exists - it just wasn't observed, extracted, abstracted, and implemented as an object. --RonJeffries
So yes, once you know the answer and the boundary conditions, any design can be demonstrated to be JustGoodFactoring - but without them, you can't argue. OnceAndOnlyOnce is a hypothesis, from my standpoint, because it is a really strong statement, and I think not suitable under all circumstances (there are boundary conditions of applicability, having to do with the size, cost and time schedule of the development).
I personally like finding the really basic patterns, along with their boundary conditions, because then we can roll out lots of other patterns and understand the line of reasoning that got us there.
Centralizing this or that functionality is great - once you have identified the functionality to centralize. Identification is the nebulous part, centralizing is the "easy", "standard OO design" part. So saying, "centralize things" is also not useful, in my book. It begs and directly asks the question, "How do I decide what things to centralize and what not?" --AlistairCockburn
Often I don't know why I want to move the code from over here to over there. Sometimes there are patterns that say where to go: Aha, let's do Flyweight. This points us back to the discussion on forces in XP patterns. Almost certainly I'm unconsciously balancing forces when I push the design this way or that.
And yet, I suspect that there's more to OnceAndOnlyOnce than meets the eye. Very often when something in C3 isn't well-factored, there is obvious duplication in the code. Obvious enough that something like RefactoringBrowser could find it with long enough search times.
In all the refactorings we have done on C3, we have never once, to my recollection, wanted instance-specific behavior or multiple inheritance. We haven't felt that we were centralizing this at the expense of decentralizing that. This makes me think that most often, there is a global OnceAndOnlyOnce that makes the whole system properly factored. Maybe I'm dreaming. --RonJeffries
Here's a bad example (bad because there are things that can be done):
Enumeration links = note.getLinks(); while (links.hasMoreElements()) { Link link = (Link) links.nextElement(); // Use link. }These 4 lines of code are repeated many times in my current project. It is a standard Java enumeration idiom. The ways I've thought of to refactor it barely seem worth abandoning the "least surprise" benefit of the standard way. -- DaveHarris
This page mirrored in WikiPagesAboutRefactoring as of July 17, 2004