Don't Let Great Be The Enemy Of Good
I've recently started working with a great Tech guy at RecycleBank, Frank Yang. In a discovery meeting I was having with him a few weeks ago, he said something to me that I had never heard before:
Don't let great be the enemy of good
I didn't understand what he meant at first, so I asked him to explain. What he meant was that we shouldn't put off implementing solutions that are only GOOD because we feel that down the road we could come up with a solution that was GREAT. In essence, we shouldn't let the promise of GREAT stop us from doing things that are GOOD, because after all, GOOD things are still good. We shouldn't let the juxtaposition make GOOD things seem bad.
This actually hits home for me a little, because there was a very specific time in my life where I succumbed to this trap in a huge way. A few years ago I was working on a Fitness application that I've had a dream about making since I first learned ColdFusion. I had the design (one of the first designs I ever created that I actually liked), I had all the ideas written on paper, and I was even consulting with Josh Peters, one of the top trainers at Equinox Fitness Clubs in New York City. Things were going well and I was having a blast.
And then, I read about Object Oriented Programming (OOP) in ColdFusion code. Everything I read made sense. Building large, scalable applications using ColdFusion components in an OOP style seemed like the GREAT solution. So great in fact, that it made my current procedural style application a merely GOOD solution.
What did I do after reading about this OOP? I completely stopped building the application. I figured I would stop everything, read up and master OOP, and then start re-building the application from scratch using this new GREAT solution.
That was 4 years ago.
Today, I have not mastered OOP in ColdFusion; I still don't even really understand the basics. I have no working Fitness application. I really have nothing to show for the last 4 years of trying to learn OOP for this project. Basically, I am back to where I was when the application was just a fantasy in my head.
In this case, GREAT was such a huge enemy of GOOD that I felt GOOD was not nearly good enough to even continue developing my existing application. And what has it gotten me? Absolutely nothing; I don't have a GREAT application. I don't have a GOOD application. The only thing I gained from the experience was the loss of 4 years of development time on an application that I have always wanted to build.
I have written similar things actually (for example - http://www.remotesynthesis.com/blog/index.cfm/2007/2/13/Overthinking-Your-Framework-is-a-Stalling-Tactic). However, I hope that the lesson you take away isn't that you should do this project without OO or a Framework. Quite the opposite.
You are too focused on getting OO perfect. No matter how much you study, you are still likely to not get it right the first or second time...and by that I mean, you will look back and see how you could have done things much better when yo are more comfortable. However, this skill can only be honed by the doing and not the studying. OO's endless abstract concepts and terminology don't really gel until you use them.
So, the point is, do your project and do it in OO. No, it won't be perfect, but then you will be closer to realizing your dream and to learning OO. And when you understand the concepts better - go refactor....it's what we do.
Exactly. Sorry, I should have given more of an explanation of what I was thinking in the aftermath. I wish that I had just continued the application in procedural code the first time. That way, I would have at least had a base application to work from for improvements. I would have been able to discover ideas and problems that I had not thought of before.
Then, when I was more comfortable with OOP, I could have ported the existing application to an OOP framework and methodology. But, I wouldn't have to worry about how the application worked from a business standpoint, just from a technical standpoint (as the application would have already been done). I would have already know so much about the application at that point.
Now, having not done anything, not even procedural code, I don't know what surprises are in the application, I don't have any learning experience from the first go-round. So, basically, when I start writing this application again, I will not only be unsure about the OOP, I will be unsure about the application itself.
So, my lesson is that I should go with Good while I can since the good solution will help the future Great to be even better.
I'd just add to that don't let "good enough" be confused with "good" code either. Code that's "good enough" usually comes back to haunt you in one way or another.
I would tend to agree with you. However, in my sad case, I think that anything would have been better than nothing as by doing nothing, I have not gained anything in terms of experience with my app. True, I have been learning better programming the whole time, and would probably have ended up rewriting the entire app anyway, but at least I would have had a solid proof of concept to work with.
My point was more to the lines of make sure you do the best job you can with the code you do produce. You might not be able to implement all the features you want, but make sure the code itself is "good"--not "good enough".
I'm sure the origins of the phrase was geared towards "feature" implementation, where my comment was more geared towards the actual coding implementation.
An overly simple example would be knowing that you shouldn't use "select *" in a query and should always use cfqueryparam, but for original prototyping started off with:
pkey = #url.id#
Well that might be "good enough" to get the job done, it's not "good" code. My point it make sure the code is "good" code:
firstName, lastName, title
pkey = <cfqueryparam type="cf_sql_integer" value="#url.id#" />
I agree with you 100%. I would always say to do the best with what you know at the time. The "good enough" code, as you say, will definitely come back to haunt you.
You touch upon an age old issue with the Obsessive Compulsive Disorder stricken developer. I have to constantly remind myself of this concept of great can become the enemy of good. Or as my personal mantra goes, "perfection is the enemy of completion".
Purist = hem & haw over minutiae.
Pragmatic = getting things done, very little refactoring