The Modularity Principle states that programs should be
built from cohesive, loosely coupled modules.
Module A is coupled to module B if A depends on B.
A depends on B if changes to B might require changes to A.
Intuitively, A and B are loosely coupled if the probability
that changes to B will require changes to A is low. This happens, for example,
if only a small part of A depends on a small part of B.
Note that this is a transitive relationship:
A depends on A.
If A depends on B and B depends on C, then A depends on C.
Module A references module B, if B appears in the implementation of A.
For example, if A and B are classes, then B might appear as the type of a field, parameter, local, or super class:
class A extends B {
B someField;
B someMethod(B someParameter) {
B someLocal;
// etc.
}
}
A references B implies that A depends on B, but not the reverse. For example, A may not reference B, but it may reference C, which references B, and so A depends on C, which depends on B, hence by transitivity, A depends on B.
The UML dependency arrow is meant to represent the idea of dependency between classes, packages, components, and other UML elements:
Note that realization, generalization, and association arrows are all special cases of the dependency arrow.
However, if we take into account the transitivity of dependence, then showing all of the dependencies between UML elements could become cumbersome:
Therefore, in these notes we will use the UML dependency arrow to denote the references relationship.
Let p be a program
or a package. In the dependency graph of p—DG(p)—the
nodes are the classes and interfaces in p. A (dashed) arrow connects node A to
node B if A references B.
A class diagram
for p is a special case of DG(p).
Assume package p
contains the classes A, B, C, D, and E:
package p;
class A extends C {
B field1;
...
}
class B {
C field2;
...
}
class C extends D {
E field2;
...
}
class D { ... }
class E extends B {
...
}
Here's DG(p):
providers(A) = the number of classes that A references
clients(A) = the number of classes that reference A
providers*(A) = encumbrance(A) = the number of classes that A depends on.
clients*(A) = the number of classes that depend on A