52

I have recently been reading The Pragmatic Programmer which states that:

Details mess up our pristine code—especially if they change frequently. Every time we have to go in and change the code to accommodate some change in business logic, or in the law, or in management's personal tastes of the day, we run the risk of breaking the system—of introducing a new bug.

Hunt, Andrew; Thomas, David (1999-10-20). The Pragmatic Programmer: From Journeyman to Master (Kindle Locations 2651-2653). Pearson Education (USA). Kindle Edition.

I am currently programming a web app that has some models that have properties that can only be from a set of values, e.g. (not actual example as the web app data confidential):

light->type = sphere / cube / cylinder

The light type can only be the above three values but according to TPP I should always code as if they could change and place their values in a config file. As there are several incidents of this throughout the app, my question is:

Should I store possibly values like these in:

  • a config file:
    'light-types' => array(sphere, cube, cylinder),
    'other-type' => value,
    'etc' => etc-value

  • a single table in a database with one line for each config item

  • a database with a table for each config item (e.g. table: light_types; columns: id, name)

  • some other way?

Many thanks for any assistance / expertise offered.

3 Answers 3

51

The same question arises in most of the projects I work on. Usually, I do this:

  1. If the set of possible values is unlikely to change any time soon, I use class/interface constants or enums in the code and enumerable fields in the database. Example: state of publishing of blog entries: 'not published', 'under moderation', 'published', etc.
  2. Values will probably change, but changes will not affect program logic - config files. Example: list of "how did you find our website?" options for a dropdown list in online purchasing form.
  3. Values are likely to change frequently and/or meant to be edited by non-developers, but yet these changes will not affect the logic - a database or at least a key-value storage with some user-friendly interface for editing.
  4. Changing the values will affect the logic - probably the system needs redesign (often true) or some business rules engine is needed. The most difficult case I've seen so far was psychological tests constructor my colleague worked on. Each type of test may have its own scoring system which may vary from simple addition to multiple characteristics scales with positive and negative values or even human evaluation of answers. After some discussion about this project, we ended up using Lua as a scripting engine, which totally conflicts with the ability of non-developers to create new tests (even though Lua is a relatively simple language you shouldn't expect that a non-programmer will learn it).

About the quote from TPP. I think it's true for pristine code, but in real life, you better start simple (KISS principle) and add features later if they're really needed (YAGNI).

1
  • I prefer to keep it all in a database for peak configurability. If you need a rules engine, abstract that to a microservice then store the reference id of that rule-set in your DB.
    – AjaxLeung
    Apr 7, 2020 at 3:34
10

If your data will be in a database, i'd recommend having a table of 'light_types' in the same DB. This gives you the ability to use foreign keys to enforce a constraint that light->type can only be one of those values, so even if the code messes up, the data in the DB will always be valid.

If the data won't be stored in a DB, creating one just for a bunch of enums doesn't do a whole lot of good. I might recommend a config file, if you really want to avoid hard-coding the values.

(I'd warn against going too far in avoiding hard-coding, though. In any non-trivial system, there will be assumptions about business rules and requirements, whether the authors realize it or not. Even if you somehow manage to avoid all assumptions and soft-code absolutely everything, you basically just end up with a "rules engine", a sort of system-within-a-system and/or meta-language, and you have a bunch of stuff in the meta-language to implement the rules. You haven't saved any work or gained any flexibility; you've just had to build and/or learn another language.

Now, if you want to find and use an existing rules engine, that might save you a bit of work (along with answering the question of where to store enums). But building your own just doubles the workload and inevitably gets you a half-assed system built by people who really don't know how to make a decent rules engine.)

0

In general a database should be used for data and a config file should be used for configuration. (as the name suggests :) ). Keeping configuration in the database is bad separation of concerns and should only be done if you have a good use case to justify it.

There is a balance to be struck when deciding how much configuration to use. You should treat your config files as much as a part of an application as the code. Keep it as terse as possible. Its very easy for applications to suffer from configuration bloat where you end up with a huge xml file full of magic strings.

In the case you describe it would be reasonable to have a configuration element to define which css file to use. (you could then just change it if requirements change). It would be overkill to configure the style of each element in the config file

5
  • 2
    How do you define what is configuration and what is data though?
    – nafg
    Oct 26, 2016 at 3:22
  • 6
    Your answer doesn't explain why storing a configuration in a database violates separation of concerns (the concern of a database is to store data; it doesn't care what data you store there), or why this is a bad thing, and your answer is now being cited elsewhere as proof that it's a bad thing. Aug 25, 2017 at 14:59
  • 1
    databases can change on demand. we can have them being asynchronous like mysql. Does static files support this? HELL NO! So I downvote :) Sep 19, 2017 at 9:15
  • 1
    @AmirHossein Static files support change on demand as long as they're not locked. That's no argument.
    – Zimano
    Jul 9, 2019 at 18:13
  • @AmirHossein +1 to the notion your argument is flawed. The conclusion you reach is convincing only if you ignore (possibly more common) use cases. If you feel the config needs to be "asynchronous" then (if I understand what you meant by that) then you can pull the config files from a Object Storage microservice. As you say, databases "change on demand" which in my experiences has ALSO meant "our service is down because of the database folks". IMO a good reason to use a database for configs is when you require relatable config fields, and even then try not to poll the db directly. Mar 4, 2021 at 13:10

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.