My Secret Life as a Spaghetti Coder
home | about | contact | privacy statement
This post at Worse Than Failure made its rounds today on the Yahoo pragprog group and CFCDev mailing list, and I had a response to one of the emails that I also thought was worth blogging. On pragprog, the discussion was turning into the question, "where do you draw the line on knowing when to eliminate literals?" (not a direct quote) Someone brought up the idea to use YAGNI and DRY as guiding factors: "If you need the number in just one place, just use the number there. YAGNI," and "If you find the number being repeated so that you would have to change it in several places, then externalise it so that I change in just one place is needed. DRY."

Initially, that struck me as an idea worth exploring, since those are two of my most-used, favorite, and life-saving principles (I mean, try violating them over and over for years and see if you don't feel like dying!). In fact, I use them a lot in determining when to create a new method (I use other heuristics as well, such as readability, which is often the most important reason I create a function ... more here about some reasons for creating methods). But, I thought about it some and came to this conclusion I posted to the pragprog group (which I changed a bit for here to make more sense):

In essence, I'm not comfortable with either of those definitions (DRY or YAGNI) as lines for determining when you are soft or hard coding. Suppose the following (generalizing to your pleasure -- since I'm having trouble writing it, I'm sure others will have trouble understanding it, as no one would ever (I think) write an application this way)
  1. it always costs the same to ship each item: 5.00 (units of currency)
  2. the company only needs to worry about one tax rate: 5%
  3. the product costs 100 dollars each, and there is only one product.
  4. customers can buy a variable quantity of this item (called "quantity" below)
  5. there is a handling charge of 3.14 (units of currency) for each item.
Then your total_cost = (100+5+3.14)*(1.0+5/100)*quantity.

We see 100 twice here. Do we pull it out? What do we name it? oneHundred? That is the only one that makes sense for both cases. Or we could change it to to get rid of calculating the percentage: total_cost = (100+5+3.14)*(1.05)*quantity.

I'm not even confident I've got the right formula - and I'm the one making this up. What happens down the line if the state changes the sales tax? Am I sure I know which number to manipulate? Here, it may look clear, but it may not be the case in other situations. And then when I need to do a circleOperation with crappyApproximationOfPi = 3.14 (the product is cylindrical, and we need to know about how much ribbon we need to wrap the package when someone selects the gift wrapping option), who gets the naming rights?

If there is a line that should be drawn (and I'm not convinced there is), and there exists a place to put it, I don't think the DRY or YAGNI principles have anything to do with its placement. Readability is the key for me, and I don't know to what degree that can be quantified.

One in particular I dislike is when people have uncommented literals like 0x0032aBlahBlahBlah in the code. How (and why) on Earth would you expect anyone to know what that referred to? Will you remember the next time you look at it? I wouldn't, but my brain may just be a sieve.

Your thoughts on where to draw the line? (Or not draw it?... Or tell me I'm wrong?)

Hey! Why don't you make your life easier and subscribe to the full post or short blurb RSS feed? I'm so confident you'll love my smelly pasta plate wisdom that I'm offering a no-strings-attached, lifetime money back guarantee!


Comments
Leave a comment

surely
total_cost = (product_cost+postage+handling)*(tax)*quantity
you never need to worry about remembering what 5, 3.14 and 1.05 actually are

Posted by duncan on Apr 13, 2007 at 06:03 AM UTC - 5 hrs

Of course, that's how /I/ would do it! (in fact, I would have assumed that most people would do it that way) =)

But, if I were to be pedantic, I might rename "tax" as "taxrate" and spell out the calculation a bit more (since even taxrate does not quite describe taxRate+1 and what its putpose is).. Or I might come up with some other name for it (I don't like "tax" alone because to me, it implies the amount of the tax, not its rate.

Posted by Sam on Apr 13, 2007 at 07:02 AM UTC - 5 hrs

Although I've never spent long hours pondering it, I suppose I work on a common sense basis.

General Rules:
1. If I need to use it more than once, make it a variable.
2. If I can foresee any plausible condition where the value might change, I'll pull it out - even if I'm only using it once. It's just easier to find and change that way.
3. If I can foresee any plausible condition where I might need to use the value in another location all together, I'll also pull it out. that way I don't have to do it later. This is merely an attempt to avoid the pain later on.

Acceptable violations:
1. If I need it more than once and the other two rules don't come into play, but all of the uses are highly localized, it may be okay to hard code it.

Any variables I "soft code" simply for the sake of not hard coding are initialized in a group at the top of of the file, function, etc. I know where they are and can access them quickly if I need to make any changes.

Posted by Rob Wilkerson on Apr 13, 2007 at 07:22 AM UTC - 5 hrs

I guess I like "encapsulate what changes". Of course, this makes for a judgment call. Most of those individual values seem subject to change. The formula for them may not be.

Then again, DRY comes into play the second time you type the same formula - maybe time to make it a function.

I find that a good test is copy/paste. If I find myself tempted to copy and paste some code, it is time to figure out why I want to do that (may still be a good idea, but still worth considering).

Posted by Steve Bryant on Apr 13, 2007 at 10:56 AM UTC - 5 hrs

Leave a comment

Leave this field empty
Your Name
Email (not displayed, more info?)
Website

Comment:

Subcribe to this comment thread
Remember my details
Google
Web CodeOdor.com

Me
Picture of me

Topics
.NET (19)
AI/Machine Learning (14)
Answers To 100 Interview Questions (10)
Bioinformatics (2)
Business (1)
C and Cplusplus (6)
cfrails (22)
ColdFusion (78)
Customer Relations (15)
Databases (3)
DRY (18)
DSLs (11)
Future Tech (5)
Games (5)
Groovy/Grails (8)
Hardware (1)
IDEs (9)
Java (38)
JavaScript (4)
Linux (2)
Lisp (1)
Mac OS (4)
Management (15)
MediaServerX (1)
Miscellany (76)
OOAD (37)
Productivity (11)
Programming (168)
Programming Quotables (9)
Rails (31)
Ruby (67)
Save Your Job (58)
scriptaGulous (4)
Software Development Process (23)
TDD (41)
TDDing xorblog (6)
Tools (5)
Web Development (8)
Windows (1)
With (1)
YAGNI (10)

Resources
Agile Manifesto & Principles
Principles Of OOD
ColdFusion
CFUnit
Ruby
Ruby on Rails
JUnit



RSS 2.0: Full Post | Short Blurb
Subscribe by email:

Delivered by FeedBurner