2
class A { public: int i; }; // A.h and defined in project libA.vcxproj (libA.dll)

I'm using class A in multiple places at various projects as below. Apporoximately 100 projects.

include "A.h"
class UseA { public: A *a; UseA(){ a = new A(); } ~UseA() {delete a;} }

My problem is whenever I add a member variable to class A I will have to build all the projects (~100) as the size of the class A has been changed and building 100 project is time consuming.

How to avoid building so many projects on size change of a single class? Also I have many classes like class A defined in libA.vcxproj.

1
  • remove #include "A.h" and move it to .cpp file. Then move ctor and dtor to the .cpp file. Then you need just forward declaration of A class in your UseA class.
    – tp1
    Mar 29, 2014 at 0:21

3 Answers 3

5

Are you familiar with the PIMPL idiom? For certain cases, it can solve this exact problem. The short version is that you wrap all your private member variables into one opaque pointer to a type so that when you add a new private member you don't need as much recompilation...

4
  • 1
    So many upvotes for an answer which ignores the fact the OP asked for extensions on public members?
    – Doc Brown
    Dec 26, 2013 at 10:50
  • 2
    @DocBrown: P.SE users are generally more polite than SO users; they choose to upvote the PIMPL idiom instead of saying OP has a poor design - blatant violation of SOLID principles. SO users would have sentenced OP to a month of Uncle Bob therapy.
    – rwong
    Dec 26, 2013 at 10:56
  • @DocBrown I had looked at the text, which just said "member variable". The example code does indeed have a public variable. I'll also upvote your answer because I think you also provide some other good (albeit unasked :) ) advice. The best answers are able to answer not only the actual question, but also perceive intent.
    – J Trana
    Dec 26, 2013 at 16:38
  • @JTrana: don't get me wrong - I think your answer is helpful for the OP, since in his project he will most probably have to deal with public and private members. But you could have added a explicit remark that your suggestion does not solve the exact problem from the example. By the way, I was not aware that my answer answers something unasked.
    – Doc Brown
    Dec 26, 2013 at 16:43
5

First make sure you really need this - having a central library which is reused more than 100 times works better when the public interface of that library does not change too often or only at specific points in time. Check if it is possible to split up your library in smaller parts, so that changes in one part don't affect the dependent projects of the other parts. Check also if it is possible to develop any changes to that library first "in private", and publish them (visibly for the majority of dependent projects) only for new "major releases" of that library.

But let's assume your project dependencies are correct and necessary for your system, and you really need to extend the public parts of that central library (or central class "A") very often. Then, you cannot avoid that all dependent projects have to be recompiled. But since you typically don't make changes to all the 100 projects simultaneously, you don't have to recompile them all on your local workstation.

What you need in this situation is a build server - a server which automatically checks out all changes from your SCCS and runs a full build of all the 100 projects in the background. For setting up such a system, you will also need a good structured automatic build process. Hopefully your 100 projects can be split up into groups of projects which can be individually compiled and tested, otherwise you have to solve that problem first.

Also a good read, though a bit outdated: Large Scale C++ Software Design by John Lakos. This book will also explain the PIMPL idiom mentioned by Jtrana in depth, though this will only help you with the private parts of your classes, not with the public ones like in your example.

4

In addition to the answers by Doc Brown and J Trana.

  • Doc Brown's answer points out that whole-project rebuild is very much necessary in software development; therefore try to reduce the pain by using build automation, instead of avoiding it.

  • J Trana's answer is a form of encapsulation or information hiding. If most of the users of class A do not need to access the new member, then these steps can be taken:

    • Make the new member private
    • Put the new member inside a private sub-member of class A, and initialize it in A's constructor.
    • Provide accessor methods (getter and setter) for the new member.
    • Note that this still requires rebuilding the whole project, because in C++ any change in a header file will have required a rebuild.
  • My suggestion #1 (vendor specific)

  • My suggestion #2:
    If you really must reduce the time spent on rebuilding while you are making many small experimental changes that involves new members, consider converting data members into property bag.

    • A property bag is a dictionary (std::map) from string to variant values.
    • If the class A provides get/set methods for this dictionary, then the addition and removal of new keys will not require a rebuild.
    • However, the drawbacks are:
      • It will be a lot slower to read from and write to the values in the dictionary, compared to accessing a class member.
      • The whole project will be more prone to errors, because the compiler will not be able to perform name checks and type checks on the keys and values stored in a property bag.
      • Example:
        A compiler can catch the bug where one tries to access a class member that does not exist.
        A compiler does not automatically catch the bug where one accesses a dictionary key that does not exist. The programmer must write code to handle this situation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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