开发者

c++ global constants issue

开发者 https://www.devze.com 2022-12-08 04:45 出处:网络
We have these set of \"utility\" constants defined in a series of file. The problem arises from the fac开发者_JAVA技巧t that TOO MANY files include these global constant files, that, if we add a const

We have these set of "utility" constants defined in a series of file. The problem arises from the fac开发者_JAVA技巧t that TOO MANY files include these global constant files, that, if we add a constant to one of those files and try to build, it builds the whole entire library, which takes up more than an hour.

Could anyone suggest a better way for this approach? That would be greatly appreciated.


First, if you are defining them directly in the header, I'd suggest instead delcaring them extern const, and then defining them in a cpp file:

//in .hpp:
extern const std::string foo;

//in .cpp:
const std::string foo = "FOO";

That way, at least definitions can be changed without a rebuild.

Second, examine where they are being included. If the constant file is being included in a low level header, can the include be moved to the cpp instead? Removing it might lower the coupling so it doesn't have to rebuild as much.

Third, break up that file. I'd suggest mapping out a structure you'd eventually want, start adding new constants to the new structure instead of the old file. Eventually (when you are sure you've got the structure you want), refactor the old file into the new structure, and make the old file include the entire structure. Finally, go through and remove all includes of the old file, pointing them at the appropriate new sections. That'll break up the refactoring so you don't have to do it all at once.

And fourth, you might be able to trick your compiler into not rebuilding if the header file changes. You'd have to check your compiler's documentation, and it might be unsafe, so you'd occasionally want to add full builds as well.


Do you really need every global define to be included in every file? You should probably split the constants up into categories and then split them into different files.

Every .h that is included is simply copied at that point in the file that is including it. If you change something in a file (either directly or via changing something that is included) then it absolutely needs to be recompile.

Another solution would be to have a .h file that has an accessor to a map of string name/values. Then in the .cpp file of that map/accessor you can insert the new values. Every new value you put would only need 1 file to be recompiled.

Another solution is not to include the header file anywhere. Simply extern in the variables you need in each .cpp file.


Perhaps it's time to do some refactoring to improve the cohesion and reduce the coupling in your software design. Splitting the global constant files would allow modules to be more selective about which constants need to be included, which will eliminate some of the unnecessary coupling. In the extreme case, you could break it all the way down to one constant per file, and ensure that each module only includes the constants it needs to use.

But that could result in poor cohesion, in the sense that the constants might naturally fall into related groups, such that a module that requires one constant will generally also require many others from that group. So the trick is to find a better grouping of constants in the various global files, then ensure that each module only includes what it needs.


(Edit: I didn't think of external constants. Indeed, my idea is kinda stupid.)

(Edit: My "stupid" macro idea actually saves build time for when constants are added. Thanks for pointing that out, Brian!)

Use parallel building :-)

Seriously, I think one solution would be to create another header called utility_ex.hpp or something where you add new constants that you occasionally merge into utility.hpp (or whatever your current utility constants header is called).

Another (less efficient) solution would be to have a macro like this:

#define constant(name) get_constant(#name)
    // # means turn name into a string literal

int get_constant(const char *name);

Now suppose you want MAX_CUSTOMERS to be defined as 100. You can say:

constant(MAX_CUSTOMERS)

in the code. In get_constant's code, you might have:

int get_constant(const char *name) {
    if (!strcmp(name, "MAX_CUSTOMERS"))
        return 100;

    //shouldn't happen
    return -1;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消