-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathMetricNamespace.qll
More file actions
113 lines (107 loc) · 3.56 KB
/
MetricNamespace.qll
File metadata and controls
113 lines (107 loc) · 3.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import cpp
/**
* A wrapper that provides metrics for a C/C++ namespace.
*/
class MetricNamespace extends Namespace {
/** Gets the number of incoming dependencies from other namespaces. */
int getAfferentCoupling() {
result = count(MetricNamespace that | that.getANamespaceDependency() = this)
}
/** Gets the number of outgoing dependencies on other namespaces. */
int getEfferentCoupling() {
result = count(MetricNamespace that | this.getANamespaceDependency() = that)
}
/**
* Gets the _instability_ of this namespace. Instability is a measure of how
* likely a namespace is to be influenced by changes to other namespace. If
* this metric value is high, it is easily influenced, if it is low, the
* impact is likely to be minimal. Instability is estimated as the number of
* outgoing dependencies relative to the total number of dependencies.
*/
float getInstability() {
exists(int ecoupling, int sumcoupling |
ecoupling = this.getEfferentCoupling() and
sumcoupling = ecoupling + this.getAfferentCoupling() and
sumcoupling > 0 and
result = ecoupling / sumcoupling.(float)
)
}
/**
* Gets the _abstractness_ of this namespace. Abstractness measures the
* proportion of abstract classes in a namespace relative to the total number
* of classes in that namespace. A highly abstract namespace (where the
* metric value is close 1) that is furthermore instable is likely to be
* useless: the class hierarchy has been over-engineered, and all those
* abstract classes are not heavily used.
*/
float getAbstractness() {
exists(int i, int j |
i = count(Class c | c.getNamespace() = this) and
j =
count(Class c |
c.getNamespace() = this and
c.isAbstract()
) and
result = j / i.(float) and
i > 0
)
}
/**
* Gets the _distance from main sequence_ of this namespace. This measure
* intends to capture the tradeoff between abstractness and instability: the
* ideal situation occurs when the sum of abstractness and instability is
* one. That is, a namespace is completely abstract and stable
* (abstractness=1 and instability=0) or it is concrete and instable
* (abstractness=0 and instability=1). We thus measure the distance from that
* ideal situation.
*/
float getDistanceFromMain() {
exists(float r |
r = this.getAbstractness() + this.getInstability() - 1 and
(
r >= 0 and result = r
or
r < 0 and result = -r
)
)
}
/** Gets a namespace dependency of this element. */
MetricNamespace getANamespaceDependency() {
exists(MetricClass c |
c.getNamespace() = this and
c.getAClassDependency().getNamespace() = result
)
or
exists(FunctionCall c |
c.getEnclosingFunction().getNamespace() = this and
c.getTarget().getNamespace() = result
)
or
exists(FunctionCall c |
c.getEnclosingVariable().getNamespace() = this and
c.getTarget().getNamespace() = result
)
or
exists(Access a |
a.getEnclosingFunction().getNamespace() = this and
a.getTarget().getNamespace() = result
)
or
exists(Access a |
a.getEnclosingVariable().getNamespace() = this and
a.getTarget().getNamespace() = result
)
or
exists(Variable v, UserType t |
v.getNamespace() = this and
v.getType().refersTo(t) and
t.getNamespace() = result
)
or
exists(Function f, UserType t |
f.getNamespace() = this and
f.getType().refersTo(t) and
t.getNamespace() = result
)
}
}