Macro Once And Only Once

OnceAndOnlyOnce is a rule which prevents duplication of actual source code. In some systems, it is possible to see areas where there is some stylized solution to a problem which can be applied to other areas of the project. Suppose two people need to add a feature A and one of them notices that it is kind of like a feature B elsewhere in the system. There is a conceptual similarity, but not much chance to reuse classes. Under what circumstances does it make sense to go back and look at feature A and adopt the same strategy for B? I tend to like systems where understanding one bit of it helps you understand the rest. How often does this happen on an XP project?

Another question. In XP, are you ever able to look at a piece of code and say "Maria was here"? I know that you adopt the same CodingConventions and you DoTheSimplestThingThatCouldPossiblyWork, but does that lead to an eradication of any design style differences?

Very few design style differences survive. I can think of none that I can relate to an individual. (PairProgramming contributes strongly to there being few differences.) In coding (as opposed to design) style, there are a couple of folks who tend to use excess parentheses, and of course one can spot those. -- RonJeffries

Yet another question. RonJeffries has mentioned that C3 has a large number of classes. Is there a bias in XP towards making a new class even when an older one is adaptable? How often have you had situations where a pair codes up a solution and you look back and say, "Gee, if they only knew about these other classes we have, they wouldn't have had to do that work."?

-- MichaelFeathers


We generally use the same style of solution wherever possible, even if no code reuse is possible. This is what makes a system appear to have a consistent "architecture".

We "always" use existing classes if it's possible. Note that adapting classes generally means making subclasses, which, of course, adds to the number of classes. We have lots of classes because that's how many classes it takes. The system is really in quite good shape, with relatively little redundancy of any kind.

If we accidentally do something with new code that could have been done with (enhancements to) old code, we go back and fix it. If we discover two classes that could be converged into one, we go back and fix it. The whole RefactorMercilessly thing is about doing that. If we didn't, we'd be violating OnceAndOnlyOnce.

Certainly, the team members aren't all identical. PairProgramming cancels out most individual differences, but, for example, certain teams wind up programming a bit more procedurally than others. I can sometimes spot who did what new work. By the time something has been in the system, however, it is pretty well smoothed down, since we have CollectiveCodeOwnership. Whoever sees code that isn't ideal will generally just fix it.

Of course we aren't perfect, and neither is our code. But we are very dedicated to the practices that work for us, and having the code clean and without redundancy is a key aspect to being able to move quickly. -- RonJeffries


From OnceAndOnlyOnce:

I'm uncertain about the boundaries of OnceAndOnlyOnce. Please consider a company that produces Java components for different customers. Each component/a group of components is/are created in a project context. Developers are considering putting all the code into a single name space (e.g. as com/mycompany/customerX/projectY in CVS). So common stuff (smaller helper classes, general network protocol stuff, etc.) is going to land in com/mycompany/util, com/mycompany/net, etc. Really radical OnceAndOnlyOnce. The boundaries are at the company's boundary. With one drawback: all projects depend on this central helper/support code. Changing this becomes a nightmare. In the end, the company needs to create a team that maintains the common packages. IMHO it would be better to have some redundancy in helper/support code to decouple the project code. What do you think? -- BerndGoetz

This is really a case of multiple clients to a shared component with global CodeOwnership. if the component changes, all the clients must be tested and/or modified. In a XP company where all teams can (and must) run each other's unit-tests and acceptance tests whenever anyone changes the shared component, this could work. -- KeithRay PS: my company doesn't go this Extreme, so components used by multiple teams are not also owned by all those teams; instead, we wail and whine and file bug reports if that other team responsible for the shared component changes it and breaks our code.


CanOnceAndOnlyOnceLoop?


EditText of this page (last edited August 24, 2012) or FindPage with title or text search