Incidentally, Steve brought up an interesting topic. Musicians practice by playing fast, then slow, then medium. Fast, slow, medium. Over and over. That seems like a good way to write software.
You first try to implement your idea as quickly as possible, stopping to think only when necessary. The goal is to not spend too much time overthinking the implementation -- you want to find out if your idea is worth executing on.
If you decide that your idea isn't worth it, then you move on to your next one. Otherwise you take it slow, going back over your code and refactoring it. (I personally don't believe in "make one to throw away", but rather that it's possible to refactor an ugly design into a succinct one.) At this stage, you should meditate on the best way to accomplish your engineering goals. It will pay off in the long run to spend extra time here.
Then comes the final stage in your project's lifecycle: medium. The core structure of the design has solidified, and you need to add the flourishes that make software truly great. But you have to take your time to ensure that the codebase stays clean. At this point, the design of the various smaller subsystems should flow naturally from the architecture you decided on in the "slow" phase.
I just recently started writing software >40 hours a week, and have been constantly torn between "getting things done" and "doing things right". The best way to program well might very well be a variation between the two modes.
Actually, it's a lot easier to make it work if you've made it right to begin with. (That said, I've always found the best way to develop is to add functionality to a working program, no matter how small it starts out).
1. Sometimes, making it work is enough. (one time code and such) There's no reason, other than for practice, to waste time designing such cases.
2. You may find out that you're solving the wrong problem, and it's much easier to justify throwing out code that you didn't labor over an extensible design, etc. It's much harder to throw away wrong code that you've put work into the internal design.
3. This doesn't mean that you don't design the outward facing interfaces correctly. Thus, you have a good set of unit tests already set up, and you can quickly tell if something is working as you refactor. You have a good baseline with which to compare.
Comments
Incidentally, Steve brought up an interesting topic. Musicians practice by playing fast, then slow, then medium. Fast, slow, medium. Over and over. That seems like a good way to write software.
You first try to implement your idea as quickly as possible, stopping to think only when necessary. The goal is to not spend too much time overthinking the implementation -- you want to find out if your idea is worth executing on.
If you decide that your idea isn't worth it, then you move on to your next one. Otherwise you take it slow, going back over your code and refactoring it. (I personally don't believe in "make one to throw away", but rather that it's possible to refactor an ugly design into a succinct one.) At this stage, you should meditate on the best way to accomplish your engineering goals. It will pay off in the long run to spend extra time here.
Then comes the final stage in your project's lifecycle: medium. The core structure of the design has solidified, and you need to add the flourishes that make software truly great. But you have to take your time to ensure that the codebase stays clean. At this point, the design of the various smaller subsystems should flow naturally from the architecture you decided on in the "slow" phase.
Repeat for each core feature.
That's exactly where I thought he was going...
I just recently started writing software >40 hours a week, and have been constantly torn between "getting things done" and "doing things right". The best way to program well might very well be a variation between the two modes.
The mantra from eXtreme Programming:
1. Make it work. 2. Make it right. 3. Make it fast. 4. Make it small.
#1 first, then if you have the need, #2. If you have a need, #3. If you have the need, #4.
It's a lot easier to make it right once you've made it work.
Actually, it's a lot easier to make it work if you've made it right to begin with. (That said, I've always found the best way to develop is to add functionality to a working program, no matter how small it starts out).
There are a few problems with this:
1. Sometimes, making it work is enough. (one time code and such) There's no reason, other than for practice, to waste time designing such cases.
2. You may find out that you're solving the wrong problem, and it's much easier to justify throwing out code that you didn't labor over an extensible design, etc. It's much harder to throw away wrong code that you've put work into the internal design.
3. This doesn't mean that you don't design the outward facing interfaces correctly. Thus, you have a good set of unit tests already set up, and you can quickly tell if something is working as you refactor. You have a good baseline with which to compare.