Don't Let Great Be The Enemy Of Good

Posted July 16, 2007 at 8:07 AM by Ben Nadel

Tags: Life, Work

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.



Reader Comments

Jul 16, 2007 at 8:40 AM // reply »
15 Comments

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.


Jul 16, 2007 at 8:49 AM // reply »
10,640 Comments

@Brian,

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.


Jul 16, 2007 at 10:50 AM // reply »
160 Comments

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.


Jul 16, 2007 at 10:59 AM // reply »
10,640 Comments

@Dan,

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.


Jul 16, 2007 at 11:12 AM // reply »
160 Comments

@Ben:

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:

select
*
from
myTable
where
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:

select
firstName, lastName, title
from
myTable
where
pkey = <cfqueryparam type="cf_sql_integer" value="#url.id#" />


Jul 16, 2007 at 11:27 AM // reply »
10,640 Comments

@Dan,

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.


Mar 30, 2009 at 2:24 PM // reply »
1 Comments

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


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
InVision App - Prototyping Made Beautiful With Prototyping Tools Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
Feb 10, 2012 at 7:21 PM
jQuery AJAX Strips Script Tags And Inserts Them After Parent-Most Elements
Update! Instead of $(eval(options.insertAfter)).after(data['insertData']); I now use: var ajaxNode = document.createElement('span'); var parent = $(eval(options.insertAfter))[0].parentNode; ... read »
Feb 10, 2012 at 6:18 PM
jQuery AJAX Strips Script Tags And Inserts Them After Parent-Most Elements
encountered this same, what I consider, jQuery bug last week. I'm building a site in which I load some content via AJAX. This content contains Linkedin share button placeholders which Linkedin API ne ... read »
Feb 10, 2012 at 11:30 AM
Cross-Origin Resource Sharing (CORS) AJAX Requests Between jQuery And Node.js
After you understand the concepts here, this is an awesome cheatsheet for enabling CORS in just about anything http://enable-cors.org/ ... read »
JM
Feb 10, 2012 at 9:10 AM
My Safari Browser SQLite Database Hello World Example
@Amy, Here is a very good tutorial on how to use JOIN: http://www.sqltutorial.org/sqljoin-innerjoin.aspx ... read »
Feb 10, 2012 at 4:42 AM
Building A Twitter-Inspired RESTful API Architecture In ColdFusion
This is great, very useful Ben. I spotted a small typo in the api.cgm listing: <cfthrow type="Unauthroized" /> Cheers Stefan ... read »
Feb 9, 2012 at 10:35 PM
CFDirectory Filtering Uses Pipe Character For Multiple Filters (Thanks Steve Withington)
I was wondering if there would be a filter you could apply so that you got everything but what you included in the filter. As in show me all docs that are not a .pdf. ... read »
Feb 9, 2012 at 10:29 PM
Learning ColdFusion 9: Application-Specific Data Sources
@Ben, No offence, but if people were really wanting advanced features they would be using a platform like ASP.NET MVC. CFML is so structurally compromised as a tag-based scripting language that ... read »
Feb 9, 2012 at 10:03 PM
Subversion - Cleanup Failed To Process The Following Paths
@Leviaguirre, do you still have problems with this? ... read »