Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In our mostly large applications, we usually have a only few locations for constants:

  • One class for GUI and internal contstants (Tab Page titles, Group Box titles, calculation factors, enumerations)
  • One class for database tables and columns (this part is generated code) plus readable names for them (manually assigned)
  • One class for application messages (logging, message boxes etc)

The constants are usually separated into different structs in those classes. In our C++ applications, the constants are only defined in the .h file and the values are assigned in the .cpp file.

One of the advantages is that all strings etc are in one central place and everybody knows where to find them when something must be changed.

This is especially something project managers seem to like as people come and go and this way everybody can change such trivial things without having to dig into the application's structure.

Also, you can easily change the title of similar Group Boxes / Tab Pages etc at once. Another aspect is that you can just print that class and give it to a non-programmer who can check if the captions are intuitive, and if messages to the user are too detailed or too confusing etc.

However, I see certain disadvantages:

  • Every single class is tightly coupled to the constants classes
  • Adding/Removing/Renaming/Moving a constant requires recompilation of at least 90% of the application (Note: Changing the value doesn't, at least for C++). In one of our C++ projects with 1500 classes, this means around 7 minutes of compilation time (using precompiled headers; without them it's around 50 minutes) plus around 10 minutes of linking against certain static libraries.
  • Building a speed optimized release through the Visual Studio Compiler takes up to 3 hours. I don't know if the huge amount of class relations is the source but it might as well be.
  • You get driven into temporarily hard-coding strings straight into code because you want to test something very quickly and don't want to wait 15 minutes just for that test (and probably every subsequent one). Everybody knows what happens to the "I will fix that later"-thoughts.
  • Reusing a class in another project isn't always that easy (mainly due to other tight couplings, but the constants handling doesn't make it easier.)

Where would you store constants like that? Also what arguments would you bring in order to convince your project manager that there are better concepts which also comply with the advantages listed above?

Feel free to give a C++-specific or independent answer.

PS: I know this question is kind of subjective but I honestly don't know of any better place than this site for this kind of question.

Update on this project

I have news on the compile time thing:
Following Caleb's and gbjbaanb's posts, I split my constants file into several other files when I had time. I also eventually split my project into several libraries which was now possible much easier. Compiling this in release mode showed that the auto-generated file which contains the database definitions (table, column names and more - more than 8000 symbols) and builds up certain hashes caused the huge compile times in release mode.

Deactivating MSVC's optimizer for the library which contains the DB constants now allowed us to reduce the total compile time of your Project (several applications) in release mode from up to 8 hours to less than one hour!

We have yet to find out why MSVC has such a hard time optimizing these files, but for now this change relieves a lot of pressure as we no longer have to rely on nightly builds only.

That fact - and other benefits, such as less tight coupling, better reuseability etc - also showed that spending time splitting up the "constants" wasn't such a bad idea after all ;-)

share|improve this question
1  
personally I wouldn't have UI title or message strings in constants at all. I'd have them in app.config –  jk. Apr 19 '12 at 12:06
1  
I kinda like how you are doing it now - I understand your disadvantages but we might just have to deal with that. –  bigtang Apr 19 '12 at 12:42
1  
I've seen exactly the same problem in a large Java project... One huge "constants" interface, change anything in it and wait 15 minutes for eclipse to recompile. I'm with Caleb: group the constants where they naturally belong, close to the code that uses them. Keeping them separate because they're constants is a useless OCD exercise. –  Michael Borgwardt Apr 19 '12 at 20:11

4 Answers 4

up vote 7 down vote accepted

Constants that are specific to a class should go in that class's interface.

Constants that are really configuration options should be part of a configuration class. If you provide accessors for the configuration options in that class (and use them in place of the constants elsewhere), you won't have to recompile the whole world when you change a few options.

Constants that are shared between classes but which aren't meant to be configurable should be reasonably scoped -- try to break them out into files that have particular uses so that individual classes only include what they actually need. This again will help reduce compile times when you change some of those constants.

share|improve this answer
    
In case you are interested: I updated my question with what I have achieved, following your answer and others –  Tim Meyer Jun 5 '12 at 14:32

I'd say simply that you want to split your huge constants class into many smaller files, one per form for example. This ensures you don't have such a huge dependency on the constants file, so adding or updating a string would not then require a total recompile. You can still store these files in a central location, but (eg) have 1 file with constants for each dialog, suitably named. Then you can only include those files in the relevant dialog files, which cuts down the recompilation massively.

I'd also suggest you use something like GNU GetText utilities to handle the strings, it's designed for translation, but works just as well for simply changing the text to something else. You could put them in a strings resource, but I find them to be more difficult to work with as they're keyed by ID, the GetText utils are keyed by an original string - makes things very easy to develop.

share|improve this answer
    
I might give that a shot. As the constants class with titles etc is split into several structs, I could maybe do one class per struct as a beginning. Not sure about the GNU thing, we usually don't want to change our strings at runtime, just during development time. We are using Qt's translation mechanism however, in case we have to translate to another language in future. –  Tim Meyer Apr 19 '12 at 16:16
    
In case you are interested: I updated my question with what I have achieved, following your answer and others –  Tim Meyer Jun 5 '12 at 14:33

Note: I am not a C++ developer... but here is my thought: You need to consider following @jk's comment about the difference between using configuration files. In DotNet, there are resources file that is used to store such information. In Windows Forms, a resource file is maintained from VS for each form.

I don't see a value for a constant to be placed outside its scope of use unless it is a global constant that must be shared. As you mentioned this will be difficult to maintain during development at least. Also, you may get name clashes. Another thing is that it might be difficult to know who is using a given constant.

Now if you want non-programmer to review information then, for GUI, you capture the screen for them. If you want them to review data table entries, you could export the data to Excel or something similar.

If you still want to go with a centralized location approach and you want to place all your constants in one big file, each developer may use a shared file that is updated at the end of each interval to a central file. The data will come from individual files used in development. This can be easily automated or done manually. However, as I said it is probably a risk you don't have to take.

share|improve this answer

I would suggest putting all of these constants into some sort of configuration file. For Java applications, we usually use .properties files, a simple text with each line formatted as "(key) = (value)". Example

MainPanel.Title = Welcome to our application
DB.table.users = TBL_USERS
logging.filename = application.log

You then load this file at runtime, populate a cache that lets you look up a key and get back a value. When you need a constant you then query the cache. You will still need to have your keys somewhere, and the cache will need to be globally accessible, but when you change the actual values of the constants, no recompile is necessary, it should be possible to just re-start the app (or if you really want to get fancy, have multiple .properties files and caches and give the application the ability to reload a cache at run-time).

For an implementation, I found this SO question: http://stackoverflow.com/questions/874052/properties-file-library-for-c-or-c (it was the first hit on a Google search - I haven't actually used this software myself).

share|improve this answer
    
For the C++ projects, we only need to recompile the constants file if we change a value. This is because values are assigned in a .cpp file. However adding/removing/renaming/moving a constant still requires a full rebuild –  Tim Meyer Apr 19 '12 at 16:05
    
@TimMeyer: If you split the constants to multiple files, adding/removing a constant would only affect the files that depend on that particular file, correct? –  FrustratedWithFormsDesigner Apr 19 '12 at 16:08
    
Correct. The main problem is that if I suggest that, people tend to mention one of the things I listed as "advantages" get lost –  Tim Meyer Apr 19 '12 at 16:14
    
However, I haven't actually thought about putting several constants files in the same place –  Tim Meyer Apr 19 '12 at 16:14
    
+1. @Tim Meyer: For this purpose, compile-time checking costs much more than it saves. Besides, what are you going to do if you need to internationalize? –  kevin cline Apr 19 '12 at 16:55

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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