I keep seeing developers extracting coupled logics into new classes, which reduces the cohesion of objects and makes objects tightly coupled to each other. This article describes a way to check the cohesion of the code in an object and the coupling between objects, which helps developers check whether the refactoring improves the cleanness of the code or not.
Please note that it can not be applied to pure functional programming.
Cohesion
VF = number of private fields (no non-private getter or setter, not a property)OF = number of non-private fieldsU = number of usage of fields by public methods (count 1 per public method per field)M = number of public methodsC = cohesiveness (0 to 1, 0 means the worst, 1 means the best)C = U / ((M + OF) * (VF + OF))
Other rules:
- protected counts as private
- Calculation includes all fields and methods in the parent classes (except Object)
Coupling/Independence
F = number of fields (both private and non-private) as:F = VF + OFR = number of referencesP = coupling factor (0 to 1, 0 means no coupling, 1 means fully coupled to others)P = R / FI = factor of independenceI = 1 - P
Examples:
1. Full cohesion:
public class Example {private final String value; // VF: +1public Example(String value) {this.value = value;}public int m1() { // M: +1return value.length(); // U: +1}}// C = 1/((1 + 0) * (1 + 0)) = 1
2. No cohesion:
public class Example {private final String value; // OF: +1public Example(String value) {this.value = value;}public String getValue() { // M: does not countreturn value; // U: does not count}}// C = 0/((1 + 0) * (1 + 0)) = 0
3. Half cohesion:
public class Example {private final String value; // OF: +1public Example(String value) {this.value = value;}public String getValue() { // M: does not countreturn value; // U: does not count}public int m1() { // M: +1return value.length() + value.indexOf("a"); // U: +1}}// C = 1/((1 + 1) * (1 + 0)) = 0.5
4. Coupling:
public class Reference {public int findI() {return 1;}}public class Example {private final Reference r1; // F: +1 & R: +1public Example(Reference r1) {this.r1 = r1;}public int m1() {return r1.findI();}}// P = 1/1 = 1// I = 0
5. Mix
public abstract class Parent {protected final int a; // VF: +1public Parent(int a) {this.a = a;}}public class Reference {public int findI() {return 1;}}public class Example extends Parent {public final String f1; // OF: +1private final String f2; // OF: +1public String getF2() {return f2;}private final String f3; // VF: +1;private final Reference r1; // VF: +1; R: +1public Example(String f1, String f2, String f3, int a, Reference r1) {super(a);this.f1 = f1;this.f2 = f2;this.f3 = f3;this.r1 = r1;}public int m1() { // M: +1return l() + a + r1.findI(); // U: +3 (f3, a, r1)}private int l() {return f3.length();}}// C (Example) = 3/((1 + 2)*(3 + 2)) = 0.2// I (Example) = 1 - 1/(2 + 3) = 0.8
No comments:
Post a Comment