(Taken from DavesRealExampleWhereThinkingAheadWouldHaveHelped
You had two options: Yagni or ThinkThenCode
. You selected Yagni and later you realized that CodeThenThink?
was worse than ThinkThenCode
. You need to do so many modifications to your code that you hurry up and easily break everything. It is easy to break the code and almost impossible to make it work again.
You didn't GetTheRightAbstraction
. Now the code is a mess.
It sounds like you entered RefactoringHell
This is an excellent example of a time when you need to stop modifying the original code and to create a totally DifferentVersionFromScratch
. Do not throw away the original code, keep the original code that is working and simply reimplement it from scratch. Whenever you think something is difficult, take a look at the original source to get some ideas. It is ok to use some CopyAndPasteProgramming
, since when all the functionality has been migrated, you will just throw away the original code.
Is this the same as plan to ReinventTheWheel, three times in a row?
If the wheel (the right abstraction) is alreay invented, why reinvent it?
Now if you realize that the wheel is not the right abstraction for the problem at hand, GetTheRightAbstraction
while taking care not to ReinventTheWheel
Is this similar to FredBrooks
It is similar, but with a twist. Your system was complete before they said that they also wanted to trade bonds. This is a case of EnlargeTheScope?: The older code was right, but now that the code must do something else, you didn't GetTheRightAbstraction. This is the same as if you just finished Word 1.0 and your customer says he wants your program to behave exactly as Excel too. He oesn't like it when you say it is going to take as long as the fisrt program, because he thinks all software is alike an easy to convert from one to the other.
You don't plan to throw away, since the first program is in production. You prefer to reimplement it from scratch using the right abstractions, that will later allow you to easily implement the rest of the functionality. When the reimplementation is finished, you can only then throw away. Of course, do a backup just in case.
Also from Brooks, he claims that coding time is about 1/6 of total time, the rest being
- 1/3 planning/design/thinking
- 1/6 coding
- 1/4 testing
- 1/4 integration
He claims to have used this estimate for years and it's pretty good.
These days when I look at possibly rewriting I ask:
- how many lines of code will it need?
- how many debugged lines of code per hour can I produce?
- how many hours will this take me?
Example, I have a crufty, unmaintainable BigBallOfMud
that I cannot face working with. I freeze it and start a rewrite. The BBOM is 100,000 lines, the rewrite should result in a cleaner version of only 20,000 lines. I can produce 10 lines per hour of debugged code, it will take 2000 hours. At 8 hours per day that's 250 days, or a complete year.
Now multiply by six - can I wait 6 years for a new update?
Clearly not. If I have 6 programmers working on it can I wait an entire year? There's even more work to do because of the interaction times, can I wait 18 months?
All numbers are approximate - change them to more accurate ones if you like. It's a very good BackOfTheEnvelopeCalculation
Hmm... well, it looks like you spent 30 years to write the first version... it may well be that 6 years isn't that long for an update after all.
In other words, if that 100,000 line program took one year to get to production quality, maybe you can expect to get the 20,000 line rewrite done in 2-3 months, assuming that you maintain the same pace (i.e., maintain enough knowledge). That doesn't seem to be such a bad time frame; on the other hand, if a team of 10 people wrote the first version, and then you come in as a third party maintainer, you really have no business rewriting from scratch on your own say-so.