4

I come from a background where using a configuration file for every, if not every, constant is the best solution for maintainability and flexibility of the program. By this I mean, every hard coded string, integer, table/array, boolean, color, formatting expression, etc. are all put in one file or class (often called the "Configuration" class).

A big benefit to this solution is that is future proofs "accidental" code changes that can introduce new "features" when a main class or code block is modified. I find that it gets developers out of code areas that should not be touched without really thinking about it. It also makes a code in a main class or section much more readable and coherent (see below):

if (x == 5)
{
    // Logic here
}

Versus

if (x == Config.MaxNumberOfResults)
{
    // Logic here
}

the later being MUCH more readable and coherent (especially in the future) and requires little to no comments to maintain as well as no logic needs rewriting if we decide we want a higher max of results.

The issue with the former code is that some other developer would eventually figure out that 5 is the max result limit and then think I want something different than that so (a few attempts later) they include that number (because god-forbid changing the number) thus putting >= now so the entire code block changes...which may introduce a "feature" somewhere else later on down the line. Using the configuration method would result in most developers never even touching the main logic (usually).

The problem is that my boss likes the idea, but wants to leave some constants in main code files even if they are only used once (i.e. that 5 or max result is only used once (right there), so does it really make sense to put a reference to it from another class/file?) I, of course, think so because of the aforementioned reasons as well as it is just cleaner and more coherent code.

Is my thinking more inline with correct coding conventions/methodologies or is my boss'?

I am fine with doing it his way, but it just feels like it will come back to haunt me later on down the road.

2 Answers 2

5

One thing to consider is that by introducing a Config class you introduce additional dependencies into your code. Many, if not all of your classes will depend on this Config class. (Such a class is sometimes called a dependency magnet.) Even a class that uses only a single constant from the Config class basically has access to all of them. This is the opposite of encapsulation. Depending on your IDE it will also be hard to find out which constant is used by which classes.

To reduce dependencies and to improve encapsulation, I suggest the following:

  1. If the specific constant value if essential for the algorithm and it makes no sense to modify it, just use the value wherever needed and don't define anything. Example: Calculating a cross product only works in 3 dimensions. So just write "3" wherever needed. Don't declare NumberOfDimensions=3 because this would give the impression that this value can be modified.

  2. If a constant is only used in one function or class and it is unlikely that it will ever be used somewhere else, declare it locally or as a class attribute. This also works for class hierarchies if you put the constants into the base class.

  3. If it is used by multiple related classes (a module) that do not have a common base class, declare a module specific Config class.

  4. If the constant is really needed by almost all of your classes, then put it into your global Config class. I believe that this is relatively rare case. An example would be a log file name and log level.

3
  • I disagree. Config is not adding more than a single file dependency (which is nothing). Giving access to the config in all classes is not worry-some since in order to use the config class, a reference must be explicitly stated and all fields are declared readonly (or const) in the config class, so public access is not really an issue. The rest is just putting the config one level of abstraction deeper that just a global config class. Because now, you would have separate "mini" config sections in each class which would be a pain to maintain. Module level config classes are the same thing too.
    – G.T.D.
    Jan 15, 2017 at 22:08
  • Encapsulation becomes more of a hinderance as projects get bigger. Making everything modularized is a nice idea, but it becomes impossible to maintain long term since there are so many small level details that must be modified on each new deployment or implementation of that module. Think of having 100+ classes that interact with each other, and each has their own "config" section or every 5~10 have a module config...that will be impossible to maintain or bring over to another project if need be. Centralizing and standardizing to a single global config is cleaner, flexible, and scalable IMHO.
    – G.T.D.
    Jan 15, 2017 at 22:15
  • I am aiming for a more project level scope encapsulation which is more maintainable and scalable in the long term as well flexible when the project needs to be altered in a different variation. Everything working together in a project is not horrible as long as you are disciplined enough not to do something stupid. It is actually very easy to work with when you do not want to rewrite or figure out what was originally written. Going back to my main point of preventing code from being changed or rewritten after the fact. I have found, well over 95% of the time, code does not need to be retouched
    – G.T.D.
    Jan 15, 2017 at 22:21
5

You're asking us to choose between two unnecessary evils.

Give numbers meaningful names. A configuration file can do this but is not required. Local constants, injectable or not, can give them names as well. There is no good excuse to let magic numbers run around naked. Context can make the meaning seem obvious but context can change. Favor readability.

One configuration file to rule them all is a doomed plan on anything but the most trivial projects. Give each configuration file a good name that makes clear what does and does not belong in it.

There is no substitute for taking the time to give things good names.

4
  • Thanks for your answer. I am just giving the scenario I am currently in. I prefer the "one config to rule them all" approach because everything is centralized in one place with no "hunting" for where is this constant used (named or not) through several files/classes/etc. I know that everything is in 1 place so there is no guessing game or hunting game. Why is the "one config to rule them all" doomed to fail? Just curious
    – G.T.D.
    Jan 16, 2017 at 1:16
  • That works exactly as well as keeping everything in one drawer in the kitchen. Jan 16, 2017 at 1:18
  • Have you ever lost anything in the kitchen that way? I mean I get what you are saying, but I don't see how it would be bad. If the config is organized (i.e. all the fields are grouped by what class/module they pertain to) then there is really nothing wrong. Also, it is more concise to put notes and various instructions about changing certain values which affect other things without making the main logic over populated with comments about a single or few options. You are not wrong, but it really comes down to proper discipline to organize the config file...which is not hard (even to maintain).
    – G.T.D.
    Jan 16, 2017 at 1:28
  • Perhaps given a somewhat real world example or tangible coding example of where the idea implodes would help me better understand. I am not saying I am not wrong, I could very well be, but I want to understand fully why before I ditch my idea in favor of fragmenting a config amongst several classes.
    – G.T.D.
    Jan 16, 2017 at 1:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.