views:

1316

answers:

21

The code base I'm currently working on is littered with hard-coded values.

I view all hard coded values as a code smell and I try to eliminate them where possible...however there are some cases that I am unsure about.

Here are two examples that I can think of that make me wonder what the best practice is:

1. MyTextBox.Text = someCondition ? "Yes" : "No"
2. double myPercentage = myValue / 100;

In the first case, is the best thing to do to create a class that allows me to do MyHelper.Yes and MyHelper.No or perhaps something similar in a config file (though it isn't likely to change and who knows if there might ever be a case where its usage would be case sensitive).

In the second case, finding a percentage by dividing by 100 isn't likely to ever change unless the laws of mathematics change...but I still wonder if there is a better way.

Can anyone suggest an appropriate way to deal with this sort of hard coding? And can anyone think of any places where hard coding is an acceptable practice?

+4  A: 

The better way for your second example would be to define an inline function:

double getpercentage(double myValue)
{
   return(myValue / 100);
}

...

double myPercentage = getpercentage(myValue);

That way it's a lot more obvious what you're doing.

Colen
+6  A: 

The first case will kill you if you ever need to localize. Moving it to some static or constant that is app-wide would at least make localizing it a little easier.

ctacke
Yeah but there's probably a million of strings through that app's code that that would apply to. Localization would be a project in-and-of-itself. So unless he wants to do the whole shebang, I think what he has is fine.
Doug T.
I agree with Doug -- localization is hard, so you need to decide up front if you want to invest considerable effort for something you might do someday, and will have to work hard at even then; or whether you will simply defer all the cost to later.
Rob Walker
You also have cases where you may change the language of an app to be in the semantics of the user, so it may stay in English and most text stays, but some is changed to match their business nomenclature. Yes/No may not change, but things like 'customer' might. This would be a case to look at.
ctacke
+1  A: 

I tend to view it in terms of the project's scope and size.

Some simple projects that I am a solo dev on? Sure, I hard code lots of things. Tools I write that only I will ever use? Sure, if it gets the job done.

But, in working on larger, team projects? I agree, they are suspect and usually the product of laziness. Tag them for review and see if you can spot a pattern where they can be abstracted away.

In your example, the text box should be localizable, so why not a class that handles that?

Genericrich
+2  A: 

I don't think that your second is really an example of hardcoding. That's like having a Halve() method that takes in a value to use to divide by; doesn't make sense.

Beyond that, example 1, if you want to change the language for your app, you don't want to have to change the class, so it should absolutely be in a config.

Hard coding should be avoided like Dracula avoids the sun. It'll come back to bite you in the ass eventually.

jcollum
+13  A: 

And can anyone think of any places where hard coding is an acceptable practice?

  • Small apps
  • Single man projects
  • Throw aways
  • Short living projects

For short anything that won't be maintained by others.

Gee I've just realized how much being maintainer coder hurt me in the past :)

OscarRyz
I think this is only valid for code that you are building for yourself; if you're at work, you will eventually have a new job and someone may need to dig in to your code and figure out what you were doing with these hard-coded values.
jcollum
I generally agree.. though "throw aways" have been known to become full fledged production apps ("hey, we'll use it for now, don't worry, we'll have a rewrite..."); so be sure they really are "throw aways."
Giovanni Galbo
It's funny how "short-lived" projects end up living more than... well, shortly.Does hard-coding really save time, even in these cases? I generally lean to no.
Reuben
I agree with Reuben. Small apps tend to grow. Throw aways tend to get recycled. Short-lived projects extend. It's still not worth hard-coding.
ctacke
I've selected this answer because it does answer my question. His points are valid...especially about throw away apps...as long as they stay that way. Obviously if there is even the slightest chance that anyone else will work on the app then hard coding should be avoided.
mezoid
Ugh, "single man" projects? So you're expected to remember the significance of some arbitrary magic number three months down the line? Perhaps a better summary would be, "anything that won't be maintained by anyone, ever again. Because it can't be."
Rob
A: 

For the first value, it really depends. If you don't anticipate any kind of wide-spread adoption of your application and internationalization will never be an issue, I think it's mostly fine. However, if you are writing some kind of open source software or something with a larger audience consider the fact that it may one day need to be translated. In that case, you may be better off using string resources.

Kamil Kisiel
+1  A: 

Remember that you WILL forget the meaning of any non-obvious hard-coded value.

So be certain to put a short comment after each to remind you.

A Delphi example:

Length := Length * 0.3048; { 0.3048 converts feet to meters }

lkessler
And then you have to a) find all hard coded values of pi and b) recompile when you need 5 digits of precision after the decimal. Not very flexible.
jcollum
Well, perhaps Pi is a bad example. I mean, who doesn't recognize it right away?
DrJokepu
You're right. I'm changing the example.
lkessler
That one makes more sense.
jcollum
I would still make this a constant. Sure, it's utterly fixed but you might want to search for it or you might change precision.
Loren Pechtel
If I programmed for all of the things I might do, I'd never get anything done.
SnOrfus
If you waste time to describe it in a comment, you could have spent the same time documenting it as a constant.
trinithis
+6  A: 

Case 1: When should you hard-code stuff: when you have no reason to think that it will ever change. That said, you should NEVER hard code stuff in-line. Take the time to make static variables or global variables or whatever your language gives you. Do them in the class in question, and if you notice that two classes or areas of your code share the same value FOR THE SAME REASON (meaning it's not just coincidence), point them to the same place.

Case 2: For case case 2, you're correct: the laws of "percentage" will not change (being reasonable, here), so you can hard code inline.

Case 3: The third case is where you think the thing could change but you don't want to/have time to bother loading ResourceBundles or XML or whatever. In that case, you use whatever centralizing mechanism you can -- the hated Singleton class is a good one -- and go with that until you actually have need to deal with the problem.

The third case is tricky, though: it's extraordinarily hard to internationalize an application without really doing it... so you will want to hard-code stuff and just hope that, when the i18n guys come knocking, your code is not the worst-tasting code around :)

Edit: Let me mention that I've just finished a refactoring project in which the prior developer had placed the MySql connect strings in 100+ places in the code (PHP). Sometimes they were uppercase, sometimes they were lower case, etc., so they were hard to search and replace (though Netbeans and PDT did help a lot). There are reasons why he/she did this (a project called POG basically forces this stupidity), but there is just nothing that seems less like good code than repeating the same thing in a million places.

Yar
+1  A: 

It's okay as long as you don't do refactoring, unit-testing, peer code reviews. And, you don't want repeat customers. Who cares?

yogman
+8  A: 

It's never good and you just proved it...

double myPercentage = myValue / 100;

This is NOT percentage. What you wanted to write is :

double myPercentage = (myValue / 100) * 100;

Or more correctly :

double myPercentage = (myValue / myMaxValue) * 100;

But this hard coded 100 messed with your mind... So go for the getPercentage method that Colen suggested :)

double getpercentage(double myValue, double maxValue)
{
   return (myValue / maxValue) * 100;
}

Also as ctacke suggested, in the first case you will be in a world of pain if you ever need to localize these literals. It's never too much trouble to add a couple more variables and/or functions

Diadistis
myValue is assumed to be a fractional value, obviously, from context.
Justice
First of all I wanted to show that it isn't clear but even for fractional you would divide with the max value which might also be correct in this specific case but not always...
Diadistis
+2  A: 

The text for the conditions should be in a resource file; that's what it's there for.

Chris Lively
+11  A: 

The real question isn't about hard coding, but rather repetition. If you take the excellent advice found in "The Pragmatic Programmer", simply Don't Repeat Yourself (DRY).

Taking the principle of DRY, it is fine to hardcode something at any point. However, once you use that particular value again, refactor so this value is only hardcoded once.

John Fisher
A: 

I once had a boss who refused to not hardcode something because in his mind it gave him full control over the software and the items related to the software. Problem was, when the hardware died that ran the software the server got renamed... meaning he had to find his code. That took a while. I simply found a hex editor and hacked around it instead of waiting.

Nazadus
+2  A: 

no.

What is a simple throw away app today will be driving your entire enterprise tomorrow. Always use best practices or you'll regret it.

justin.m.chase
+9  A: 

Of course hard-coding is sometimes acceptable. Following dogma is rarely as useful a practice as using your brain.

(For an example of this, perhaps it's interesting to go back to the goto wars. How many programmers do you know that will swear by all things holy that goto is evil? Why then does Steve McConnell devote a dozen pages to a measured discussion of the subject in Code Complete?)

Sure, there's a lot of hard-gained experience that tells us that small throw-away applications often mutate into production code, but that's no reason for zealotry. The agilists tell us we should do the simplest thing that could possibly work and refactor when needed.

That's not to say that the "simplest thing" shouldn't be readable code. It may make perfect sense, even in a throw-away spike to write:

const MAX_CACHE_RECORDS = 50
foo = GetNewCache(MAX_CACHE_RECORDS)

This is regardless of the fact that in three iterations time, someone might ask for the number of cache records to be configurable, and you might end up refactoring the constant away.

Just remember, if you go to the extremes of stuff like

const ONE_HUNDRED = 100
const ONE_HUNDRED_AND_ONE = 101

we'll all come to The Daily WTF and laugh at you. :-)

Think! That's all.

Dominic Cronin
I agree. Anytime it seems something should be hard coded, I make it a constant. Then when you look back you can see what it means. EARTH_RADIUS is a lot clearer than 3950 in calculations.
null
A: 

Hard coding should be banned forever. Althought in you very simple examples i don't see anything wrong using them in any kind of project.

In my opinion hard coding is when you believe that a variable/value/define etc. will never change and create all your code based on that belief.

Example of such hard coding is the book Teach Yourself C in 24 Hours that everybody should avoid.

+1  A: 

Code always evolves. When you initially write stuff hard coding is the easiest way to go. Later when a need arrives to change the value it can be improved. In some cases the need never comes.

The need can arrive in many forms:

  1. The value is used in many places and it needs to be changed by a programmer. In this case a constant is clearly needed.

  2. User needs to be able to change the value.

I don't see the need to avoid hard coding. I do see the need to change things when there is a clear need.

Totally separate issue is that of course the code needs to be readable and this means that there might be a need for a comment for the hard coded value.

iny
A: 

I normally add a set of helper methods for strings and numbers.

For example when I have strings such as 'yes' and 'no' I have a function called __ so I call __('yes'); which starts out in the project by just returning the first parameter but when I need to do more complex stuff (such as internationaizaton) it's already there and the param can be used a key.

Another example is VAT (form of UK tax) in online shops, recently it changed from 17.5% to 15%. Any one who hard coded VAT by doing:

$vat = $price * 0.175;

had to then go through all references and change it to 0.15, instead the super usefull way of doing it would be to have a function or variable for VAT.

In my opinion anything that could change should be written in a changeable way. If I find myself doing the same thing more than 5 times in the same day then it becomes a function or a config var.

stuartloxton
A: 

"hardcoding" is the wrong thing to worry about. The point is not whether special values are in code or in config files, the point is:

  • If the value could ever change, how much work is that and how hard is it to find? Putting it in one place and referring to that place elsewhere is not much work and therefore a way to play it safe.
  • Will maintainance programmers definitely understand why the value is what it is? If there is any doubt whatsoever, use a named constant that explains the meaning.

Both of these goals can be achieved without any need for config files; in fact I'd avoid those if possible. "putting stuff in config files means it's easier to change" is a myth, unless either

  • you actually want to support customers changing the values themselves
  • no value that could possibly be put in the config file can cause a bug (buffer overflow, anyone?)
  • your build and deployment process sucks
Michael Borgwardt
A: 

Hardcoded literals should appear in unit tests for the test values, unless there is so much reuse of a value within a single test class that a local constant is useful.

The unit tests are a description of expected values without any abstraction or redirection. Imagine yourself reading the test - you want the information literally in front of you.

The only time I use constants for test values is when many tests repeat a value (itself a bit suspicious) and the value may be subject to change.

I do use constants for things like names of test files to compare.

Andy Dent
In the book xUnit Test Patterns hard coding in tests is listed as a test smell that leads to obscure tests that are difficult to maintain because a maintainer will be unsure if the hard coded value is vital to the success of the test. ie does the method take "abc" or is any string valid for the test
mezoid
I mostly use hardcoded literals for comparison with results, either coming from a function (eg: list of tables) or matching a value input - the genre of "do I get back value X after storing it in the system?" tests. Yes, a comment may be necessary - just think:"test == documenting intent"
Andy Dent
A: 

Not normally (Are hard-coding literals acceptable)

Another way at looking at this is how using a good naming convention for constants used in-place of hard coded literals provides additional documentation in the program.

Even if the number is used only once, it can still be hard to recognized and may even be hard to find for future changes.

IMHO, making programs easier to read should be second nature to a seasoned software professional. Raw numbers rarely communicate meaningfully.

The extra time taken to use a well named constant will make the code readability (easy to recall to the mind) and useful for future re-mining (code re-use).

John Burley