54

Is it ever a good idea to hardcode values into our applications? Or is it always the right thing to call these types of values dynamically in case they need to change?

Edward
  • 2,149
  • 4
  • 19
  • 24
  • 2
    a config parameter would help you – Gopi Apr 14 '11 at 04:44
  • 58
    You never know when the value of `pi` might change... – Gabe Apr 14 '11 at 04:46
  • @Gabe Good one. Its just that before I hard code a value I cannot help but think twice, or three times...I'm sure there has to be a balance because I have simply not been able to program without hardcoding occasionally. – Edward Apr 14 '11 at 05:22
  • 12
    Man, I guess people like @gabe are the reason this is a "Rule". If you repeat 3.14 in 20 places in your code and then find that you actually need more accuracy, you are screwed. I didn't realize this wasn't obvious. – Bill K Apr 14 '11 at 06:05
  • 19
    That was a little rude, @Bill. @Gabe was clearly joking, but aside from that, the question was about hardcoding vs. config parameters, not using a constant vs. repeat magic numbers in multiple places. – David Conrad Apr 14 '11 at 12:45
  • 1
    Yes, hardcoding can be a good idea sometimes. See the Wikipedia article on the "Softcoding" anti-pattern. – user16764 Apr 14 '11 at 13:51
  • 1
    @Bill K "If you repeat 3.14 in 20 places in your code and then find that you actually need more accuracy, you are screwed. " -- You're screwed if you think that pi=3.14 is acceptable accuracy for anything else than a homework program. – quant_dev Apr 15 '11 at 22:06
  • @user16764 if you are using that single-source article that is more about how you can write bad code in ANY pattern, you should re-evaluate. I'd actually disagree, I've yet to see a time that it's a bad pattern--but you could certainly not know what you are doing and write hard to understand code, and if you did so, people that came after you and couldn't understand it might blame the pattern--but I've seen that kind of complaining about most patterns used by people who didn't understand that the most important thing in writing code is writing for the next human, not the computer. – Bill K Apr 16 '11 at 08:53
  • @BillK That's what `Math.pi()` is for. – ADTC Oct 20 '17 at 21:24
  • 1
    @ADTC which, btw, is hardcoded http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/lang/Math.java#l123 – Mariusz Sakowski Oct 17 '18 at 16:30

14 Answers14

65

Yes, but do make it obvious.

Do:

  • use constants
  • use a descriptive variable name

Don't:

J.K.
  • 13,063
  • 1
  • 40
  • 56
  • 3
    You'll end up using a comment anyway, so a constant or variable with a descriptive name doesn't take any more effort. – JeffO Apr 14 '11 at 02:42
  • On small embedded platforms sometimes you are better off using #define for naming constants - but you need to know your compiler well before making the decision to use constants vs "named numbers" done with the preprocessor. – quickly_now Apr 14 '11 at 03:06
  • @quickly: Completely true. However, I wanted to make my answer as generic as possible by conveying the overall concept, rather than delving into finer specifics. – J.K. Apr 14 '11 at 03:35
  • I would also add "during initial prototyping". They should be moved to constants as soon as you're out of initial prototyping. – jsternberg Apr 14 '11 at 03:36
  • Thanks for the feedback. Yeah every time I took a course or read examples the one writing the code always treated hard coding values as a shortcut but never to be used in production. – Edward Apr 14 '11 at 04:29
  • 1
    though there are exceptions to the *magic number* rule there are none to the *making it obvious* that rule them all !!! – Newtopian Apr 14 '11 at 05:42
  • 51
    Which is cleaner, `diameter = 2 * radius` or `diameter = RADIUS_TO_DIAMETER_FACTOR * radius`? There indeed are corner cases where a magic number may be better solution. – Joonas Pulakka Apr 14 '11 at 05:57
  • @quickly_now: That's mostly a C thing, and even then `enum` is the preferred alternative to `const int`. – MSalters Apr 14 '11 at 08:10
  • I agree with @Joonas. I'd say use a magic number if it is used once or twice (nearby) in your code. It's the same as "three or more -- use a **for**" – Septagram Apr 14 '11 at 09:07
  • 6
    I can't agree with this answer enough. I tend to think of programming like being a novelist. You tell your story through the code and if people cannot understand the logic it makes your code worthless in my opinion. That's why well thought out naming conventions are essentially for readability. Also, there is no good reason to use magic numbers. By using magic numbers you remove the "why" from the equation and make it more difficult to understand. For instance: "diameter = 2 * radius" What is the two for? This "diameter = RADIUS_TO_DIAMETER_FACTOR * radius" makes much more sense. – chrisw Apr 14 '11 at 12:29
  • 12
    diameter = 2 * radius is straight from high school maths. The reason for not naming the "2" is that for it to have a value of anything else would require a change to the laws of physics or maths, or both. (On the other hand, naming Pi, or Plancks constant is a good move for simple readability). – quickly_now Apr 14 '11 at 13:32
  • 1
    I can only imagine how insane a kernel interface _without_ magic numbers would be :) `__syscall(foo, 0x0004)`? Ick :) – Tim Post Apr 14 '11 at 13:38
  • 9
    @Joonas: Pfft. Surely you mean `diameter = radius << 1`? I suppose that could also be `diameter = radius << RADIUS_TO_DIAMETER_BITS_TO_SHIFT`. – Ant Apr 14 '11 at 14:14
  • @Ant: Cool idea! – 700 Software Apr 14 '11 at 14:42
  • 1
    @Ant: Haha :-) Actually, I believe most compilers would optimize it that way - as long as the constant has been defined by compile time! – Joonas Pulakka Apr 14 '11 at 14:56
  • 6
    how 'bout some `diameter = radius.toDiameter()` – Carson Myers Apr 14 '11 at 15:32
  • 1
    @Jonas: Actually, neither of your examples is really appropriate. Instead, the logic should be in a function `GetDiameter(radius)`. Overkill, maybe, but it makes the purpose of the "2" more obvious than a constant does, and will actually reduce the code footprint if you happen to be doing this calculation more than once. – Aaronaught Apr 14 '11 at 17:43
  • "and will actually reduce the code footprint if you happen to be doing this calculation more than once" It won't. And it makes code less readable. – quant_dev Apr 15 '11 at 22:08
  • @CarsonMyers - But in the implementation of `toDiameter()`, you'd have either a "2 * radius" or the bitshift way of doing it. – pasawaya Oct 31 '12 at 05:44
  • 2
    @qegal true, but it would be in a function called `toDiameter(radius)` that would consist of a single expression. In calling code it's obvious that you're getting a radius no matter how you do it, and looking at the function, it's obvious what it's trying to accomplish – Carson Myers Nov 01 '12 at 04:59
  • @Ant: is radius an int? – JBRWilkinson Apr 17 '15 at 21:37
  • @quant_dev: what if GetDiameter() is declared as inline or constexpr? – JBRWilkinson Apr 17 '15 at 21:40
30

What I find odd about this Q&A so far is that nobody has actually attempted to clearly define "hard-code" or, more importantly, the alternatives.

tl;dr: Yes, it is sometimes a good idea to hard-code values, but there's no simple rule as to when; it depends completely on context.

The question does narrow it down to values, which I take to mean magic numbers, but the answer to whether or not they're a good idea is relative to what they're actually used for!

Several examples of "hard-coded" values are:

  • Configuration values

    I cringe whenever I see statements like command.Timeout = 600. Why 600? Who decided that? Was it timing out before, and someone raised the timeout as a hack instead of fixing the underlying performance issue? Or is it actually some known and documented expectation for processing time?

    These shouldn't be magic numbers or constants, they should be externalized in a configuration file or database somewhere with a meaningful name, because their optimal value is determined largely or entirely by the environment that the application is running in.

  • Mathematical formulas

    Formulas usually tend to be pretty static, such that the nature of the constant values inside isn't really particularly important. The volume of a pyramid is (1/3)b*h. Do we care where the 1 or 3 came from? Not really. A previous commenter rightly pointed out that diameter = radius * 2 is probably better than diameter = radius * RADIUS_TO_DIAMETER_CONVERSION_FACTOR - but that is a false dichotomy.

    What you should be doing for this type of scenario is creating a function. I don't need to know how you came up with the formula but I still need to know what it's for. If, instead of any of the nonsense written above, I write volume = GetVolumeOfPyramid(base, height) then suddenly everything becomes a lot clearer, and it's perfectly okay to have magic numbers inside the function (return base * height / 3) because it's obvious that they're just part of the formula.

    The key here is of course to have short and simple functions. This doesn't work for functions with 10 arguments and 30 lines of calculations. Use function composition or constants in that case.

  • Domain/business rules

    This one is always the gray area because it depends on what exactly the value is. Most of the time, it's these particular magic numbers that are candidates for turning into constants, because that makes the program easier to understand without complicating the program logic. Consider the test if Age < 19 vs. if Age < LegalDrinkingAge; you probably can figure out what's going on without the constant, but it's easier with the descriptive title.

    These may also become candidates for function abstraction, for example function isLegalDrinkingAge(age) { return age >= 19 }. The only thing is that often your business logic is a lot more convoluted than that, and it might not make sense to start writing out dozens of functions with 20-30 parameters each. If there isn't a clear abstraction based on objects and/or functions then resorting to constants is OK.

    The caveat is, if you're working for the tax department, it becomes really, really burdensome and honestly pointless to write AttachForm(FORM_CODE_FOR_SINGLE_TAXPAYER_FILING_JOINTLY_FOR_DEPRECIATION_ON_ARMPIT_HAIR). You're not going to do that, you're going to AttachForm("B-46") because every single developer who ever has worked or ever will work there is going to know that "B-46" is the form code for a single taxpayer filing blah blah blah - the form codes are part of the domain itself, they never change, so they're not really magic numbers.

    So you have to use constants sparingly in business logic; basically you have to understand whether or not that "magic number" is actually a magic number or if it's a well-known aspect of the domain. If it's domain, then you don't soft-code it unless there's a really good chance it will change.

  • Error codes and status flags

    These are never okay to hard-code, as any poor bastard who has ever been hit with the Previous action failed due to error code 46 can tell you. If your language supports it, you should be using an enumeration type. Otherwise, you'll usually have an entire file/module full of constants specifying the valid values for a particular error type.

    Don't ever let me see return 42 in an error handler, capiche? No excuses.

I probably left out several scenarios but I think that covers most of them.

So, yeah, it's sometimes acceptable practice to hard code stuff. Just don't be lazy about it; it should be a conscious decision rather than plain old sloppy code.

Aaronaught
  • 44,005
  • 10
  • 92
  • 126
  • Thanks for the good breakdown! - most people don't think through all the options I would add **"Environment Configuration"** - I think these should be avoided (not hard-coded), since most data should be put in a config file or database. This follows the principal of "keeping data and logic separate" that is a mainstay of MVC or MVVM. string TestServerVar = "foo"; string ProdServerVal = "bar"; – m1m1k May 07 '19 at 16:39
9

There are various reasons for assigning an identifier to a number.

  • If the number might change, it should have an identifier. It's much easier to find NUMBER_OF_PLANETS than to search for every instance of 9 and consider whether it should be changed to 8. (Note that user-visible strings might have to change if the software ever has to be used in a different language, and that's a hard thing to predict in advance.)
  • If the number is hard to type in any way. For constants like pi, it's better to give one maximum-precision definition than to retype it in several places, possibly inaccurately.
  • If the number occurs in different places. You shouldn't have to look at two uses of 45 in adjoining functions and wonder if they mean the same thing.
  • If the meaning isn't instantly recognizable. It's safe to assume that everybody knows what 3.14159265... is. It isn't safe to assume that everybody will recognize the gravitational constant, or even pi/2. ("Everybody" here does depend on the nature of the software. Systems programmers can be expected to know the octal representation of Unix permission bits or the like. In naval/marine architecture software, checking the Froude number of a proposed hull and speed to see if it's 1.1 or greater might be perfectly self-explanatory to anybody who should be working on it.)
  • If the context isn't recognizable. Everybody knows there are 60 minutes in an hour, but multiplying or dividing by 60 may be unclear if there's no immediate indications that the quantity is a time value or a rate value.

This gives us criteria for hard-coding literals. They should be immutable, not hard to type, occurring in one place or context only, and with recognizable meaning. There's no point in defining 0 as ARRAY_BEGINNING, for example, or 1 as ARRAY_INCREMENT.

Nathan Tuggy
  • 345
  • 1
  • 6
  • 14
David Thornley
  • 20,238
  • 2
  • 55
  • 82
5

As an addition to other answers. Use constants for strings when possible. Of course, you don't want to have

const string server_var="server_var";

but you should have

const string MySelectQuery="select * from mytable;";

(assuming you actually have a query where you want to get all the results from a specific table, always)

Other than that, use constants for any number other than 0 (usually). If you need a permission bitmask of 255, don't use

const int 8th_bit=255; //or some other obscure naming scheme that equates to 255.

instead use

const int AllowGlobalRead=255;

Of course, along with constants, know when to use enumerators. The above case would probably fit well in one.

Earlz
  • 22,658
  • 7
  • 46
  • 60
  • typedef enum {state_0 = 0, state_1 = 1, state_2 = 2, ...}... Don't laugh, I've seen it done. Smack that person around the head with a wet fish! – quickly_now Apr 14 '11 at 03:04
  • @quickly well of course you'd want something more like `typedef enum {init_state=0, parse_state=1, evaluation_state=2, ... }` – Earlz Apr 14 '11 at 03:10
  • 6
    THIS_NAMING_CONVENTION_IS_RECOMMENDED_FOR_CONSTANTS – StuperUser Apr 14 '11 at 12:20
  • 4
    For strings, you don't just want constants. You want to put any user-visible strings into some sort of resource file (details will depend on your platform) so you can change to another language easily. – David Thornley Apr 14 '11 at 13:45
  • You might also want to stick business-logic-related strings (like SQL queries) in a resource file with some kind of encryption or obfuscation. That will prevent "curious" users from reverse-engineering your logic (or database schema). – TMN Apr 14 '11 at 15:09
  • @Stuper yea, I actually usually follow that convention. For some reason didn't in this answer though – Earlz Apr 14 '11 at 22:43
5

It depends what you consider hardcoding. If you try to avoid any and all hardcoded things, you end up in softcoding territory, and make a system that only the creator can manage (and that's the ultimate hardcode)

Plenty of things are hardcoded in any reasonable framework and they work. i.e. there's no technical reason why I shouldn't be able to change the entry point of a C# application (static void Main), but hardcoding that does not create any problems for any user (except the occasional SO question)

The rule of thumb I use is that anything that can and will change, without affecting the state of the whole system, should be confugurable.

So, IMHO, it's silly not to hardcode things that are never changing (pi, gravitational constant, a constant in a mathematical formula - think volume of a sphere).

Also it's silly not to hardcode things or processes that will have an impact on your system that will require programming in any instance, i.e. it's wastefull to allow the user to add dynamic fields to a form, if any added field would require the maintenance developer to go in and write some script that will make that thing to work. Also it's stupid (and I've seen it a few times in enterprise environments) to create some configuration tool, so nothing is hardcoded, yet, only the developers in the IT department can use it, and it's only slighty easier to use it than to do it in Visual Studio.

So, bottom line, whether a thing should be hardcoded is a function of two variables:

  • will the value change
  • how will a change in the value affect the system
SWeko
  • 261
  • 1
  • 6
4

Is it ever a good idea to hardcode values into our applications?

I hardcode values only if the values are specified in the Specification (on a final release of the specification), e.g. The HTTP OK response will always be 200 (unless it changes in the RFC), so, you will see (in some of my codes) constants like:

public static final int HTTP_OK = 200;

Otherwise, I store constants in the properties file.

The reason why I specified specifications, is that changing constants in specifications requires change management, in which, the stakeholders will review the change and approve/disapprove. It never happens overnight and takes months/years for an approval. Don't forget that many developers uses specifications (e.g. HTTP) so changing it means breaking millions of systems.

Buhake Sindi
  • 830
  • 9
  • 16
3
  • if the value can change, and indeed might change, then soft-code it whenever possible as long as the effort involved does not exceed the expected return
  • some values cannot be soft-coded; follow Jonathan's guidelines in those (rare) cases
Steven A. Lowe
  • 33,808
  • 2
  • 84
  • 151
3

I've noticed that any time you can extract data from your code, it improves what's left. You start noticing new refactorings and improving whole sections of your code.

It's just a good idea to work towards extracting constants, don't consider it some stupid rule, think about it as an opportunity to code better.

The biggest advantage would be the way you might find similar constants being the only difference in groups of code--abstracting them into arrays has helped me reduce some files by 90% of their size and fix quite a few copy & paste bugs in the meantime.

I've yet to see a single advantage to not extracting data.

Bill K
  • 2,699
  • 18
  • 18
2

I recently coded a MySQL function to properly calculate the distance between two lat/long pairs. You can't just do pythagorus; longitude lines get closer together as latitude increases toward the poles, so there's some kinda hairy trig involved. Point is, I was pretty torn about whether to hard-code the value representing the earth's radius in miles.

I ended up doing it, even though the fact is, lat/lng lines are much closer together on, say, the moon. And my function would drastically underreport distances between points on Jupiter. I figured the odds of the website I'm building having an extraterrestrial location get entered is pretty slim.

Dan Ray
  • 9,106
  • 3
  • 37
  • 49
1

Well it depends if your language is compiled. If it's not compiled, it's not a big deal, you just edit the source code, even if it will be slightly delicate for a non programmer.

If you are programming with a compiled language, this is clearly not a good idea, because if the variables change, you have to recompile, which is a big waste of time if you want to adjust this variable.

You don't need to make some slider or interface to dynamically change his variable, but the least you could do is a text file.

For example with my ogre project, I'm always using the ConfigFile class to load a variable I have written to a config file.

jokoon
  • 2,262
  • 3
  • 19
  • 27
1

Two occasions where constants are (in my opinion at least) OK:

  1. Constants that relate to nothing else; you can change those constants whenever you like without having to change anything else. Example: The default width of a grid column.

  2. Absolutely immutable, precise, obvious constants, like "number of days per week". days = weeks * 7 Replacing 7 with a constant DAYS_PER_WEEK hardly provides any value.

user281377
  • 28,352
  • 5
  • 75
  • 130
0

I do agree completely with Jonathan but as all rules there are exceptions...

"Magic number in the spec: Magic number in the code"

Basically states that any magic numbers that remains in the spec after reasonable attempts to get descriptive context for them should be reflected as such in the code. If magic numbers remain in the code every efforts should be made to isolate them and make them clearly linked to their point of origin.

I have performed a few interfacing contracts where it is necessary to populate messages with values mapped from the database. In most cases the mapping is fairly straight forward and would fit in Jonathan's general guide lines but I have encountered cases where the target message structure was just plain awful. More than 80% of the values that had to be passed down in the structure were constants enforced by the specification of the distant system. this coupled with the fact that the message structure was gargantuan made that a LOT of such constants had to be populated. In most cases they did not provide a meaning or reason, just said "put M here" or "put 4.10.53.10100.889450.4452 here". I did not attempt either to put a comment next to all of them it would have rendered the resulting code unreadable. I did however make sure the code sections where these magic values appear are properly isolated and that their containers (classes, packages) named appropriately to point directly to the specification enforcing them.

That said, when you think about it... it's pretty much all about making it obvious...

Newtopian
  • 7,201
  • 3
  • 35
  • 52
0

If you're hardcoding the value of the earth's gravitational constant, noone's going to care. If you hardcode the IP address of your proxy server, you're in for trouble.

jwenting
  • 9,783
  • 3
  • 28
  • 45
  • 1
    You might need more precision for earth's gravitational constant, so hardcoding it several times might lead to problems. – user281377 Apr 14 '11 at 12:24
  • 1
    Peter Noone? From Herman's Hermits? – David Conrad Apr 14 '11 at 12:48
  • The gravitational acceleration on the Earth is pretty much 9.81 m/s^2 for most latitudes and altitudes (of course, if you're searching for oil underground, or shooting ICBMs over the North Pole, knowing the variation in gravity is very important to a lot more decimal places), with the gravitational acceleration on other planets being a different number, but as far as I know, the gravitational constant is constant around the universe. There is a lot of physics that would have to change if g were variable. – Tangurena Apr 14 '11 at 18:31
0

Mostly no, but I think that is worth noting that you will have the most problems when you start duplicating the hard-coded value. If you don't duplicate it (ex. use it just once in the implementation of a class) then not using a constant might be alright.