Cross-reference based reports take "uses" and "used by" information as input and refine it into useful advanced reports. Review file dependencies, procedure calls, variable use and the like. These reports are in the Report menu of Project Analyzer.
When you take all the branches and leaves in a call tree, you get a need report, available in the Report menu. The Need report tells you all the parts in a program that a procedure, class or module requires to work. Utilizing cross-references found in the code, it lists all required procedures, variables, constants, user-defined types and Enums.
You can create a need report for one procedure or a group of procedures. If you create it for a group of procedures, you simply get a list of everything that the group needs. If you create it for a class or a module, you get a list of things required by all the code contained in it. A need report is especially useful if you want to copy certain code from a project to another, and want to include all the required code.
Note that the Need report is based on compile-time dependencies and it does not necessarily contain the full run-time call tree (execution flow). One example is event definitions in classes. When an event fires, the execution moves to the event handler, the event handler is not needed for the class to compile, and thus not included in the Need report. Usually the Need report contains the full (execution-based) call tree, but not always.
The Cross-reference report lists all program entities and their referrers. For procedures, it includes calls and called-by information. It is a useful tool to see where a procedure, variable or another program element is being used.
Sample report: Cross-reference report
If you need to know which actions cause a procedure to execute, select the procedure in the main window and take an Executed by report. This report goes back in the call tree to the top-level procedures that will, when called, eventually execute the selected procedure. You can see which events, start-up procedures, constructors, desctructors, exposed procedures and other procedures are at the top of the call tree, and the execution paths to the selected procedure.
The Executed by report ignores circular references where the selected procedure executes itself by a recursive loop in the call tree.
This report is a kind of an opposite of the Need report, in that it takes all the branches of the backward call tree. However, the Executed by report is based on the run-time execution flow, while the need report is based on compile-time dependencies. The Executed by report includes execution paths that may (or may not) execute at run-time.
The File dependency levels report starts with independent "leaf" files that don't require any other files to compile or run (Level 1). After them, its adds files that that depend on the independent files but no others (Level 2). Then it adds files that depend on Level 2 to get Level 3. It repeats this process until all files have been listed. As you can see, each level builds on the functionality offered by the previous levels. The highest level is likely to contain the "main" part of the program, such as the main form or the Sub Main module.
You use the File dependency levels report to understand the dependency structure of a system. When you need to make large changes to the system, it may be beneficial to work on a single level at a time.
Sample report: File dependency levels
When you wish to find potentially reusable components in a large system, get the Subsystem report. It locates independent subsystems, that is, groups of files that depend on each other but no other parts of the full system. Since a subsystem is independent of other parts, in can potentially be reused in another program.
The report utilizes file dependency information to find related groups of files. For each potentially reusable file it determines which other files it requires and which files those files require, recursively. This dependent group of files is called a subsystem. If the subsystem is small enough (max ½ of the files in the project), it is included on the subsystem report. Larger subsystems are considered too large; they are more likely to be the full system, not directly reusable. Thus, in a 100-file project, a subsystem can consist of 2-50 files.
The report also contains a section of self-contained, independent files. These files may be reused independently of any other files.
Suggested uses for the Subsystem report:
Examples of subsystems you can look for:
Sometimes a subsystem is too large to reuse "as is". This happens when the code was not structured in a reusable way. An example is a file that accesses global variables or functions from another file that is heavily dependent on other parts of the system. Breaking the link to that file may allow to decrease the subsystem considerably. A direct variable access or a function call always creates a dependency. You can often break the dependency by passing the data as a parameter or utilizing events rather than direct calls. Example: If MyForm requires the global variable UserName in module GlobalData, you can break the dependency
Notice that Project Analyzer does not consider external dependencies between files. External dependencies between 2 files can happen via a disk file, a database, an I/O device or an external project that calls both the files. Even if a small subsystem may appear reusable, it may still require some other parts of the program to function the way it is designed. Other parts may be responsible for providing data in the database, writing a disk file, managing an external device etc.
Sample report: Subsystem report
This specialized report detects classes that could be split into smaller classes. The report lists class of low cohesion. These classes consist of 2 or more unrelated parts (sub-components). The parts don't call each other nor do they access common class-level variables. As they have no common functionality, they could be in separate classes.
For each sub-component in a non-cohesive class, the report lists the methods and variables belonging to that sub-component. Consider splitting the class into these sub-components. This is not always possible or desirable, though.
You can read more about the logic behind non-cohesive classes and components under the cohesion metrics. To visualize cohesion, try the Cohesion diagrams in Enterprise Diagrams.
Sample report: Non-cohesive classes
This report is designed for locating hidden problems with variables. Only global and module-level variables are considered, not local variables.
The report counts the number of reads and writes to each variable. The reads (and writes) are further classified into live, dead and dead but exposed reads (and writes).
This report goes beyond regular detection of dead/write-only/read-only variables. The regular dead code detection routines assume that each read and write instruction executes. This is not necessarily the case. The read/write can be in a dead procedure, or a procedure that seems to be dead but that may execute by an external call.
| Reads | Live | Dead (exp) | Writes | Live | Dead (exp) | |
|---|---|---|---|---|---|---|
| x | 3 | 2 | 1 (1) | 2 | 0 | 2 (0) |
In this example, variable x is being read 3 times. 2 of the reads are in a live procedure and 1 read occurs in a dead procedure. There dead read is not truly dead since it is in an exposed procedure (1). An external program may call that procedure and trigger the read.
On the write side, there are 2 writes in total. Since there are 3 reads and 2 writes, the variable is reported live. What is important, however, is that both writes occur in a dead procedure (0 live writes, 2 dead writes, none of them in exposed procedures). What this means is that the variable never gets any value at run-time! Why is this so? Can that cause problems?
You can use the report to locate potentially dead or problematic variables: variables that seem to be all right, but that are not actually used properly:
In many cases there are no simple mechanical answers. Due to the complexity of the issue, you should consider each potential problem (red/violet variable) separately. Right-click the variable in the main window of Project Analyzer to bring up the References list. There you can see the actual list of reads/writes. Points to consider:
The Variable use report is most useful when taken after cleaning the bulk of dead variables and dead procedures via other means (via the problem detection feature or Auto-fix). When you have done that, review this report for problems that went undetected by dead code removal.
Sample report: Variable use report
File dependency analysis finds circular file dependencies that can have a negative effect on reusability.
©Aivosto Oy - Project Analyzer Help Contents