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.
The Need report lists all the other code parts that a procedure, class or module requires to work. It lists all the branches of a call tree, including all required procedures, variables, constants, user-defined types and Enums.
The Need report is also an impact report. It lists the parts of the program that, when changed, might have an impact on the selected procedures, classes or modules.
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
The Procedure references report lists all procedures and their call sites. This is useful for finding out usage patterns of certain procedures. (To list references to a single procedure, you should rather right-click its name and select References.)
Sample report: Procedure references report
The Variable references report lists global and module-level variables and the lines accessing them. This is useful for finding out usage patterns of certain variables. (To list references to a single variable, you should rather right-click it and select References.)
Sample report: Variable references report
The Constant references report lists global and module-level constants and the lines accessing them. This is useful for finding out usage patterns of certain constants. (To list references to a single constant, you should rather right-click it and select References.)
Sample report: Constant references 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 MyForm->GlobalData by passing UserName as a parameter to MyForm. Similarly, if MyForm needs to store some data, you can (instead of calling GlobalData.Save) declare an Event called MyForm.Save and handle this event to store the data the way that is appropriate in each application.
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 analyzes how each variable is used in your project. The report helps you look for hidden defects. For each variable the report lists the number of read and write instructions. In addition, you see whether the instructions actually execute at run-time or not.
This report works with global and module-level variables. Local variables within procedures are not considered.
|3||2||1||1||varname||2||0||2||0||Warning if there is a problem with the variable|
|Read||Total number of reads from variable|
|Wri||Total number of writes to variable|
|†||Dead reads or writes. These instructions are not executed at run-time.|
|×||Exposed reads or writes. These instructions were not found to execute, but they may execute from an external call.|
In the above example, variable varname is being read 3 times. 2 of the reads are in a live procedure and 1 read occurs in a dead procedure. The 1 dead read is not truly dead since it is in an exposed procedure. 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.
For each problematic variable, right-click the variable in the main window of Project Analyzer and bring up the References list. There you can see the actual list of reads/writes. Points to consider:
The Variable use report provides the same information as the Deadness of variables set of problem detection rules. Get the Variable use report to look for logic problems, missing functionality and useless computation.
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