The Wayback Machine - https://web.archive.org/web/20080929224816/http://www.codeguru.com:80/cpp/cpp/cpp_mfc/files/article.php/c6859/

CodeGuru
Earthweb Search
Forums Wireless Jars Gamelan Developer.com
CodeGuru Navigation
Member Sign In
User ID:
Password:
Remember Me:
Forgot Password?
Not a member?
Click here for more information and to register.

jobs.internet.com

internet.commerce
Partners & Affiliates
















RSS Feeds

RSSAll

RSSVC++/C++

RSS.NET/C#

RSSVB

See more EarthWeb Network feeds

Home >> Visual C++ / C++ >> C++ >> C++ & MFC >> File I/O


Manage the Physical Dependencies of a Project to Reduce Compilation Time
Rating: none

Zeeshan (view profile)
March 30, 2004

In our daily experience, we are making our project in different files, not in a single file. We will do this because we want to reduce the compilation time during the development as well as reuse the code written in different files. For example, let's say that you want to make some project that has 10,000 lines of code. During the development of project, or after it, if we change any single line, the compiler has to recompile all 10,000 lines. With today's computers, it might not be a big problem, but it will eventually become a nightmare when projects become larger. On the other hand, if we split our project into more than one file, such as 10 files each containing 1000 lines, any change in one file ideally should not affect in other files.


(continued)



During the development of a project, we usually talk about the design of classes, discussing in terms of design pattern, and describe the relationship among the classes. But, most of the time we are not concerned about the files in which those classes are written. In any large-scale project, it is not also worth the time and energy to study the physical design of the project, but in some cases, where the project size is very huge, it is inevitable.

It is very common that a large-scale project has some general-purpose classes that are useful in other projects too. So, a natural solution to use those classes in other projects is to make those classes in separate files. It is a common practice of C++ users to make two files for one class; one file contains definitions, and the other has the implementation of the class and its member functions. A Point class will be something like this:

But, if you didn't program carefully, sometimes it is not possible to just include these two files in another project and use it. One of the most common problems that may arise is to include some other definition files in your project that are not needed. And, other files also may need some other files, so at the end you may have to include a bunch of files to just use one single class.

One example of this is that you might want to use a Database class that is created in some library or DLL; then you also might need to include the definition files of some other classes in that library, such as RecordSet.H, DBFactory.H and DBException.H. The situation is even worse if you have to include the definition files of different Database classes, such as OralceInterface.H, SQLInterface.H, and SybaseInterface.H.

It is better to see carefully which files are included in files, especially which files are included in Definition file (Header file). If you change anything in any definition file, all the files, whether it is a Definition file or Implementation file, need to recompile. From the compiler's prospective, a CPP file with all preprocessor expended is called a translation unit. In other words, a translation unit is an Implementation file with all the definition files included. Here is an example of a translation unit.

Now, if you change anything in any of the definition files that are included in Camera.CPP you have changed this translation unit and it has to be recompiled. The situation becomes more serious if these definition files are included in more than one translation unit; the change in one definition file means that you need to recompile all those translation units.

Changes in definition files can be minimized if we use them only for definition, not for implementation.

"In other words, implementation of a function should not be in the header file even if it is only a one-line function. If performance is concerned, that function can be declared inline explicitly. If there is any change in the implementation of the function only, the compiler will recompile only that translation unit."

However, in the other case, the change of implementation of function means recompiling all translation units that have this header file.

If one header file is included in another header file, changing the first header file will change all the files that include either the first or second file. The situation becomes even worse when the header file includes another header file, which includes another header file, and so on. Now, a change in one file may mean that the compile is not limited to one file only, but it may involve recompiling the whole project. This diagram shows this concept clearly.


(
Full Size Image)

It doesn't matter that your Camera class does not include Point.H or ViewPort.H directly; it is included in the Camera translation unit. Now, a change in Point header file will compile not only Camera translation unit, but also all translation units in this example.

The basic rule of thumb to minimize physical dependencies is:

"Try to avoid inclusion of a header file within a header file until you don't have any other option."

But how can we make the compiler happy when we are not including a header file? To see the answer to this question, we first must understand in which cases we are forced to include a header file and in which cases we can avoid it.

You have to include the header file when you need the full details of the class. In other words, you have to include a header file when you are accessing a member function or variable of a class, inherit from a class, or aggregate its object in another class. We have already decided not to write implementation code in a header file, so this first case will be eliminated automatically. If you use another object in member functions only, either creating its local object or use it as a parameter, or it contains a pointer of another class, you do not need to include its header file. To make the compiler happy too, you can just do forward of that class in the header file. Now, we can restate our basic rule to minimize physical dependencies:

"Use a Forward declaration instead of including a header file wherever possible, such as in the case when you are not inheriting a class or aggregating it in another class."

For example, in this case we have to include the Point header file in the ViewPort header file.

#include "Point.h"

class ViewPort
{
public:
   // Other functions

private:
   // other attributes
   Point m_PtLeftTop;
   Point m_PtRightBottom;
};

But, there is no need to include a ViewPort header file in the Transformation header files if it just uses it. Such as the following:

class ViewPort;

class Transformation
{
public:
   void Scale(int p_x, int p_y, ViewPort& p_viewPort);
   // other functions
};

But, you have to include the ViewPort header file in the Transformation implementation file because there is no way to avoid this. The situation is a little bit better, and now a change in Point.H will not propagate in all translation units. At least, it will not have any effect on all the translation units that include the Transformation.H file.


(Full Size Image)

You can further reduce the physical dependencies by making a pointer of a class rather than making the object of a class. In the case of a pointer, the compiler does not need full details in header file and it can be totally eliminated.


(Full Size Image)

In this case, you have to create and destroy the object yourself, as well as there is extra overhead of function calling. In addition, this physical design might not fit very well to your logical design because you are not doing inheritance; therefore, you can't access the protected data of a class, and cannot override virtual functions. This technique is also known as the "Pointer to Implementation Principle" or, in short, the "PImpl Principle."

There might be one solution to avoid including a header within a header. Include all header files in the CPP file before including its own header file. Take a look at the above example; ViewPort.H needs the Point.H file. Now, include this header file in ViewPort.CPP before including the ViewPort.H file.

// ViewPort.CPP
#include "Point.h"
#include "ViewPort.h"

Compilers will look at this translation unit so that it seems to be something like this:

and happily compile this unit. But, there are two problems in this approach. The first is that you have to include header files in the proper order. You have to remember the dependencies of the header file and include it in the proper order or the program will not recompile even if you include all the required header files, but not in proper order. The second problem is even more problematic; if you want to use ViewPort.H in any other translation unit, that translation unit will not compile until you include Point.H. From a physical point of view, you haven't changed anything, but you also create more problems by introducing dependencies among header files; these are hard to remember. Here is one more rule of thumb for managing physical dependencies:

"Never make any files that are dependent on the order of header file inclusion."

About the Author
Master in Computer Science (MCS) getting first class second position from University of Karachi.

Tools:
Add www.codeguru.com to your favorites
Add www.codeguru.com to your browser search box
IE 7 | Firefox 2.0 | Firefox 1.5.x
Receive news via our XML/RSS feed







RATE THIS ARTICLE:   Excellent  Very Good  Average  Below Average  Poor  

(You must be signed in to rank an article. Not a member? Click here to register)

Latest Comments:
No Comments Posted.
Add a Comment:
Title:
Comment:
Pre-Formatted: Check this if you want the text to display with the formatting as typed (good for source code)



(You must be signed in to comment on an article. Not a member? Click here to register)


JupiterOnlineMedia

internet.comearthweb.comDevx.commediabistro.comGraphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

Jupitermedia Corporate Info

Solutions
Whitepapers and eBooks
Intel Article: Using Power & Display Context in the Intel Mobile Platform SDK
Internet.com eBook: Real Life Rails
IBM SCA Center Article: Simplifying Composite Applications with Service Component Architecture
Intel PDF: Quad-Core Impacts More Than the Data Center
Internet.com eBook: The Pros and Cons of Outsourcing
Go Parallel Article: Scalable Parallelism with Intel(R) Threading Building Blocks
Intel PDF: Analysis of Early Testing of Intel vPro in Large IT Departments
Internet.com eBook: Best Practices for Developing a Web Site
Intel PDF: IT Agility through Automated, Policy-based Virtual Infrastructure
IBM CIO Whitepaper: The New Information Agenda. Do You Have One?
Microsoft Article: BitLocker Brings Encryption to Windows Server 2008
Microsoft Article: RODCs Transform Branch Office Security
Go Parallel Article: James Reinders on the Intel Parallel Studio Beta Program
Avaya Article: Advancing the State of the Art in Customer Service
IBM Whitepaper: How are other CIOs driving growth?
Adobe Acrobat Connect Pro: Web Conferencing and eLearning Whitepapers
Avaya Article: Avaya AE Services Provide Rapid Telephony Integration with Facebook
Go Parallel Article: Getting Started with TBB on Windows
HP eBook: Storage Networking , Part 1
MORE WHITEPAPERS, EBOOKS, AND ARTICLES
Webcasts
Go Parallel Video: Intel(R) Threading Building Blocks: A New Method for Threading in C++
HP Video: Is Your Data Center Ready for a Real World Disaster?
HP On Demand Webcast: Virtualization in Action
Go Parallel Video: Performance and Threading Tools for Game Developers
Rackspace Hosting Center: Customer Videos
Intel vPro Developer Virtual Bootcamp
HP Disaster-Proof Solutions eSeminar
HP On Demand Webcast: Discover the Benefits of Virtualization
MORE WEBCASTS, PODCASTS, AND VIDEOS
Downloads and eKits
Actuate Download: Free Visual Report Development Tool
Red Gate Download: SQL Backup Pro
Microsoft Download: Silverlight 2 Software Development Kit Beta 2
30-Day Trial: SPAMfighter Exchange Module
Red Gate Download: SQL Toolbelt
IBM SCA Download: Start Building SCA Applications Today
Iron Speed Designer Application Generator
Microsoft Download: Silverlight 2 Beta 2 Runtime
MORE DOWNLOADS, EKITS, AND FREE TRIALS
Tutorials and Demos
IBM IT Innovation Article: Green Servers Provide a Competitive Advantage
Microsoft Article: Expression Web 2 for PHP Developers--Simplify Your PHP Applications
Featured Algorithm: Intel Threading Building Blocks - parallel_reduce
MORE TUTORIALS, DEMOS AND STEP-BY-STEP GUIDES