This formulation of this statement has been attributed to KentBeck
; it has existed as part of the UnixWay
for a long time.
's "Hints for Computer System Design" (1983) http://research.microsoft.com/en-us/um/people/blampson/33-hints/webpage.html
and Stephen C. Johnson and Brian W. Kernighan's "The C Language and Models for Systems Programming" in Byte magazine (August 1983) ("the strategy is definitely: first make it work, then make it right, and, finally, make it fast.")
The second half of this (making it right before making it fast) is really just a reformulation of the RulesOfOptimization
If it doesn't work right, in what sense does it work at all?
Here's my interpretation. First crank out code that handles one common case (MakeItWork). Then fix all of the special cases, error handling, etc. so all tests pass (MakeItRight?).
Another interpretation, "Make it right" means make the code more clear, i.e., refactor. "Make it work" is the part about getting the code to operate correctly. A rephrase might be, "Make it work correctly, make the source code clear, make it run quickly."
This reminds me of something KentBeck
wrote in TestDrivenDevelopment
: Write a test, make it run, make it right. To make it run, one is allowed to violate principles of good design. Making it right means to refactor it. -- DaveHoover
Isn't this a violation of the law of IncompatibleGoals - "Good, fast, cheap - pick any two"?
No. There is no "make it cheap" in the phrase.
Quite correct. However, there is "make it right" followed by "make it fast". Does fast mean "run quickly", or does it mean "do it right now", in which case they are incompatible goals?
I don't think it means either 'make it quickly' or 'make it right now'. I think it means 'Make it become fast'.
I have always taken it as a statement of evolution of one's solution. I.e., to mean "make the code work, then make it 'right' (as in morally correct, i.e. good design), then make it run quickly". Is this the canonical interpretation? -- PaulMitchellGears
What happens when 'right' also means 'fast'? Localized optimization certainly is the root of all programming evil. But is global optimization?
[Note: Global optimization is making design choices that become very difficult to change after you've made such decisions because they pervade your code base.]
Right. "Make it work, make it right, make it fast" is an assertion that if you can "make it right", you'll be able to "make it fast" later. You won't need to do any global optimization - it'll all be local. It's only those times when you can't "make it right" that you have to DesignForPerformance
ahead of time.
"Right" never means "fast", though "fast" may be an equally important requirement. If so, you first make it "right" (and possibly slow), then transform the "right" program into the "right and fast" program. While doing so, you always have a way to check whether the program is still "right", at the very least by comparing it against the known "right and slow" version.
Should you attempt to directly write the "right and fast" version, you'll get tangled up in complicated algorithms and non-obvious structures and it will never become "right" because you don't understand your own code any more. After all, if it isn't "right", it doesn't matter much how quickly it delivers the wrong results.
- Get at least some of the stuff to work so you are getting feedback (i.e. get your first test case to pass)
- From there, get everything to work so you have completed a chunk of functionality
- Optional: make it go faster, but only if you need to.
My interpretation of this phrase is that it describes the relationship between TestFirstDesign
, and Refactoring.
When I first started TestFirstDesign
, I found I was spending way too much time thinking about good names, good structure, etc. What I found was that it was far more productive to do just the bare minimum to get the test to pass. If one can think of a good method or variable name, use it, but if not, just use the first thing that comes to mind. If one does not want to type in a long descriptive variable name, use a short one instead. Just pass the test, just make it work. Now that the code works, improve method and variable names; do a search and replace to change short names to long descriptive ones; move methods to different classes, subdivide methods, combine methods, reuse existing methods. Now is the time to make the code structurally and aesthetically please, make it right. Finally, the performance of the program as a whole is important. Make sure the new operation runs adequately fast and does not excessively degrade other operations. If need be, make some alterations to improve the performance, but only if it is necessary or at least desirable. Now is the time to make it fast, but only address speed where it is needed.
I think software, at the micro-level, challenges the common belief, "If you can't do it right the first time, when will you have time to do it over?" Experimentation is needed to determine what is "right" whether one does the experimentation in one's mind or by trying different versions of the code. It usually takes longer to get that mental model right and only have to type the code in once, then to try a version of the code and do it over as needed. -- WayneMack
I've heard a different version of this phrase: MakeItWorkMakeItSmallMakeItFast
Often making it fast is making it right. If you don't think about your design then you are unlikely to meet your requirements. Handling interrupts, for example. Frame rates for video playback. Quality of service guarantees. Task latencies.
(This is obviously EmbeddedSystem
weenie talk, but you strictly application mushheads can listen in and learn something.) Refactoring to the smallest kernel of operations means that your interrupt handlers don't make any decisions, your data is moved through the minimum of layers, and everything progresses as quickly as the code can be made to work. That's fast. That's right. But only if it all works.
I always interpreted this phrase in terms of business needs, not coding standards.
1. Meet the minimum requirements for the business to call project a success. (Make it work.)
2. Add bells and whistles to make the program less prone to error and more feature rich. (Make it right.)
3. Find and eliminate waste in the process. Some assumtions from the start will have been incorrect. Remove unecessary business logic. Included in this step is to improve code for better performance. (Make it fast.)
Another form: Make it run, make it right, make it fast. In other words, get to a running system first. Once it is running, make it right. Then make it fast.
Here is a different take on the phrase to make fast. The origin may differ from the current intent, but to make something fast is to make it not easily moved, freed, or separated; firm, fixed, or stuck. This is from Webster's New World Dictionary. So the original phrase to make something fast, was probably to make something firm or not easily moved. This is where we get the word fasten. Once again, fast as we use it has changed over time, but if you look at it from an earlier meaning, then there is no contradiction.