This is a guest post from Tim Bourguignon. Enjoy.
Dear new developer,
Let me tell you a story.
Once upon a time, there was a black chalk board in a dark room. The board carried remainders of countless creations. Diagrams that could pass as hieroglyphs for the non-educated eye. Or well crafted UML to the others. From systems to modules, modules to components and component to classes, it all seemed to flow. Generic, inter-operable and reusable, it was beautiful. Those architectural blueprints led the creation of the software. Countless tests secured it, using the best means at hand. Production servers welcomed the bits. But a few week later, the company shut down. There was no market for this software. There was not enough cash left for the company to pivot and explore a different idea. Too much time was lost writing the most beautiful and never used piece of code in the world. Beautiful or well crafted code that doesn’t solve a real problem doesn’t count.
Once upon another time, a software crashed in production. A website was down. A shopping system was not taking orders. A customer was losing a fair amount of money for every hour, every minute and every second that passed. And boy was she furious. A few caffeine-doped hacking hours solved the problem. Thankfulness replaced the customer’s furor. The architecture of the solution lacked flexibility. The re-use potential was at an ever lowest. A bitter smell of copy-paste still held in the air. And the amount of technical debt in the codebase reached new heights. But the fix saved the business. Sometimes, ugly or imperfect code that “do the job” is the best you can hope for.
Here’s how David Heinemeier Hanson and Jason Fried described the launch of Basecamp:
When we launched Basecamp, we didn’t even have the ability to bill customers! Because the product billed in monthly cycles, we knew we had a thirty-day gap to figure it out. So we used the time before launch to solve more urgent problems that actually mattered on day one. Day 30 could wait.Rework by DHH & Jason Fried
Let me rephrase this: they launched a paid-product with no way to earn money! Does this sound sane to you? It actually is. Worst case scenario, nobody is willing to pay anyway. They don’t have users, they don’t need a payment system. Period. They concentrated their effort on making a great product until the launch date. If the product attracted customers, they would need a payment system. The month that ensued might have been smooth… or very bumpy. Again at the end of that following month, some code had to be running. Good or bad, perfect or crappy looking, it had to do the job. Otherwise they would lose money.
Let’s generalize by putting code aside for a moment. Have you ever written a text to throw it out seconds later realizing how crappy it was? I know I do it countless times every single day. Have you ever had a great idea put you into ecstasy, only to throw it away the moment you put it on paper. Have you ever realized how dumb an idea you had, after hearing you verbalize it? I know I do every single day. Plans are perfect, until they meet reality.
For everything you do, there is a right time. Sometimes it is “yesterday”, sometimes it is “now”. But more often than not, it is “later” or even “never”. The best way to find it out is to strive to make “it” work. Whatever you do, try to make your plans meet reality as fast as possible. Only then can you be sure you are not working on false promises.
Don’t underestimate this first rule. We often forget about it at the first pinch of peer pressure. If you write software as part of a team, you have experienced a variation of the following in the past:
My coworkers will review my code. What will they think of me? I’d better refactor this component, make non-trivial changes to this module, enable future extensions in this class and clean my code up to its core to uphold the design standards…
What I could have done in a few minutes has grown into hours and the peer pressure increases. What has taken a long time to craft must be excellent, or was it the contrary?
Can you live up to this first rule? Our formal education taught us to seek the unattainable best grade and to hunt for any flaws. To the contrary, this rule tells us to seek the “good-enough” and then iterate on it. Use those intermediate versions to foster discussion. Lay a “good-enough” version of your work on the table, be open about its flaws and be sharp in criticizing it yourself. As a group, you can then decide whether to invest in making it suck less, or leave it be. As J.B. Rainsberger said in his talk “7 minutes, 26 seconds, and the Fundamental Theorem of Agile Software Development”:
If every item in our shop either costs $8 or $13 and we hard-coded those values, we are done!
Of course, not every draft that does the job is production ready. Production is often far away down the road. You will have to work hard to find out what “good-enough” means for every new challenge you face. But by seeking working solutions in your daily life, you will make true progress. Refine working software. Keep both feet on the ground and focus on tiny measured steps. This is the basis for producing a good solution. The solution that is there when the deadline falls. The solution that makes the business work.
This post was originally published at Auswanderer Quatsch ².
Tim has been building synapses between human beings since 1983. Passionate developer, Mentoring advocate, mentor and mentee himself, he works as Chief Learning Officer, Head of Agile and technical Agile Coach for the MATHEMA company in Germany. In his free time, he hosts the Software Developer’s Journey podcast and spends as much time as he can with his wife, with [1;3] kids clutched on his back!