Code organization

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Code organization

      Hello, Mike and Rez!

      I have bought your book (4th ed.) recently, and it's great!

      And I have some questions about source code organization.
      I'm a web-developer and some C++ stuff little confuse me. One of the most confusing thisng for me is header files.
      When we use header files as inteface for class it's OK. But then we add some typedefs, enums, global vars, #include s and other non-class stuff
      and header become a horrible mess.
      I'd read some articles describing diffecrent best-practices about using headers like blog.knatten.org/2012/11/30/ho…void-includes-in-headers/. And it seem reasonable.
      But let's look at GCC4 code:

      1. Actors. I supposed that every "package" in project is self-containing. But in Actor.h or ActorFactory.h I don't see any #include. If I try to take Actors pakage and add it to another project for exaple, it wouldn't complile at all, cause it depends on another pars of system AND (it scares me greatly) it depends implicitly! Is this normal practice or not?

      2. Another thing is interfaces.h. This header contains tens of different interface classes and some contantns, typedefs and so on. I understand that it is simpler to include one header than bunch of headers but what if our engine will have not tens but hundreds of classes? interfaces.h wiil become some sort of God header (by analogy this God object).

      3. Precompliled headers is good or evil? When should we use it? And it contains most of standard library includes, but this way leads to implicitly dependencies. Or it's OK?
      And why some code contains in GameCodeStd.cpp but not in .h?

      And two more questions:

      1. Why folder, contains Process.h and other called "Mainloop"? I can't find connection.

      2. I can't find where g_pApp instance creates.

      I hope, you'll help me.
      Regards.

      The post was edited 1 time, last by andjey ().

    • RE: Code organization

      Originally posted by andjey
      I have bought your book (4th ed.) recently, and it's great!

      Awesome! I'm glad you're enjoying it. :)


      1. Actors. I supposed that every "package" in project is self-containing. But in Actor.h or ActorFactory.h I don't see any #include. If I try to take Actors pakage and add it to another project for exaple, it wouldn't complile at all, cause it depends on another pars of system AND (it scares me greatly) it depends implicitly! Is this normal practice or not?

      I'm not sure what you mean by package. Actor.h and ActorFactory.h don't have any includes because they don't need them. In fact, the best case is to have header files with no includes because it reduces compile times and incidental dependencies. In C++, header files are never compiled by themselves. You can't just compile a .h file. Instead, header files are compiled as apart of one or more CPP files. Actor.h and Actor.cpp are essentially one unit (maybe this is what you mean by package?). As such, the dependencies are included explicitly in the CPP files.

      You actually should be able to extract the actor system and insert it into another project if you wanted to. Its dependencies are mostly internal.


      2. Another thing is interfaces.h. This header contains tens of different interface classes and some contantns, typedefs and so on. I understand that it is simpler to include one header than bunch of headers but what if our engine will have not tens but hundreds of classes? interfaces.h wiil become some sort of God header (by analogy this God object).

      Personally, I never follow the pattern of having a bunch of unrelated interfaces in a single file since it couples the interfaces together. I tend to limit files to only having one class, though I break this rule when it makes sense. For example, I have a type.h file that contains a bunch of common types, like my implementation of Matrix, Vector, etc.


      3. Precompliled headers is good or evil? When should we use it? And it contains most of standard library includes, but this way leads to implicitly dependencies. Or it's OK?
      And why some code contains in GameCodeStd.cpp but not in .h?

      I generally don't use precompiled headers but most companies I've worked at do. The pattern used in Game Coding Complete is pretty common. It's suppose to speed up compile times, but I prefer including stuff explicitly. I've never liked the "include a bunch of stuff all the time" pattern. Everyone has their own opinions as to whether or not precompiled headers are good.

      The only code in GameCodeStd.cpp is the actually definition of a number of global variables. If these were moved to the header file, the compiler would complain about multiple definitions.


      1. Why folder, contains Process.h and other called "Mainloop"? I can't find connection.

      For two reasons:
      1) The Process system is meant to be used to control the main loop.
      2) Because this system is introduced in the chapter entitled "Main Loop".


      2. I can't find where g_pApp instance creates.

      It's defined on line 68 in GameCode.cpp and assigned in the constructor of GameCodeApp on line 81. The actual instantiation of the application object happens on line 60 of TeapotWars.cpp (TeapotWarsApp is a subclass of GameCodeApp).

      -Rez
    • Thank you, Rez, for this detailed response. It helps me so much! :)
      I'm not sure what you mean by package.

      I mean folder with files related by one subject.
      As such, the dependencies are included explicitly in the CPP files. You actually should be able to extract the actor system and insert it into another project if you wanted to. Its dependencies are mostly internal.

      Ok. I see.
      But there is another problem:

      Source Code

      1. //myHeader.h
      2. //Some Interface class
      3. class IMyClass
      4. {
      5. typedef std::map<int, int> testMap;
      6. };

      C Source Code

      1. //myImplementationIsOK.cpp
      2. #include <map>
      3. #include "myHeader.h"

      C Source Code

      1. //myImplementationIsGoingBad.cpp
      2. #include "myHeader.h"
      3. #include <map>
      4. Compile ERROR!!!

      It turns out that wherever I want to impement my class or inherit from it, I must include all of it's dependencies manualy. Even worse - if I want just to use IMyClass as function argument somewhere, I need to include all of it's dependencies.
      It seems that it is overhead. Or I'm wrong?

      The post was edited 8 times, last by andjey ().

    • Originally posted by andjey
      Ok. I see.
      But there is another problem:

      Source Code

      1. //myHeader.h
      2. //Some Interface class
      3. class IMyClass
      4. {
      5. typedef std::map<int, int> testMap;
      6. };

      C Source Code

      1. //myImplementationIsOK.cpp
      2. #include <map>
      3. #include "myHeader.h"

      C Source Code

      1. //myImplementationIsGoingBad.cpp
      2. #include "myHeader.h"
      3. #include <map>
      4. Compile ERROR!!!

      It turns out that wherever I want to impement my class or inherit from it, I must include all of it's dependencies manualy. Even worse - if I want just to use IMyClass as function argument somewhere, I need to include all of it's dependencies.
      It seems that it is overhead. Or I'm wrong?


      The answer is that you never, ever do that. The very first thing you ever include in a CPP file is the matching header. The only exception is in the case of a standard include, such as GameCodeStd.h. In fact, precompiled headers must be included first or you'll get a compile error.

      If a header file needs to include something that's not included in GameCodeStd.h, it must include it. So in your example, if <map> were not apart of GameCodeStd.h, you would include <map> in the header.

      One of the reasons I don't like this pattern of having a standard precompiled header everyone includes is that it does hide some dependencies. The idea is that this standard header only includes things that EVERYONE is dependent on, but I still prefer to explicitly include everything. In my engine, the very first include in any CPP is always the matching header. That way, if the header is missing some dependency, is shows up as a compile error right away.

      -Rez
    • One of the reasons I don't like this pattern of having a standard precompiled header everyone includes is that it does hide some dependencies. The idea is that this standard header only includes things that EVERYONE is dependent on, but I still prefer to explicitly include everything. In my engine, the very first include in any CPP is always the matching header. That way, if the header is missing some dependency, is shows up as a compile error right away.

      Oh, thanks, Rez! The way you describe (matching header goes first) seemed me reasonable and I try to follow that pattern. But using precompiled header in GCC4 confused me, and I doubted that maybe I'm use some sort of bad-practice.
      But now everything fell into place!
      Thank you once again!

      -
      Regards.

      The post was edited 2 times, last by andjey ().