rvasa / jseat

Automatically exported from code.google.com/p/jseat
0 stars 0 forks source link

Update Metric comparisons #23

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Background:
Currently we use a single enum such as ClassMetric to define all the 
metrics a class will store. Such as...

ClassMetric.FAN_OUT_COUNT,
ClassMetric.FAN_IN_COUNT,
ClassMetric.ILOAD_COUNT;
// ...
etc.

This is convenient for describing metrics in the system, but does not 
provide a classification of the type of metric. In build001 two categories 
of metrics are made; comparative metrics and distanceComputationMetrics.

We cannot simply create two different enums to describe the metrics 
because many metrics belong in both classifications. This would lead to 
inconsistent and unexpected use.

Two examples of where the distinction between metric classification 
becomes important.
Example 1:

public int computeModifiedMetrics(ClassMetricData cmd)
// This should compute modified metrics only from our base comparative 
metric set.

Example 2:
public double distanceFrom(ClassMetricData cmd, ClassMetricData cmd2)
// This should compute the distance moved from cmd to cmd2. This should be 
performed only on distance computation metrics.

Proposed Solution:
One way to address this would be to store metrics as a EnumMap<T, T> where 
T is the generic type, such as ClassMetric or MethodMetric. EnumMap's are 
very efficient at storing enums (much more so than a standard map). They 
were specifically implemented for storing enum bit values and are thus 
very fast.

Two methods would need to be added to the ClassMetric vocabulary type.

public boolean isComparativeMetric();
public boolean isDistanceMetric();

Our MetricData class would implement a Set<ClassMetric> getMetrics() to 
retrieve the metric set.

Each metric would then be defined as either a comparative metric, distance 
or both.

// A comparison of distance metrics could be performed similar to:
for (ClassMetric metric : cm.metrics)
{
  if (metric.isDistanceMetric()) // Only compare distance metrics.
    return cm.getSimpleMetric(metric) == cm2.getSimpleMetric(metric)
}

Original issue reported on code.google.com by jtha...@gmail.com on 31 Aug 2007 at 6:27

GoogleCodeExporter commented 9 years ago
Another alternative would be to leave the current implementation and storage of 
metrics as a simple int[] and to write a wrapper class for performing metric 
comparison. i.e. Some sort of utility class.

This would also have to perform the distance comparisons, number of modified 
metrics 
etc. To support  this, a new enum would be created to configure which metrics 
are 
compared in such comparisons.

MetricType.COMPARATIVE,
MetricType.DISTANCE;

class MetricUtil()
{
   // Compares the entire contents of the two metric sets for equality.
   public static boolean equal(int[] metrics, int[] metrics2);

   // Compares the 'type' contents of the two metric sets for equality.
   public static boolean equal(int[] metrics, int[] metrics2, MetricType type);

   // The distance from metrics to metrics2
   public static double distanceFrom(int[] metrics, int[] metrics2);

   // The distance from metrics and metrics2, using MetricType for comparison.
   public static double distanceFrom(int[] metrics, int[] metrics2, MetricType type);

   // The number of different metrics between metrics and metrics2
   public static int modifiedMetrics(int[] metrics, int[] metrics2);

   // The number of different metrics (that are of the specified type)
   // between metrics and metrics2
   public static int modifiedMetrics(int[] metrics, int[] metrics2, MetricType type);
}

Using an example from the initial issue article the class would use the utility 
to 
perform the comparison instead of doing it itself.

Example 2:

// This should compute the distance moved from cmd to cmd2. This should be 
// performed only on distance computation metrics.
public double distanceFrom(ClassMetricData cmd, ClassMetricData cmd2)
{
   return MetricUtils.distanceFrom(cmd.getMetrics(), cmd2.getMetrics(), 
MetricType.DISTANCE);
}

Original comment by jtha...@gmail.com on 31 Aug 2007 at 6:50

GoogleCodeExporter commented 9 years ago
After further thought I think I will implement the metric utility class. Whilst 
enums in Java are glorified classes that can easily encapsulate all this 
information 
from an implementation point of view the utility class will be easier to 
implement 
because it has no impact on the rest of the system added as is.

Changing the metric representation at the storage level would proliferate 
changes 
through other parts of the systems such as persistence.

Original comment by jtha...@gmail.com on 31 Aug 2007 at 6:58

GoogleCodeExporter commented 9 years ago
Looking at the two groupings of metrics in build001 I'm puzzled as to how they 
were 
made.

I am referring to...
public final String[] metrics =  {"branchCount", ...}
public final String[] distanceComputationMetrics =  {"branchCount", ...}

For example, the metrics staticMethodCount, sycnrhonizedMethodCount and 
finalMethodCount are not part of the distanceComputationmetrics. But 
abstractMethodCount is. This seems odd, is this a mistake?

These lists have not been updated with any of the newer metrics that have been 
added. Is this on purpose? There are many, many metrics not in either set and 
are 
thus not looked at during metric comparisons. Some of which, seem that they 
should 
be used during class equality/clone checks for example.

So far I am treating them as follows....
MetricType.COMPARATIVE // Only in the comparative metric set
MetricType.DISTANCE // Only in the distannce metric set.
MetricType.ANY // In both
MetricType.NOT_COMPARABLE // Not used for comparison purposes.

Original comment by jtha...@gmail.com on 31 Aug 2007 at 7:31