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.
The same question arises in most of the projects I work on. Usually, I do this:
- 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.
- 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.
- 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.
- 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
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.)
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