Measuring dependencies with mete-tools

This gives the details regarding measuring dependences with mete-tools. The processing options section, while given first for convenience, will probably only make sense after reading the rest of this document.

Processing Options

There are several forms of measurement provide by mete-tools that are based on measuring dependencies first and then processing the results (a list will be provided here when the other forms are documented) but the fundamental form is given by the processing option Dependencies.

  None Immediate Raw
Text Frequency distribution in the standard format. The measurements are the number of dependencies from a module to a different module in the application. Options: 'all' — consider all outgoing dependencies of modules in the application, where they go to a module in the application or not. Frequency distribution listing modules with each measurement Options: 'all' — consider all outgoing dependencies of modules in the application, where they go to a module in the application or not. Two variants. Default is to list all details of all dependencies to other modules in the application (unless Option 'all' is specified). With Option 'short', give only (from, to, type, count) details, where 'count' is the number of dependencies with the same from, to, and type. Not affected by 'all'. (See example below.)
Html Standard HTML format Standard HTML format List is given in a table, with each part of the dependency in a cell. 'short' has no Html format.
For example, this will produce the list of dependencies in the "short" form.

  java -Doptions=short -Dprocessing=Dependencies \
      -Devidence=Raw -Dformat=Text -Dsource=Corpus -Dwarnings=None \
      -Xmx1000m -jar mete-tools.jar \
      /opt/QualitasCorpus-2008.6.3/Applications/jgraph/jgraph-5.10.2.0
The output produced is here. This shows that org.jgraph.JGraph has two occurrences where org.jgraph.event.GraphSelectionListener is used as the type of a parameter where as it has only one case where it invokes a method on org.jgraph.event.GraphSelectionListener.

See a more detailed example for more details.

Dependency

In a general sense a module X has a dependency on another module Y if knowledge of Y is required with compiling and/or executing code associated with X. Many dependencies can be identified by virtue of the presence of Y's name in the source of X (e.g., Y is the declared type of parameters, locals, use in an instanceof expression, and so on) however in some cases they will not be visible in the source, e.g., in

myObj.method(another.getValue()); 
the return type of the method getValue() is not visible in the source, however it is necessary to know the type in order to determine whether the call to method is legal (and, in the case of overloading, which method to call).

If there is a dependency between X and Y, then X is send to depend on Y and Y has X as a dependent. One module can depend on another in different ways, e.g., invoke a method on it, use it as a parameter type, use it in a cast expression.

Dependency attributes

A dependency, as represented by mete-tools, has the following attributes:
from The module the dependency is from (that is X in the discussion above).
to The module the dependency is to (Y).
type The way in which from depends on to. See the discussion below for more details.
targetID An indication of the part of the to module the dependency is to. For example, if a method in module A invokes a method methodB(int) on module B, then the targetID would be something like "methodB(int)". For a reference to a field, it will be the name of the field. If B is being used as the type of a parameter, then it might be "to whole module". The main intent of this is to allow similar looking dependencies to different parts of a module to be distinguished. For example, if A invokes two different methods on B, then without this attribute they could not be distinguished.
location A classification of the part of the from module the dependency occurs. See the discussion below for more details.
locationID More details regarding the location.
visibility A classification of how visible the dependency is. See the discussion below for more details.

Dependency Type

Below are the possible dependency types as recorded by mete-tools. The names mostly come from the bytecode equivalents, however there is no intention that they only be provided by jepends. The philosophy is that, if a type from this list can be determined by the instrument, then it should be recorded as such.
Extends The to module appears in the extends clause.
Implements The to module appears in the implements clause.
Parameter The to module appears as the type of a parameter.
Return The to module appears as a return type.
Throws The to module appears in a throws clause.
Field The to module appears as the type of a field.
Local The to module appears as the type of a local variable.
Catch The to module appears as the type of an exception in a catch clause.
Cast The to module appears in a cast expression.
Allocation The to module appears in a allocation ("new") expression.
Instanceof The to module appears in an instanceof expression.
InvokeStatic A static method is invoked on the to module.
InvokeVirtual A instance method is invoked on the to module (which is a class).
InvokeSpecial A constructor or private method is invoked on the to module.
InvokeInterface An instance method is invoked on the to module (which is an interface).
Get An instance field of to module is read from.
Put An instance field of the to module is written to.
GetStatic A static field of the to module is read from.
PutStatic A static field of to module is written to.
Nested The to module is nested within the from module.
Enclosing The to module encloses the from module.
Unknown Somehow a dependency to the to module was detected but the type could not be determined.

Dependency Location

Where in the from module the dependency occurs. Possible values are:-
Header In an implements or extends clause.
Initialiser In a static initialiser (<clinit>).
Constructor In a constructor.
Method In a method.
Field The type of a field. Note that initialisation of fields is recorded against constructors.
ConstantPool Found in the constant pool but nowhere else.

Dependency Visibility

How visible the dependency is. For example, the type of a parameter of a public method would be considered "public", and the type of a field with default access would be considered "default". Visibility is given with respect to the module the dependency comes from, so a public method in a default access class is considered public visibility. Public, Protected, Default, Private;

Instrument Limitations

jepends

When measurements are based on bytecode, as is the case with the jepends part of mete-tools, there is loss of precision when the bytecode does not include information that is present in the source code. Below are the known cases with respect to measuring dependencies.
Locals
Whether or not information about the types of local declarations is included in the bytecode depends on the compiler switches used during the compilation. This means that dependencies with type Local will not be reported. It is also possible that the fact that one module depends on another may be completely missed. For example:
   class A {
     ...
     public void method() {
       ...
       B aB;
       ...
     }
     ...
   }
If the only use of B is as shown, then it may be that it will not appear in the bytecode at all (as seems to be the case with both the Eclipse and Sun compilers). While this is unlikely looking code, it probably does happen, and so represents a difference between reality and what the tool measures.