views:

111

answers:

7

In theory, source code should not contain hardcoded values beyond 0, 1 and the empty string. In practice, I find it very hard to avoid all hardcoded values while being on very tight delivery times, so I end up using a few of them and feeling a little guilty.

How do you reconcile avoiding hardcoded values with tight delivery times?

+1  A: 

This comes with a little bit of planning, in most cases it is as simple as having a configuration file, or possibly a database table that stores critical configuration items. I don't find that there is any reason that you "have" to have hard coded values, and it shouldn't take you much additional time to offload to a configuration mechanism to where tight time lines would be a valid excuse.

Mitchel Sellers
+2  A: 

The problem of hardcoded values is that sometimes it's not obvoius that particular code relies on them. For example, in java it is possible to move all constants into separate interface and separate particular constants into inner sub-interfaces. It's quite convenient and obvious. Also it's easy to find the constant usage just by using IDE facilities ("find usage" functionality) and change or refactor them.

Here's an example:

public interface IConstants {

    public interface URL {
        String ALL = "/**";
    }

    public interface REST_URL {
        String DEBUG = "/debug";
        String SYSTEM = "/system";
        String GENERATE = "/generate";
    }
} 

Referencing is quite human readable: IConstants.REST_URL.SYSTEM

igorp1024
Why interface ?
Svish
As an example. BTW, the advantage over class is that it's not possible to instantiate it.
igorp1024
+1  A: 

To avoid hard-coding you should

  • use configuration files (put your values in XML or ini-like text files).
  • use database table(s) to store your values.

Of course not all values qualify to be moved to a config file. For those you should use constructs provided by the programming language such as (constants, enums, etc).

Just saw an answer to use "Constatn Interface". With all due respect to the poster and the voters, but this is not recommended. You can read more about that at:

http://en.wikipedia.org/wiki/Constant_interface

del.ave
Final class (as shown as example in wikipedia) will not allow you to implement inner structures of constants and you'll end up with one heavy class with a mixture of the variety of constants.
igorp1024
And wikipedia tells that since java5 using static imports it's no longer considered as anti-pattern :) Just use static imports.
igorp1024
+1  A: 

Most non-trivial enterprise-y projects will have some central concept of properties or configuration options, which already takes care of loading up option from a file/database. In these cases, it's usually simple (as in, less than 5 minutes' work) to extend this to support the new propert(ies) you need.

If your project doesn't have one, then either:

  • It could benefit from one - in which case write it, taking values from a flat .properties file to start with. This shouldn't take more than an hour, tops, and is reusable for any config stuff in future
  • Even that hour would be a waste - in which case, you can still hav a default value but allow this to be overridden by a system property. This require no infrastructure work and minimal time to implement in your class.

There's really no excuse for hardcoding values - it only saves you a few minutes at most, and if your project deadline is measured in minutes then you've got bigger problems than how to code for configurability.

Andrzej Doyle
+1  A: 

Admittedly, I hardcode a lot of stuff at my current hobby project. Configuration files are ridiculously easy to use instead (at least with Python, which comes with a great and simple .cfg parser), I just don't bother to use them because I am 99% confident that I will never have to change them - and even if that assumption proved false, it's small enough to refactor it with reasonable effort. For annything larger/more important, however, I would never type if foo == "hardcoded bar", but rather if foo == cfg.bar (likely with a more meaningful name for cfg). Cfg is a global singleton (yeah, I know...) which is fed the .cfg file at startup, and next time some sentinel value changes, you change the configuration file and not the source.

With a dynamic/reflective language, you don't even need to change the part loading the .cfg when you add another value to it - make it populate the cfg object dynamically with all entries in the file (or use a hashmap, for that matter) and be done.

delnan
+1  A: 

2 suggestions here: First, if you are working on embedded system using language like C. Simply work out a coding convention to use a #define for any string or constant. All the #define should be categorized in a .h file. That should be enough - not too complex but enough for maintainability. You don't need to mangle all the constant between the code line.

Second, if you are working on a application with access to DB. It is simple just to keep all the constant values in the database. You just need a very simple interface API to do the retrieval.

With simple tricks, both methods can be extended to support multi-language feature.

ttchong
+1  A: 

The assumption behind the question seems to me invalid.

For most software, configuration files are massively more difficult to change that source code. For widely installed, software, this could easily be a factor of a million times more difficult: there could easily be that many files hanging round on user installations which you have little knowledge and no control over.

Having numeric literals in the software is no different from having functional or algorithmic literals: it's just source code. It is the responsibility of any software that intends to be useful to get those values right.

Failing that make them at least maintainable: well named and organised.

Making them configurable is the kind of last-ditch compromise you might be forced into if you are on a tight schedule.

soru
Selected this as the best answer because it accounts for the tight delivery times better.Making a configuration scheme for specific and occasional values is too costly. Not only you have to make the structure flexible enough to account for changing or interrelating requirements, you have to make a maintenace interface for the user to keep it truly configurable.When you get fixed time and resources, it isn't wise to expand the requirements. I can live with the guilt as long as the most important global values are user configurable.
ASalazar