[ fromfile: liborg.xml id: liborg ]
A dependency between two program elements exists if one is reusing the other; that is, if building, using or testing one (the reuser) requires the presence and correctness of the other one (the reused). In the case of classes, a dependency exists if the implementation of the reuser class must be changed whenever the interface of the reused class is changed.
Another way of describing this relationship is to say that ProgElement1 depends on ProgElement2 if ProgElement2 is needed in order to build ProgElement1.
This dependency is a compile time dependency if ProgElement1.h must be #included in ProgElement2.cpp in order to compile.
It is a link time dependency if the object file ProgElement2.o contains symbols that are defined in ProgElement1.o.
We depict the dependency between a reuser ClassA and a reused ClassB with a UML diagram as shown in Figure 7.1
A dependency between ClassA and ClassB can arise in a variety of ways.
In each of the following situations, a change in the interface of ClassB might necessitate changes in the implementation of ClassA.
ClassA has a data member that is a ClassB object or pointer.
ClassA is derived from ClassB.
ClassA has a function that takes a parameter of type ClassB.
ClassA has a function that uses a static member of ClassB.
ClassA sends a message (e.g., a signal) to ClassB.[24]
In each case, it is necessary to #include ClassB in the implementation file for ClassA.
In the package diagram shown in Figure 7.2, we have displayed parts of our own libs collection of libraries.
There are direct and indirect dependencies shown.
At this level of granularity we are concerned with the dependencies between libraries (indicated by dashed arrows).
If you wish to reuse one of the libraries shown in Figure 7.2, you need to ensure that all of its dependent libraries are also part of your project.
For example, if you use the filetagger library, there is a chain of dependencies that requires you to also make available the dataobjects library (e.g., FileTagger is derived from DataObject), the utils library (e.g., the test code generally reuses the various assert macros in utils), and the id3lib library (e.g., FileTagger has a member of type auto_ptr<ID3_Tag*> and defines some functions with parameters of type ID3_FrameID*).
Code reuse, a valuable and important goal, always produces dependencies.
When designing classes and libraries it is important to make sure that we produce as few unnecessary or unintentional dependencies as possible
because they tend to slow down compile times and reduce the reusability of your classes and libraries.
Each #include directive produces a dependency and should be carefully examined to make sure that it is really necessary.
This is especially true in header files: Each time a header file is #included it brings all of its own #includes along with it so that the number of dependencies grows accordingly.
In a class definition, one good rule to follow is this: Do not use an #include if a forward declaration will suffice.
For example, the header file “classa.h” might look something like this:
#include "classb.h"
#include "classd.h"
// other #include directives as needed
class ClassC; // forward declaration
class ClassA : public ClassB {
public:
ClassC* f1(ClassD);
// other stuff that does not involve ClassC
};
We have (at least) two intentional reuse dependencies in this definition: ClassB and ClassD, so both #include directives are necessary.
A forward declaration of ClassC is sufficient, however, since the class definition only involves a pointer to that class.
Dependency management is an important issue that is the subject of several articles and for which a variety of tools have been developed. Two open-source tools are
cinclude2dot , a perl script that analyzes C/C++ code and produces a dependency graph.
Makedep, a C/C++ dependency generator for large software projects that parses all source files in a directory tree and constructs a large dependency file for inclusion in a Makefile.
| Generated: $Date: 2009-09-08 12:15:32 -0400 (Tue, 08 Sep 2009) $ | © 2009 Alan Ezust and Paul Ezust. |