Find the rule of thumb.
You know, the one that works most of the time.
The time you save in the vast majority of cases will leave you with an extraordinary amount of time to deal with the exceptions.
"But what about (insert special case here)!?"
Yes? What about it?
The time to optimize (and deal with the special case) is when there is a proven need for it.
Not before.
Optimizing is very different to dealing with special cases. A lot of (most?) bugs occur in special cases. If you don't consider the special cases, you're letting bugs in. Going back and checking for special cases on line-by-line on a huge body of code might possibly be effective, but it's no easier than getting it right the first time, and I bet in 99% of cases, that checking gets omitted. Of course, in theory, your unit tests and assertions are checking those special cases anyway, right? (c.f. the MetaFont test file) Perhaps you mean something different when you say "Special case". Can you give a concrete example? --AnAspirant
I was going to write a paragraph or two explaining how the special cases I was talking about differs from the one you were talking about.
Then I realized that I had forgotten what I was originally talking about (oops... next time I'll add more context).
And then I noticed that I had forgotten before I had finished writing the piece in the first place.
I'm not talking about the act of writing code or other such 'hard' (concrete?) tasks. I'm talking about the 'soft' tasks.
Managing people. Leading programmers. Dealing with management. And so on.
Although I'm sure some sort of case could be made for this in 'hard' task, what I'm getting at is the people related problems, where you can always find another exception.
Just find a solution that works for the brunt of the problem. And treat it as a rule of thumb... if there's a valid reason in some situation not to follow it, then deal with it then. Don't try to deal with it when you create the solution.
As a concrete software example, I'm currently working on a bond analytics library.
Most bonds follow easy-to-understand rules when going from a yield level to a price.
Instead, you start with the simple stuff, and then extend outwards. Progress is a lot quicker. And you end up with a better abstraction at the end of it, since you're constructing things as you go and not adding GoldPlating up front.