[...from ThelopNameExample, where it was just begging to be made a page.]
...but misunderstood. DoItRightTheFirstTime
was not meant on an overall module or project level. It was meant to be applied on the single function interface: its name and its functionality. If this is done right, you will *never* have to change it again. You may change its implementation details, you may change the places where it it used, you may even correct errors that are found, but you will never change its prototype and its semantic content. So you have produced a building block that may be reused either on the module level, the project level or - if it is general enough - as a general library function. If you use Thelop it will be clear from its name, where it belongs. It will also be an incarnation of LanguageIndependentProgramming
, so if you switch the programming language you will be able to transfer the API directly (and only change part of the implementation). This means a shift in the time horizon. You no longer program for the project at hand or for a time span of 3-10 years, you start to create code that's meant to last. That's what is called ProgrammingForEternity?
. -- HelmutLeitner
(Sorry, I just had to say that. ;-)
Sometimes the wrong kind of upfront DomainAnalysis
can harm its target iteration if too much new theory underrid the old: CodeUnitTestFirst
means _before_ committing resources to this. See ExtractAlgorithmRefactor
Otherwise, you can upfront all you like if your brains feel not full-top with domain details: Recognizing it's best served with this reveals don't pray to it when actually implementing its schemes. --PCP.
Don't apologize, but do explain what you
I get the best results by trying
to do BigDesignUpFront
, even though the reality is a fractal mess of back-tracking and fore-tracking. This is similar to the argument that you can't ever achieve perfection, but you're not even going to come close if you don't kid yourself about it and really try. Jeez, this subject makes my head hurt. But tell me...
Would you rather buy
quality from a hypocrite, or
crap from somebody consistent?
It turns out that the combination of YouArentGonnaNeedIt
, testing, and refactoring allow you to start with anything -- even a very bad guess -- and get to something very good in not too much time. There's no need in code to do it right the first time.
Sometimes you can't figure out how to refactor it, so you put it off and figure out how to do it right the second time. That happens also, and doesn't prove to be much of a problem when you have tests.
Understood, but there's a need to
try. Would you guess the square root of two to be one hundred and twenty-five? In systems of closed feedback (like what you describe above), there is sometimes a convergeance on quality and sometimes not, and there is something that makes convergeance take place. I can look at a first attempt and predict whether convergeance will ever occur. Throw away the bathwater, throw away the baby.
The above is counter to my experience. It's not that hard to make good code great, or bad code better. It's a lot easier than trying to get it right the first time. My experience is that I seldom do
get it right the first time, so effort spent trying is a waste of time. Smarter brains may do better.
Beyond a certain threshold, trying to get a first effort to be perfect
is a waste of time. Beyond a different threshold, an effort with insufficient attention to excellence is also a waste of time (and why I take issue with "not that hard to make bad code better" -- oh, yes it is!). It's probably futile to discuss only one of those thresholds at a time. Your last statement is loaded with wisdom: "Smarter brains may do better." From seeking perfection (but not going much beyond threshold number one),
your brain is that very brain, poised to do better on the next effort. Are we in balance yet? -- WaldenMathews
Sounds like it.
DIRTFT is a part of LanguageOrientedProgramming
and is primarily used on the API because that's what really counts in the long run. The implementation of individual functions/method bodies seems relatively unimportant. There is no hard work and no large design necessary to achieve DIRTFT for an API within the framework of LOP because its automatic if you use your language correctly.--hl
That makes LOP sound suspiciously like a SilverBullet; and "it's automatic" sounds like ForFree...
It surely isn't a SilverBullet
, because LOP attacks only certain types of problems (readability, learnability, consistency, orthogonality, completeness). It is free, because LOP is not a product you can buy. It is not free, because essentially you have to learn a language.
"LOP may be used as a weapon against bad design." -- hl
"LOP may be used as a weapon against proprietary APIs." -- hl
When considering "do it right the first time,"
I think we need to separate "doing it all the first time" from "each thing you do must be 'right' (IE: without errors/bugs) before you go to the next thing."
- Doing it all the first time through is typical of WaterFall, with BigDesignUpFront.
- While CodeUnitTestFirst ensures that the code you write is "correct" within minutes (effectively "the first time"), the design you have right now may not be the design that's delivered to the customer.
Thus, I think we have two different meanings for the same phrase.
Excellent distinction, Jeff. But, having decided which things you will do right this time around, don't you at least want to do them completely (i.e., all of what makes up those things)? This turns out to be a test of analytical skill, because it amounts to choosing the right SeparationOfConcerns, and doing what's in scope with rigor and completeness. Slicing the balogne improperly will make this impossible.
This sounds to me like a variation of IfItWorksItIsOk
. How do prove that the overall design is correct and/or optimal? -- hl
The biggest problem with DoItRightTheFirstTime
is that it is an impossible to meet ideal. There are a lot of things which prevent you from doing the "right thing." Two prominent issues are:
- lack of knowledge
- what is right today may be wrong tomorrow
It is rather simplistic to ask for perfection. What people can really achieve is "Do Our Best Every Time." -- WayneMack
Impossible to meet ideals is what life is all about. Most of your conscious life from the moment you understand you are mortal is spent blithely ignoring the fact, and so should it be with quests for perfection. While DoItRightTheFirstTime is impossible, DoOurBestEveryTime? is mere platitude. Somewhere between those, on a line too thin to see with an electron microscope, and too much in motion to ever pin down....is a thing called Living.
You have to DoItRightTheFirstTime
for what you know. The point with an iterative, refactoring approach is that, you don't know
much first time so doing it right is pretty easy. Of course when you add the next bit of functionality DoItRightThisTime
will probably involve changing what you DidRightLastTime?
because, with the new info, it isn't right anymore.
I think we can and should DoItRightThisTime
each time. -- TomAyerst
Tom, yes! There's such a thing as aiming too high and there's such a thing as aiming too low, and no way I know to quantify them, except by looking back at the results of each iteration. Since it's not possible to avoid errors of aim, I personally try to err to the high side, because failing in that zone is a high quality learning experience. Can't say the same for the other end of the spectrum. -- WaldenMathews
Don't forget to contrast DoItRightTheFirstTime
Could one say that XP is DoItRightTheNextTime?
? With the understanding that the feedback loop is made as short as possible, so that the epsilon to "next time" approaches zero. --JeffMantei
In the context of QualityIsFree
is the economic value of doing a job right the first time because it is cheaper to do so (i.e., avoid costs associated with rework, recalls, external failures, etc.). It relates to conforming to known requirements -- not about predicting future unforeseen changes to requirements. Also, DoItRightTheFirstTime
isn't tied to a specific SDLC, methodology, or process -- thus, it's not necessarily the cheapest
way to do something. -- AnthonPang
No disrespect to the author of the first bit on this page, but when I saw that he advocates code that will never change, that is meant to last for all eternity, my first reaction was that this must be some kind of joke or prank. Do people actually believe this is a possible or desirable goal? Why?
- I'm not at all offended. Most people think like you. Nevertheless is seems desirable to me to invent a language (a set of rules) that reduces the infinite freedom of structuring code to a small set of possibilities. This makes the creation of interfaces and the reuse of code much simpler (just as natural languages makes understanding each other much simpler). It's not the code the never changes but the interface. If we have a "Screen" and want to know its "Width", why should we ever write anything else but width=ScreenRetWidth() or width=screen.RetWidth() ? I wouldn't mind if someone prefers "get" or want to drop the verb or use some other naming standard. But it is senseless to have things like "GetSystemInfo(info_structure); width=info_structure.scr_x_dim; ". If this really exists, please wrap it, hide it in a single place in a library and don't burden zillions of programmers to follow this path. So if I want to capture a part of the screen into an image, I always write image=ScreenRectRetImage(rect); writing it to a File might be ImageWriteFile(image,"test.jpg") while printing might be PrinterDrawImage(x,y,image) or PrinterRectDrawImage(rect,image). It's quite simple and these interfaces never have to change because they are identical to their semantic content. Most APIs are crap because they treat function names and semantical content as different and independent things. If you WalkYourTalk? life becomes incredibly simple. -- HelmutLeitner
And then, next thing you know, somebody invents a pear-shaped screen... Have a lot of fun with that interface...
But what is the meaning of screen width? When I first started programming, the answer was often either 40 or 80 characters. Today, screen width is measured in pixels (or some such unit) and characters do not have a fixed width and the font may be user selected. In other cases, the screen width may refer to a physical measure of the dispay. In other cases, such as server side web, you may not even know. Sure there are lots of bad interface designs out there, but I don't believe there is one true way that you can define and lock down for all uses for all of time. The world does not correspond to programming rules; we have to adjust our programming to fit the world.
- What's the problem? region=PearScreenRetRegion(); width=RegionRetWidth(region); It just adds the word "Pear" to the vocabulary. [Why didn't you DoItRightTheFirstTime and foresee this condition?]
What is the problem? Per the previous statement "It's not the code the never changes but the interface." After declaring that you can define a static interface, you keep coming back and changing the interface to meet the situation. If you keep expanding the interface, then all it appears that you are advocating it that I am forced to implement unneeded functionality for my programming situation to meet your personal "common language."
- What is the Problem?
- pixel=ScreenRetWidth() or pixel=ScreenRetWidthPixel()
- You can have many languages to describe the world, but within one language there are only a few variations to describe given semantics. Programmers currently act as if there is no need for a common language and as if such a common language would deprive them of some kind of freedom. -- hl
If you want to add new kinds of names, that represent kinds of objects that don't exist in your library, you'd better use another library (for example, don't try to add I/O handling to a graphics system). In this specific case you are correct, though. It was a poor design decision from the buddies that wrote the example initially not to think about units. However, it can be fixed, without changing the interface, only by adding new functions: bind S
creenRetWidth to S
creenRetWidthCurUnit (or however you abbreviate current). Create a function that changes the current units, and also make the other getters: S
creenRetWidthCm and others.