(This page is the previous version of OnceAndOnlyOnce, which was cleaned up on 4/21/2005.)
Does anyone else see the irony in that? Yes irony, compounded by the fact that the original is better. This page begins with a definition whereas the new page jumps right into discussion and philosophy without first giving a decent definition.
A design technique to replace duplicated declarations of behavior with abstractions.
The philosophy that information on how a piece of software operates - be it an algorithm, a set of constants, human-readable documentation, or something else - should exist in only one place. The practice of this is not always easy; in most languages (LispLanguage advocates claim that practicing OAOO is significantly easier for them), there are many types of situations where there is no obvious way to follow OnceAndOnlyOnce, or where following it requires more effort than simple duplication. The essence of it, however, is: Write everything once and only once - locate and fold together any duplication you find while adding the current feature.
Practitioners of OnceAndOnlyOnce believe that, if information is written down in more than one place:
Yes. I once saw Beck declare two patches of almost completely different code to be "duplication", change them so that they WERE duplication, and then remove the newly inserted duplication to come up with something obviously better. -- RonJeffries, from the XpMailingList
Many techniques can be applied in the service of OnceAndOnlyOnce: Modular programming, structured programming (information about the meaning of a certain code path), data hiding, object-oriented programming... Of course, OAOO is not typically considered the reason for using these techniques, and all of them can be abused as well as used.
YouArentGonnaNeedIt emphasizes the value of avoiding complexity in the first place, while OnceAndOnlyOnce emphasizes the value of removing existing complexity. In other words, as you practice YouArentGonnaNeedIt, remember that you are gonna need OAOO.
Some helps for making your code OnceAndOnlyOnce-compliant:
See also:
Code wants to be simple. If you are aware of CodeSmells, and duplicate code is one of the strongest, and you react accordingly, your systems will get simpler. When I began working in this style, I had to give up the idea that I had the perfect vision of the system to which the system had to conform. Instead, I had to accept that I was only the vehicle for the system expressing its own desire for simplicity. My vision could shape initial direction, and my attention to the desires of the code could affect how quickly and how well the system found its desired shape, but the system is riding me much more than I am riding the system.
-- KentBeck, feeling mystical, see MysticalProgramming
A gigantic refactoring (down from dozens and dozens of pages to what you see now) involved adding a "Therefore"-description at the top of this page. There used to be none at all. RalphJohnson had this to say about it:
I've read this page dozens of times in the past. Reading it again today made my heart sink. It is hard to explain. OnceAndOnlyOnce is a profound concept, but difficult to apply. I've spent my entire professional life (25 years) learning how to apply it to programs. This page makes it seem so sterile, so dead. Since the last time I read it, it was rewritten to make OnceAndOnlyOnce seem like a simple rule to apply, instead of a prime principle. OnceAndOnlyOnce is NOT easy! And it was wrong to refactor this page so that all hints of tension and disagreement are removed from it.
[Time passed. The description was changed. If you still think the above holds, please try to fix it rather than complain. For example, add some divisiveness?]
Ok.. divisiveness... Considering ThreeStrikesAndYouRefactor, shouldn't this be called OnceAndOnlyTwice?? [You only live twice, Mr. Bond.] But even that doesn't quite capture the real issue. There are some things which are just so worthwhile that you replicate them all over the system, wherever appropriate. + is an example - you'd be silly if you tried to factor an application so that addition happens only once. Likewise for data references, etc., etc.
I believe this is a misinterpretation of OnceAndOnlyOnce. Once and only once suggests that you implement something once, not that you call it once. Using addition throughout your program is permitted.
(Divisiveness, continued) Refactoring leads some people's thinking into the rich history of mathematics, where people recognize similarities (or "Type Puns" as I sometimes like to think of them) and use mappings between similarities to solve problems. Mastery, of programming, or of a program, shows up as the ability to clearly express ideas in a concise manner - OnceAndOnlyOnce is an attempt to capture the end point of Mastery. But it doesn't lead the way there - for that you need some teaching tools (like PairProgramming and UnitTesting). But teaching tools don't really lead the way there, either - for that, you need real leaders who FocusOnWhatsImportant?.
Once, this page was refactored into a pattern form. OnceAndOnlyOnce is not a pattern. A pattern is something you can teach someone to do in a fairly short amount of time. A day, usually. Perhaps a few weeks. But learning how to refactor classes to form a TemplateMethod does not help you see how to use XML to represent your user interfaces (a recent OnceAndOnlyOnce technique applied to Squeak), or how to make a good virtual machine. These are patterns; OnceAndOnlyOnce is not a pattern. OnceAndOnlyOnce is a principle. -- RalphJohnson
Here's an example of OAOO tension ... if I recall accurately, JohnVlissides wrote somewhere (I think he was writing about SubjectOrientedProgramming) that the ability to modify a system's functionality by adding code (and leaving existing code untouched) was the mark of good programming. the "don't change existing code" part clearly feels less risky than doing OAOO. I suspect that many programmers have internalized something similar to "don't change existing code," and it is probably one of the motivations behind CopyAndPasteProgramming. CopyAndPasteProgramming allows you to modify functionality by adding code and leaving most of the existing code untouched. And you can't really blame them. Leaving working code untouched is not an unreasonable way of minimizing risk. ... the urge to apply OAOO must be balanced by an unwillingness to change working code. -- Mark Rim
Perhaps the best explanation of OAOO I've seen is a direct example of an existing program (say one that generates an E-commerce site for a restaurant) and making the necessary changes to a duplicate copy of that program to load in a different environment (say a department store). While most of the code remains the same, the upkeep between the two copies means that a fix in one might actually break the other. By putting the common logic in one place (such as a traditional library) and limiting access to only the necessary calls later, the changes that affect both programs won't crash the other. (Please clean this up if need be. -- WyattMatthews)
I've been practicing "OnceAndOnlyOnce" for years without having such a different name. I usually referred to it as Modular Code or Code Reuse. I learned it the hard way over many years of programming. Oft-times, I would be developing something and go to cut-n-paste something good from somewhere else and realize it would be nice to have a clean interface for it. Such modularization encouraged me to think more about clean, elegant interfaces. Such a teaching means that the programming tools I put together are usually more flexible than at first envisaged. I will usually prefer to spend a lot more time at the outset to create a much more reusable tool than have to rewrite when I want to use it a slightly different way. Even adding simple, but not-needed-right-now options are potentially useful and I've learned I cannot predict when they will be later useful. So I add them anyway!
-- Wade "Static" Bowmer.
I add this remark with some trepidation (having read the history of this page). Wouldn't this principle make most sense to those who were familiar with the concept of database normalization? The object there is to ensure that each piece of information is kept OnceAndOnlyOnce, with the exception of foreign key values which express relationships between entity occurrences. Just wondered if the parallels might be useful in explanation. Please feel free to move these comments down the page when responding. -- SteveHolden
That's pretty much my observation as someone moving over from a traditional Process oriented background - COBOL (don't laugh!) to OO analysis & design. Entity Relationship Models use a top down approach to derive a normalized view of the data, and it seems to me that in OO analysis/design an object model is normalized data (attributes/properties) AND logic (operations/methods). -- Keith
(Discussion of OAOO, open-source, and communism moved to OpenSourceCommunism)
I like the idea of OAOO. However, much of my work is RDBMS based (Oracle), meaning that I write a fair bit of SQL. Sometimes, the simplest way to get the data you need is to throw everything into one big (possibly ugly) SQL statement. The database optimizer then works out the best way to get what you need. If the data changes, it does it a different way. The problem is that if I want to encode something once and only once, that means I have to break up these large SQL statements and do things procedurally instead (PL/SQL). This means that the code looks good but runs like a dog and all that money spent on the database and its optimizer is as good as wasted. Thoughts anyone?
-- ChrisRimmer
Anything stopping you from building up the massive SQL statement from the decomposed procedures, and running the optimizer on that?
Yes. I think you've misunderstood the problem. The point about SQL is that you tell it what you want, not how to do it. These procedures actually return data, not a fragment of SQL. So there's no way to combine them to produce some big SQL statement.
The answer is, I believe to use database views to encapsulate multi-table relationships. I had already pretty come to this view (pardon the pun) when I read this article by Martin Fowler:
http://www.martinfowler.com/articles/dblogic.html
-- ChrisRimmer
You won't get much direct benefit to performance by practicing OAOO. The benefit comes in reducing complexity and therefore increasing understanding/maintainability/extensibility. In the statement above, "one big (possibly ugly) SQL statement" can translate to one big complex, off-putting statement. It may run well, but the next guy that sees it, even if it is you one month from now, may find it sooo hard to understand that he shies away from it, or spends 5 times the effort in understanding and modifying it as would have been necessary for a few separate procedures. -- Jeff Santini
I didn't expect to get a benefit to performance. I was looking for the kind of maintenance gains you talk about. However, what I don't want is a thousand-fold decrease in performance! This is quite possible in the situation I describe. See my comments above about the use of views. -- ChrisRimmer
Slashdot has an article about the correlation of redundant code to defects. A study using static analysis of the Linux kernel code found that files with duplication were 45% to 100% more likely to contain bugs. That's a great reason to do OnceAndOnlyOnce. -- DavidPlumpton
I don't think the paper in question (http://www.stanford.edu/~engler/p401-xie.pdf) really says that. They are talking about redundancies (things like dead code, variables assigned to themselves, etc.), not duplicate code. -- EricHodges
(Feel free to remove such fluff, but this is just to lighten up the tenor of the page...)
Has anyone else ever noticed that the phrase "once and only once" is, itself, redundant? In proper English (sorry, Yerpians and other furners), the phrase "only once" is explicit without adding the useless precursor to it. Hmm. Refactoring called for, methinks.
Natural language is not code. Repetition for emphasis is acceptable, and the "only once" ensures that twice is not valid. Three is right out.
The person before was saying the "once and" was the superfluous part. "Only once" is sufficient to convey meaning clearly. No one would think that twice would be okay if they were told to do something "only once". A lot of "emphasis" expressions in English (such as "in any way, shape or form") are actually not condoned by good writers.
It is this kind of nonsense up with which I will not put. Repetition for emphasis is perfectly acceptable - the language would be sterile without the flourishes of this kind. Shakespeare provides many examples of bad grammar that are considered excellent speech. Also, only once leaves a vernacular gap - zero or one time might be acceptable there.
Vernacular gap? Puh-leeeease. Someone might say, "That code is in two places. That code should be written only once." Do you really think that the intended audience might then interpret that to mean he or she might have the option to eliminate the code from both places? As for your Shakespeare comment, there is a big difference between writing as an art and writing for business communication. I was speaking of the latter type of writing, good writers of which would not condone the flourishes whereof thou speakest, dude.
OAOO is a catchphrase for the rule. It is acceptable that it be written with a flourish to make it memorable.
How about saying "Exactly once?" This has the same overall effect as "only once," but has a stronger emphasis on the elimination of redundancy by implication. Or not, what do I know?
OAOO has a rhythm to it that aids retention in one's memory, similar to the old trick of making rhymes to remember things, so (IMHO) it works better as a catchphrase.
It echoes "The truth, the whole truth, and nothing but the truth."
It's funny because it isn't just one person making these replies, so maybe you are outnumbered on OAOO. ;-) I like the suggestion of "exactly once". Or if you need a rhythm (note spelling), we could sing the rule like this: "This is the way we write our code, write our code, write our code. This is the way we write our code, exa-a-a-ct-ly once".
: OnlyOnce?'s acronym (OO) is too easy to confuse with ObjectOriented's (OO). ;)I would think that the primary appeal of the phrase as it stands is that it reflects the logical equivalence phrasing "if and only if". -- Mike G. Burton
''"Once and Only Once" is not redundant. Contrast "Do it once and only once" with "Do it once and do it again."
: Then again, contrast "Do it only once" with either of the last two phrases.Unique rather than one of ... .
The PragmaticProgrammers say DontRepeatYourself.
Even "Once" would be sufficient, as more or less would no longer be once. Still, OAOO has the right ring to it.
"Only once" can, in some contexts, mean zero or one times. "Once" by itself can mean one or more times. "Once and only once", outside of context, means "Exactly once." When you are talking about doing something OAOO in a discussion or a document, you might use the words "once" or "only once" by themselves, but that's not what this debate is about. The debate is, by what label do we refer to the principle?
Exactly! I'm glad someone finally sees the point I was making!
Uhh...say, what?!? How can "only once" ever be interpreted as something other than exactly one occurrence?
In ordinary English, phrase like "only once" could be construed to mean <=1 and not necessarily ==1, depending on context. For example, there used to be an IRS regulation that said you could sell your house without paying capital gains tax, but "only once" in your life. I doubt that any court ever interpreted that to mean that all Americans are required to sell their house before they die. Similarly, I would not be surprised to hear someone say, "Laws against bigamy require that a man have only one wife". Would anyone construe this statement to mean that every man MUST be married? Which brings to mind, I have heard much debate over the years in Christian circles over whether the Bibical requirement that a pastor must be the "husband of only one wife" means that he cannot be divorced and remarried, or that he cannot be a bigamist, i.e. does "only one" mean "only one at a time" or "only one ever".
Um, no. You've quoted poor English examples to substantiate your argument: 'once' means 'exactly one time'. 'Only once' is a tautology, in this case the 'only' being simply emphatic, so if one wanted to be really pedantic the topic should be called 'Once'. Doesn't have quite the same ring to it though does it? ;o) -- RJTAll of which said, there is a vast difference between redundant language and redundant code. If the writer decided to change the phrase "one and only once" to "exactly once", and happened to miss changing it one place out of twenty, this mistake might cause some modest confusion to readers, but almost all would surely figure out the intent, and at worst understanding might be modestly impaired. But if a software project decided to change, say, the format of data written to a database, and the programmers missed changing one place out of twenty, at best the program would fail when we tried to execute the unchanged portion; at worst it would succeed and corrupt the database.
In programming we want to say everything exactly once because that eliminates possibilities for ambiguity and contradiction and reduces maintenance burden. But in writing we often say things more than once for emphasis, or to explain the same concept in two different ways for clarity. We often need to repeat things for people because they might not get it the first time. A computer either understands what you said or it doesn't. I'm reminded of a program I had to modify years ago that had three GOTO statements in a row that all specified the same place. (Yes, many years ago, in the prehistoric COBOL days.) I asked the original programmer what he was trying to accomplish. He "explained" that he wanted to make sure it really went there. It does not at all follow that "good programming practice" and "good writing" should follow the same rules. Any more than I assume that the rules of good programming practice apply to French cooking or origami.
The way I learned it is that there are two elements of OnceAndOnlyOnce:
hth -- PaulMitchellGears
If only there was a way to say ==1 in less than four words. Oh wait, there is! ExactlyOnce!
OnceAndOnlyOnce makes for a better slogan though...
Ow! Okay, this is the part that gets me - if you say "once," how can that mean "not at all?" We are playing around with semantics that are hiding the original value and meaning. Eh?
One last attempt and then we drop the semantic drivel. The opposite of "Do something once and only once" would be "Do something once and then do it again (and again)."
Err - that doesn't make a lot of sense semantically or otherwise. If we are going to start playing with semantic definitions here shouldn't we get somebody who actually knows this stuff involved?
But see YouDontNeedItAnymore before you RefactorMercilessly, particularly the bit about accidentally hiding unused code.
Let's please move past the actual name of this principle. Now, let's gain a deeper understanding of the two hindrances to proper OAOO: expression and time.
Concerning the former, no programming language available today is capable of the marvelous expression necessary to convey an idea accurately, flawlessly, and abstractly. None is able to express the true nature of the things the mind can conceive. Hence, we just don’t have the way to convey things properly. Unfortunately, such expression might be so bewildering as to dissuade from the pursuit thereof. (Personally, I hope that a wonderfully consummate programming language appears soon so that I can leave all the others behind.)
As for the matter of time, I wouldn't say that anyone's ability to design a system is strong or weak. I’m happy to see all the designs. But, I would say that implementation is often hasty because of deadlines and errant because of ignorance.
In conclusion, had we superior expression and infinite time, we would be able to achieve OAOO with utter perfection.
-- JJDawson
My favourite instance of OnceAndOnlyOnce was the following exercise. I needed to implement some geometrical interpolation functions over a set of variables. The set of variables was defined only at runtime, and the implementation language was C++ (not the most natural of languages for expressing this sort of idea). The fact that the types of the variables were known only at runtime, and that the interpolation algorithm was independent of the type, implied the use of template functions to contain the representation of the type-independent interpolation algorithms. Nothing too fancy so far.
But now, I also wanted to abstract out the control algorithm which surrounded the template function call, because the control algorithm was common to all of the places where variables needed to be interpolated. The obvious plan would be to write a function that encapsulated the control algorithm (basically a loop over the set of variables, with a type decoder to make the static template function instantiation work). However, the control algorithm needed to call different template function algorithms depending on what part of the code was calling it. These template functions had different sets of arguments passed in from surrounding code, and hence could not be expressed as a function pointer argument to a single control function - not to mention that template function pointers are a dodgy concept at best. So I employed a macro instead of a function to encapsulate the control algorithm, the macro being the lesser of two evils compared to OnceAndOnlyOnce.
Finally I needed another macro to allow the control loop macro to expand the corresponding template function call in place depending on the type of the variable in each iteration of the control loop.
All of this is to say that although the language did not allow me to express the design concepts in the most natural form, I nevertheless went to a substantial amount of effort to achieve OnceAndOnlyOnce for its maintenance benefits, rather than taking the easier-to-write but harder-to-maintain-and-debug approach of CopyAndPasteProgramming.
"None is able to express the true nature of the things the mind can conceive" -
Alan Turing proved that even his simple turing machine was capable of universal computation, therefore if any programming language can express a turing machine, it can express any computable function. Humans are *not* however somehow magically capable of expressing incomputable functions. Therefore human minds and programming languages are firmly on the same footing as to expression. You can express *anything* the mind can conceive even only using assembly, but it might take a long time, especially if you aren't using OAOO.
"In conclusion, had we superior expression and infinite time, we would be able to achieve OAOO with utter perfection." What makes you think we need infinite time? OnceAndOnlyOnce suggests to me it should be instantaneous.
Has anyone noticed that after lots of refactoring, not only do you get OnceAndOnlyOnce, and LotsOfShortMethods, but a lot of classes only have one method and one field (or fields that are so closely related they should be a tuple, like {x,y} in a point), or they at least tend towards that situation? How about the phrase OnePerOne??
-- MikeAmy?
See: TwiceAndOnlyTwice?, OnceAndOnlyOnceCommunismDiscussion, OnceAndOnlyOnceNameParadox
No paradox at all: Surely it is OnceAndOnlyOnce in the same way that it is IfAndOnlyIf (iff)
-- JohnArrizza?
CategoryModellingLawsAndPrinciples, CategoryExtremeProgramming, CategoryPlanning