metrics: move up values method in Metric interface
authorAlexandre Terrasa <alexandre@moz-code.org>
Fri, 7 Mar 2014 06:10:14 +0000 (01:10 -0500)
committerAlexandre Terrasa <alexandre@moz-code.org>
Fri, 7 Mar 2014 06:10:14 +0000 (01:10 -0500)
Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

src/metrics/inheritance_metrics.nit
src/metrics/mclasses_metrics.nit
src/metrics/metrics_base.nit
src/metrics/mmodules_metrics.nit

index 5e7f21f..a9f3247 100644 (file)
@@ -64,21 +64,25 @@ private class InheritanceMetricsPhase
                                mclasses.add_all(mod_mclasses)
                                cmetrics.collect(new HashSet[MClass].from(mod_mclasses), mainmodule)
                                for name, metric in cmetrics.metrics do
-                                       print toolcontext.format_h4("\t{name}: {metric.desc}")
-                                       print toolcontext.format_p("\t    avg: {metric.avg}")
-                                       var max = metric.max
-                                       print toolcontext.format_p("\t    max: {max.first} ({max.second})")
-                                       var min = metric.min
-                                       print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                                       if metric isa IntMetric then
+                                               print toolcontext.format_h4("\t{name}: {metric.desc}")
+                                               print toolcontext.format_p("\t    avg: {metric.avg}")
+                                               var max = metric.max
+                                               print toolcontext.format_p("\t    max: {max.first} ({max.second})")
+                                               var min = metric.min
+                                               print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                                       end
                                end
                                hmetrics.collect(new HashSet[MModule].from(mgroup.mmodules), mainmodule)
                                for name, metric in hmetrics.metrics do
-                                       print toolcontext.format_h4("\t{name}: {metric.desc}")
-                                       print toolcontext.format_p("\t    avg: {metric.avg}")
-                                       var max = metric.max
-                                       print toolcontext.format_p("\t    max: {max.first} ({max.second})")
-                                       var min = metric.min
-                                       print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                                       if metric isa FloatMetric then
+                                               print toolcontext.format_h4("\t{name}: {metric.desc}")
+                                               print toolcontext.format_p("\t    avg: {metric.avg}")
+                                               var max = metric.max
+                                               print toolcontext.format_p("\t    max: {max.first} ({max.second})")
+                                               var min = metric.min
+                                               print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                                       end
                                end
                        end
                end
@@ -87,21 +91,25 @@ private class InheritanceMetricsPhase
                        print toolcontext.format_h2("\n ## global metrics")
                        cmetrics.collect(mclasses, mainmodule)
                        for name, metric in cmetrics.metrics do
-                               print toolcontext.format_h4("\t{name}: {metric.desc}")
-                               print toolcontext.format_p("\t    avg: {metric.avg}")
-                               var max = metric.max
-                               print toolcontext.format_p("\t    max: {max.first} ({max.second})")
-                               var min = metric.min
-                               print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                               if metric isa IntMetric then
+                                       print toolcontext.format_h4("\t{name}: {metric.desc}")
+                                       print toolcontext.format_p("\t    avg: {metric.avg}")
+                                       var max = metric.max
+                                       print toolcontext.format_p("\t    max: {max.first} ({max.second})")
+                                       var min = metric.min
+                                       print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                               end
                        end
                        hmetrics.collect(mmodules, mainmodule)
                        for name, metric in hmetrics.metrics do
-                               print toolcontext.format_h4("\t{name}: {metric.desc}")
-                               print toolcontext.format_p("\t    avg: {metric.avg}")
-                               var max = metric.max
-                               print toolcontext.format_p("\t    max: {max.first} ({max.second})")
-                               var min = metric.min
-                               print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                               if metric isa FloatMetric then
+                                       print toolcontext.format_h4("\t{name}: {metric.desc}")
+                                       print toolcontext.format_p("\t    avg: {metric.avg}")
+                                       var max = metric.max
+                                       print toolcontext.format_p("\t    max: {max.first} ({max.second})")
+                                       var min = metric.min
+                                       print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                               end
                        end
                end
        end
@@ -110,7 +118,7 @@ end
 # Metric Set used to collect data about inheritance in each module
 class InheritanceMetricSet
        super MetricSet
-       redef type METRIC: InheritanceMetric
+       redef type METRIC: MModuleMetric
        fun collect(mmodules: Set[MModule], mainmodule: MModule) do
                clear
                for metric in metrics.values do
@@ -121,19 +129,12 @@ class InheritanceMetricSet
        end
 end
 
-# An abstract metric used to collect data about inheritance usage
-#
-# The metric is based on a module
-abstract class InheritanceMetric
-       super FloatMetric[MModule]
-       fun collect(mmodule: MModule, mainmodule: MModule) is abstract
-end
-
 # Module metric: proportion of MClasses Defined Using Inheritance
 #
 # Count MClasses that have another parents than Object
 class MDUI
-       super InheritanceMetric
+       super MModuleMetric
+       super FloatMetric
        redef fun name do return "mdui"
        redef fun desc do return "proportion of mclass defined using inheritance (has other parent than Object)"
 
@@ -154,7 +155,8 @@ end
 #
 # Count classes that have another parents than Object
 class MDUIC
-       super InheritanceMetric
+       super MModuleMetric
+       super FloatMetric
        redef fun name do return "mduic"
        redef fun desc do return "proportion of class_kind defined using inheritance"
 
@@ -179,7 +181,8 @@ end
 #
 # Count interface that have another parents than Object
 class MDUII
-       super InheritanceMetric
+       super MModuleMetric
+       super FloatMetric
        redef fun name do return "mduii"
        redef fun desc do return "proportion of interface_kind defined using inheritance"
 
@@ -204,7 +207,8 @@ end
 #
 # Count classes that have at least a child
 class MIF
-       super InheritanceMetric
+       super MModuleMetric
+       super FloatMetric
        redef fun name do return "mif"
        redef fun desc do return "proportion of mclass inherited from"
 
@@ -225,7 +229,8 @@ end
 #
 # Count classes that have at least a child
 class MIFC
-       super InheritanceMetric
+       super MModuleMetric
+       super FloatMetric
        redef fun name do return "mifc"
        redef fun desc do return "proportion of class_kind inherited from"
 
@@ -250,7 +255,8 @@ end
 #
 # Count interfaces that have at least a child
 class MIFI
-       super InheritanceMetric
+       super MModuleMetric
+       super FloatMetric
        redef fun name do return "mifi"
        redef fun desc do return "proportion of interface_kind inherited from"
 
@@ -276,6 +282,7 @@ end
 # Count only absrtract, concrete and extern classes
 class CNOAC
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnoac"
        redef fun desc do return "number of class_kind ancestor"
 
@@ -296,6 +303,7 @@ end
 # Count only absrtract, concrete and extern classes
 class CNOPC
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnopc"
        redef fun desc do return "number of class_kind parent"
 
@@ -316,6 +324,7 @@ end
 # Count only absrtract, concrete and extern classes
 class CNOCC
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnocc"
        redef fun desc do return "number of class_kind children"
 
@@ -336,6 +345,7 @@ end
 # Count only absrtract, concrete and extern classes
 class CNODC
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnodc"
        redef fun desc do return "number of class_kind descendants"
 
@@ -356,6 +366,7 @@ end
 # Count only interfaces
 class CNOAI
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnoai"
        redef fun desc do return "number of interface_kind ancestor"
 
@@ -376,6 +387,7 @@ end
 # Count only interfaces
 class CNOPI
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnopi"
        redef fun desc do return "number of interface_kind parent"
 
@@ -396,6 +408,7 @@ end
 # Count only interfaces
 class CNOCI
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnoci"
        redef fun desc do return "number of interface_kind children"
 
@@ -416,6 +429,7 @@ end
 # Count only interfaces
 class CNODI
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnodi"
        redef fun desc do return "number of interface_kind descendants"
 
@@ -436,6 +450,7 @@ end
 # Following the longest path composed only of extends edges from self to Object
 class CDITC
        super MClassMetric
+       super IntMetric
        redef fun name do return "cditc"
        redef fun desc do return "depth in class tree following only class, abstract, extern kind"
 
@@ -449,6 +464,7 @@ end
 # Following the longest path composed only of implements edges from self to Object
 class CDITI
        super MClassMetric
+       super IntMetric
        redef fun name do return "cditi"
        redef fun desc do return "depth in class tree following only interface_kind"
 
index 5babf79..69a1063 100644 (file)
@@ -62,12 +62,14 @@ private class MClassesMetricsPhase
                                mclasses.add_all(mod_mclasses)
                                metrics.collect(new HashSet[MClass].from(mod_mclasses), mainmodule)
                                for name, metric in metrics.metrics do
-                                       print toolcontext.format_h4("\t{name}: {metric.desc}")
-                                       print toolcontext.format_p("\t    avg: {metric.avg}")
-                                       var max = metric.max
-                                       print toolcontext.format_p("\t    max: {max.first} ({max.second})")
-                                       var min = metric.min
-                                       print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                                       if metric isa IntMetric then
+                                               print toolcontext.format_h4("\t{name}: {metric.desc}")
+                                               print toolcontext.format_p("\t    avg: {metric.avg}")
+                                               var max = metric.max
+                                               print toolcontext.format_p("\t    max: {max.first} ({max.second})")
+                                               var min = metric.min
+                                               print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                                       end
                                end
                        end
                end
@@ -77,12 +79,14 @@ private class MClassesMetricsPhase
 
                        metrics.collect(mclasses, mainmodule)
                        for name, metric in metrics.metrics do
-                               print toolcontext.format_h4("\t{name}: {metric.desc}")
-                               print toolcontext.format_p("\t    avg: {metric.avg}")
-                               var max = metric.max
-                               print toolcontext.format_p("\t    max: {max.first} ({max.second})")
-                               var min = metric.min
-                               print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                               if metric isa IntMetric then
+                                       print toolcontext.format_h4("\t{name}: {metric.desc}")
+                                       print toolcontext.format_p("\t    avg: {metric.avg}")
+                                       var max = metric.max
+                                       print toolcontext.format_p("\t    max: {max.first} ({max.second})")
+                                       var min = metric.min
+                                       print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                               end
                        end
                end
        end
@@ -104,9 +108,11 @@ class MClassMetricSet
        end
 end
 
-# An abstract metric about MClass
-abstract class MClassMetric
-       super IntMetric[MClass]
+# A metric about MClass
+interface MClassMetric
+       super Metric
+       redef type ELM: MClass
+
        # Collect the metric value for this mclass
        fun collect(mclass: MClass, mainmodule: MModule) is abstract
 end
@@ -114,6 +120,7 @@ end
 # Class Metric: Number of Ancestors
 class CNOA
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnoa"
        redef fun desc do return "number of ancestor classes"
 
@@ -125,6 +132,7 @@ end
 # Class Metric: Number of Parents
 class CNOP
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnop"
        redef fun desc do return "number of parent classes"
 
@@ -136,6 +144,7 @@ end
 # Class Metric: Number of Children
 class CNOC
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnoc"
        redef fun desc do return "number of child classes"
 
@@ -147,6 +156,7 @@ end
 # Class Metric: Number of Descendants
 class CNOD
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnod"
        redef fun desc do return "number of descendant classes"
 
@@ -158,6 +168,7 @@ end
 # Class Metric: Depth in Inheritance Tree
 class CDIT
        super MClassMetric
+       super IntMetric
        redef fun name do return "cdit"
        redef fun desc do return "depth in class tree"
 
@@ -169,6 +180,7 @@ end
 # Class Metric: Number of Introduced MProperties
 class CNBIP
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnbip"
        redef fun desc do return "number of introduced properties"
 
@@ -183,6 +195,7 @@ end
 # Class Metric: Number of Refined MProperties
 class CNBRP
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnbrp"
        redef fun desc do return "number of redefined properties"
 
@@ -197,6 +210,7 @@ end
 # Class Metric: Number of Inherited MProperties
 class CNBHP
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnbhp"
        redef fun desc do return "number of inherited properties"
 
index 77878a9..f5f9589 100644 (file)
@@ -141,82 +141,106 @@ end
 #
 # The concept is reified here for a better organization and documentation
 interface Metric
+       type ELM: Object
+       type VAL: Object
+       type RES: Map[ELM, VAL]
+
        fun name: String is abstract
        fun desc: String is abstract
-       # clear all results for this metric
+
+       # Clear all results for this metric
        fun clear is abstract
+
+       # Values for each element
+       fun values: RES is abstract
+
+
+       # The value calculated for the element
+       fun [](element: ELM): VAL do return values[element]
+
+       # Does the element have a value for this metric?
+       fun has_element(element: ELM): Bool do return values.has_key(element)
+
+       # The values average
+       fun avg: Float is abstract
 end
 
 # A Metric that collects integer data
 #
 # Used to count things
-class IntMetric[E: Object]
+class IntMetric
        super Metric
 
-       var values = new Counter[E]
+       redef type VAL: Int
+       redef type RES: Counter[ELM]
+
+       protected var values_cache = new Counter[ELM]
+       redef fun values do return values_cache
 
-       redef fun clear do values.clear
+       redef fun clear do values_cache.clear
 
        # Return the couple with the highest value
-       fun max: Couple[E, Int] do
-               assert not values.is_empty
-               var elem = values.max.as(not null)
-               var value = values[elem]
-               return new Couple[E, Int](elem, value)
+       fun max: Couple[ELM, Int] do
+               assert not values_cache.is_empty
+               var elem = values_cache.max.as(not null)
+               var value = values_cache[elem]
+               return new Couple[ELM, Int](elem, value)
        end
 
        # Return the couple with the lowest value
-       fun min: Couple[E, Int] do
-               assert not values.is_empty
-               var elem = values.min.as(not null)
-               var value = values[elem]
-               return new Couple[E, Int](elem, value)
+       fun min: Couple[ELM, Int] do
+               assert not values_cache.is_empty
+               var elem = values_cache.min.as(not null)
+               var value = values_cache[elem]
+               return new Couple[ELM, Int](elem, value)
        end
 
        # Values average
-       fun avg: Float do return values.avg
+       redef fun avg: Float do return values_cache.avg
 end
 
 # A Metric that collects float datas
 #
 # Used sor summarization
-class FloatMetric[E: Object]
+class FloatMetric
        super Metric
 
-       var values: Map[E, Float] = new HashMap[E, Float]
+       redef type VAL: Float
+
+       protected var values_cache = new HashMap[ELM, VAL]
+       redef fun values do return values_cache
 
-       redef fun clear do values.clear
+       redef fun clear do values_cache.clear
 
        # Return the couple with the highest value
-       fun max: Couple[E, Float] do
+       fun max: Couple[ELM, Float] do
                assert not values.is_empty
                var max: nullable Float = null
-               var elem: nullable E = null
+               var elem: nullable ELM = null
                for e, v in values do
                        if max == null or v > max then
                                max = v
                                elem = e
                        end
                end
-               return new Couple[E, Float](elem.as(not null), max.as(not null))
+               return new Couple[ELM, Float](elem.as(not null), max.as(not null))
        end
 
        # Return the couple with the lowest value
-       fun min: Couple[E, Float] do
+       fun min: Couple[ELM, Float] do
                assert not values.is_empty
                var min: nullable Float = null
-               var elem: nullable E = null
+               var elem: nullable ELM = null
                for e, v in values do
                        if min == null or v < min then
                                min = v
                                elem = e
                        end
                end
-               return new Couple[E, Float](elem.as(not null), min.as(not null))
+               return new Couple[ELM, Float](elem.as(not null), min.as(not null))
        end
 
-       # Values average
-       fun avg: Float do
+       redef fun avg do
                if values.is_empty then return 0.0
                var sum = 0.0
                for value in values.values do
index fc3a781..4075280 100644 (file)
@@ -54,12 +54,14 @@ private class MModulesMetricsPhase
                                mmodules.add_all(mgroup.mmodules)
                                metrics.collect(new HashSet[MModule].from(mgroup.mmodules), mainmodule)
                                for name, metric in metrics.metrics do
-                                       print toolcontext.format_h4("\t{name}: {metric.desc}")
-                                       print toolcontext.format_p("\t    avg: {metric.avg}")
-                                       var max = metric.max
-                                       print  toolcontext.format_p("\t    max: {max.first} ({max.second})")
-                                       var min = metric.min
-                                       print  toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                                       if metric isa IntMetric then
+                                               print toolcontext.format_h4("\t{name}: {metric.desc}")
+                                               print toolcontext.format_p("\t    avg: {metric.avg}")
+                                               var max = metric.max
+                                               print  toolcontext.format_p("\t    max: {max.first} ({max.second})")
+                                               var min = metric.min
+                                               print  toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                                       end
                                end
                        end
                end
@@ -69,12 +71,14 @@ private class MModulesMetricsPhase
 
                        metrics.collect(mmodules, mainmodule)
                        for name, metric in metrics.metrics do
-                               print toolcontext.format_h4( "\t{name}: {metric.desc}")
-                               print  toolcontext.format_p("\t    avg: {metric.avg}")
-                               var max = metric.max
-                               print  toolcontext.format_p("\t    max: {max.first} ({max.second})")
-                               var min = metric.min
-                               print  toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                               if metric isa IntMetric then
+                                       print toolcontext.format_h4( "\t{name}: {metric.desc}")
+                                       print  toolcontext.format_p("\t    avg: {metric.avg}")
+                                       var max = metric.max
+                                               print  toolcontext.format_p("\t    max: {max.first} ({max.second})")
+                                       var min = metric.min
+                                       print  toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                               end
                        end
                end
        end
@@ -98,7 +102,8 @@ end
 
 # An abstract Metric on MModules
 abstract class MModuleMetric
-       super IntMetric[MModule]
+       super Metric
+       redef type ELM: MModule
        # Collect the metric on the MModule
        #
        # Results are stored in the property `values`
@@ -108,6 +113,7 @@ end
 # Module Metric: Number of Ancestors
 class MNOA
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnoa"
        redef fun desc do return "number of ancestor modules"
 
@@ -119,6 +125,7 @@ end
 # Module Metric: Number of Parents
 class MNOP
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnop"
        redef fun desc do return "number of parent modules"
 
@@ -130,6 +137,7 @@ end
 # Module Metric: Number of Children
 class MNOC
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnoc"
        redef fun desc do return "number of child modules"
 
@@ -141,6 +149,7 @@ end
 # Module Metric: Number of Descendants
 class MNOD
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnod"
        redef fun desc do return "number of descendant modules"
 
@@ -152,6 +161,7 @@ end
 # Module Metric: Depth in Tree
 class MDIT
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mdit"
        redef fun desc do return "depth in module tree"
 
@@ -165,6 +175,7 @@ end
 # count all mclasses introduced by the module
 class MNBI
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnbi"
        redef fun desc do return "number of introduction in module"
 
@@ -178,70 +189,80 @@ end
 # count all mclasses refined in the module
 class MNBR
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnbr"
        redef fun desc do return "number of refinement in module"
 
        redef fun collect(mmodule, main) do
-               values[mmodule] = 0
+               var value = 0
                for mclassdef in mmodule.mclassdefs do
-                       if not mclassdef.is_intro then values.inc(mmodule)
+                       if not mclassdef.is_intro then value += 1
                end
+               values[mmodule] = value
        end
 end
 
 # Module Metric: Number of Concrete Class in module (intro + redef)
 class MNBCC
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnbcc"
        redef fun desc do return "number of concrete class in module (intro + redef)"
 
        redef fun collect(mmodule, main) do
-               values[mmodule] = 0
+               var value = 0
                for mclassdef in mmodule.mclassdefs do
-                       if mclassdef.mclass.kind == concrete_kind then values.inc(mmodule)
+                       if mclassdef.mclass.kind == concrete_kind then value += 1
                end
+               values[mmodule] = value
        end
 end
 
 # Module Metric: Number of Abstract Class in module (intro + redef)
 class MNBAC
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnbac"
        redef fun desc do return "number of abstract class in module (intro + redef)"
 
        redef fun collect(mmodule, main) do
-               values[mmodule] = 0
+               var value = 0
                for mclassdef in mmodule.mclassdefs do
-                       if mclassdef.mclass.kind == abstract_kind then values.inc(mmodule)
+                       if mclassdef.mclass.kind == abstract_kind then value += 1
                end
+               values[mmodule] = value
        end
 end
 
 # Module Metric: Number of Interface in module (intro + redef)
 class MNBIC
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnbic"
        redef fun desc do return "number of interface in module (intro + redef)"
 
        redef fun collect(mmodule, main) do
-               values[mmodule] = 0
+               var value = 0
                for mclassdef in mmodule.mclassdefs do
-                       if mclassdef.mclass.kind == interface_kind then values.inc(mmodule)
+                       if mclassdef.mclass.kind == interface_kind then value += 1
                end
+               values[mmodule] = value
        end
 end
 
 # Module Metric: Number of Enum in module (intro + redef)
 class MNBEC
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnbec"
        redef fun desc do return "number of enum in module (intro + redef)"
 
        redef fun collect(mmodule, main) do
-               values[mmodule] = 0
+               var value = 0
                for mclassdef in mmodule.mclassdefs do
-                       if mclassdef.mclass.kind == enum_kind then values.inc(mmodule)
+                       if mclassdef.mclass.kind == enum_kind then value += 1
                end
+               values[mmodule] = value
        end
 end