开发者

Practice of having a "Common" header [closed]

Closed. This question is opinion-based. It is not currently accepting answers. 开发者_开发知识库

Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.

Closed last year.

Improve this question

By common I don't mean utility, I mean a header that holds enums that multiple types want to use, etc.

For example, if multiple types can have a Color, which is an enum, you'd want to make that available. Some people would say to put it into the class that it "fits best with", but this can create header dependency issues.

I really dislike creating a header that contains things like this, because it seems like it makes the code more complex. I'm looking for other's thoughts on what techniques they employ when they run into a situation like this. If they use a "Common" header, etc.


I always use a Common.h file that almost never changes and contains definitions that are extremely likely to be needed in virtually all files. I think it increases productivity so that you don't have to open another .cpp file and copy the list of all the headers you know you'll definitely need.

For example, here are two excerpts from my Common.h:

typedef unsigned char uint8;
typedef signed char int8;
typedef unsigned char uint08;
typedef signed char int08;
typedef unsigned short uint16;
typedef signed short int16;
typedef unsigned int uint32;
typedef signed int int32;
typedef unsigned long long uint64;
typedef signed long long int64;
typedef const char cchar;
typedef const bool cbool;
typedef char Byte;


#ifdef ASSERT
/* Re-defining assert */
#undef ASSERT
#endif

#ifdef DEBUG
#ifndef ASSERTIONS
#define ASSERTIONS
#endif
#endif

#define ASSERT_ALWAYS(Expression)   if (!(Expression)) FatalError(ErrorInfo("Assertion Failure", #Expression, FUNCTION_NAME, __FILE__, __LINE__))

#ifdef ASSERTIONS
#ifdef DEBUG
#define ASSERT(Expression)   ASSERT_ALWAYS(Expression)
#else
#define ASSERT(Expression)   if (!(Expression)) ErrorLog("[Release Assertions]: The following assertion failed: " # Expression)
#endif
#else
#define ASSERT(Expression)
#endif


Common header is ok as long as there are only a few people working on your project. Once you have 20+ people editing that file and merging changes back and forth, you start to have a nightmare.

Perhaps an alternative would be to have a color.h or a common/color.h file, which would enforce some structure on your files.


Personally I am not a fan.

  1. I means that when you modify a constant (or type) that is used in only one place, you need to recompile your entire project.
  2. The value of the constant (or definition of the type) and the use of the said constant (or type) are in two different places.

Generally speaking, I like to define a constant that is used only once, next to where it is used. This means that if I want to know what value the constant holds, it is right there for me to look at. It also means that I only need recompile one file when the said constant changes.

There is a case for a constant header file if the constant or type is used extensively or if a constant or type is shared across modules.


IMO Common headers are good practice if you restrict them to containing things that seldom change like

typedef unsigned int UINT32;

If you find yourself editing this file a lot, then you have stuff in it that doesn't belong there.


I prefer to be explicit about what each and every cpp file needs. I find it's easier in the long run and that it prevents 'common' headers from causing files to be rebuilt when they don't need to be. As a project grows, having a strict 'include only what you need' policy can help keep build times down. The price of this is a little thought when you're initially building a new class. I often have header files just for a single enum or typedef and I even go as far as having a special build configuration which builds without precompiled headers and (since I work with Visual Studio) use #pragma hdrstop to define my precompiled headers rather than having every file need to include a common file for this purpose.

Over the years I've found this to work very well at keeping build times down and allowing code to be moved around (out into libraries or across into other projects) or built for test harnesses.

I view common headers as unnecessary coupling which should be removed and, to be honest, a sign of laziness and lack of attention to detail.


If you want 'global' enums then put them in their own namespace instead of polluting the global namespace, e.g.:

// Types.h

namespace MyTypes
{
    enum Color
    {
        RED,
        BLUE,
        GREEN,
    };
}

Personally I prefer to keep enums associated with a class but YMMV.


Avoid it! Creating that common header will resultr in tight coupling between modules. Dr. Bob Martin talks about coupling in his Clean Code book and lecture series. Also, as a team lead who has experienced the difficulty of trying to replace a module in a tightly-coupled system, it really sucks!

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜