Analyzing Dependencies

Exploring dependencies among symbols, especially functions and variables, is an important task across many software development activities. When debugging, the challenge is often to discover any paths where certain symbols could have interacted with others. In quality assurance, efficient test development depends upon understanding what portions of the software could be related. And while making enhancements during software maintenance, a thorough understanding of dependencies is critical to insure that changes don't introduce new errors.

Unique to Imagix 4D's source code analysis functionality is its Analyzer feature. Analyzer automatically creates detailed graphs that visually depict various aspects of a given symbol and its use. Among the graphs generated for functions and variables are a series of views showing the symbol's dependencies to other symbols in your software. At the push of a button, you get a precise, comprehensive analysis, displaying the particular dependencies you're interested in. The following are some examples.
As you examine any symbol in your code, its corresponding Analyzer tab includes a number of graphical queries. A set of these specifically explore potential relationships to a second symbol. After selecting the second symbol of interest, you're able to have Imagix 4D automatically check for any interdependencies.

Preconfigured queries in Analyzer tab automate source code analysis
Included in the Analyzer dialog for a function is the ability to check dependencies relative to a second function. (Full Dialog)

Through the Paths Between Functions query, Imagix 4D identifies both direct and transitive call dependencies between the two target functions. Any and all paths through the calling hierarchy in which one function calls the other are displayed.

Call tree displays full set of function-to-function dependency paths in software
The functions (blue-sided rectangles) and calls (red lines) in the call tree from ReceiveCont to Send are layed out from top to bottom.

The Paths To Variable query operates similarly. It finds all of the paths through which the target variable is directly or transitively used by the target function. Both sets and reads of the variable are shown.

Call graph with variables shows all paths in source code through which function accesses variable
In the paths from ReceiveCont to the variable connection, uses of connection are indicated as sets (aqua lines) and/or reads (orange lines).

The rest of the relationship queries find overlaps in the use and dependencies of two target functions. One of these, Common Ancestor Functions, identifies all functions that originate separate calls to the pair. If FuncA calls FuncB, and the two target functions are only reached from FuncA through the same call to FuncB, then FuncB is displayed while FuncA is omitted. These ancestors are thus the lowest functions in the calling hierarchy that are dependent on both target functions.

Starting from this display of ancestor functions, you might then use the Paths Between Functions query to examine more completely the full path from a specific ancestor to a target function.

Query-based dependency analysis identifies all ancestors shared by two functions
Only direct calls (red lines) are displayed between the ancestors on the left and the two target functions on the right. Therefore, Call is directly called by some functions that only transitively call Send.

The Common Descendant Set Variables analyzes in the reverse direction, checking for any overlap in the variables set by the two target functions. All such variables are identified. Again, a follow-up query, Paths To Variable, could be used to further investigate how a particular descendant variable is reached from a target function.

Graph uses reverse engineering to determine common variable dependencies of two functions
Direct sets (aqua lines) are displayed between the target functions on the left and the descendant variables on the right. Most of the variables are only set transitively.

Function and variable
dependency analysis