Let’s elaborate on the nature of these call tree diagrams. Consider the following code:
void doStuff() { doOtherStuff(); } void doOtherStuff() { init(); final(); } void blah( int x ) { if ( x == 2 ) { function(); otherFunction(); } else { doStuff(); } }
Depending on the input for the blah function, we are going to experience two very different call graphs. If blah is called with a value of 2 for its input parameter x, then we would see a call tree like:
But on the other hand, if blah is called with any other value we end up with a call tree that looks like:
Any given program will potentially have a very large number of corresponding call trees. A call forest if you will. All things being equal, a small call forest is probably more comprehensible than a large one. The idea here is that in order to really understand the program a software engineer will have to understand every call tree in a program’s call forest. This is probably impractical in just about every real world program, so the software engineer will need to construct the program such that understanding a subset of the call trees will yield the necessary insight to effectively work with the program.
Next I want to talk about global variables, but first we need to look into abstract data types.