Part of a series on how software architecture shapes AI driven code degradation. This post explains a group of measurements on their own. Each metric gets its definition, its figure, and its numbers.
Lack of cohesion, average class (LCOM)
ck_lcom_mean · ↓ lower is better · Chidamber & Kemerer 1994, via the CK tool
Line is the mean of ten runs. Band is one standard deviation. Click for full size.
Counts the method pairs in a class that share no field, against the pairs that do. A class whose methods all touch the same state is one idea. A class whose methods touch disjoint state is several classes wearing one name. This is the numeric version of what the plain-English cohesion prompt asked for in words.
ck_lcom_mean = mean over classes of LCOM(C)
Where. P is the set of method pairs in C whose accessed-field sets are disjoint. Q is the set of pairs that share at least one field. Low is cohesive. The measure is unbounded above and grows roughly with the square of the method count, so a large class is penalised twice: once for incoherence and once for being large.
In this harness. Computed by the CK tool, which parses source with Eclipse JDT. Only declared source classes are seen: library types are not, and neither is anything the parser fails on, so the class count in the validity group is worth checking beside any CK figure. The harness reads CK's per-class LCOM column and takes the mean, and separately the maximum.
How to read it. The natural place to check whether asking the agent for cohesion actually produced it.
Lack of cohesion, worst class
ck_lcom_max · ↓ lower is better · C&K 1994, via CK
Line is the mean of ten runs. Band is one standard deviation. Click for full size.
The least cohesive class in the codebase. Unlike the mean it cannot be diluted by adding cohesive classes, so it answers whether there is a junk-drawer class in here, rather than whether classes are cohesive on average.
Where. Same LCOM as above. Because it is unbounded and grows with method count, the worst class is often simply the largest one, so read it beside the class-weight concentration index.
In this harness. Computed by the CK tool, which parses source with Eclipse JDT. Only declared source classes are seen: library types are not, and neither is anything the parser fails on, so the class count in the validity group is worth checking beside any CK figure.
How to read it. A step change here means a junk drawer appeared.
Lack of cohesion, normalised (LCOM*)
ck_lcom_star_mean · ↓ lower is better · Henderson-Sellers 1996, via CK
Line is the mean of ten runs. Band is one standard deviation. Click for full size.
A redesign of LCOM that is bounded roughly to the range 0 to 1 and does not simply grow with the number of methods. Because it is normalised, a difference here is a difference in shape rather than in class size, which is exactly the correction the original LCOM needs.
Where. m is the number of methods in C and a the number of fields. μ(aj) is how many of those methods access field j. So the first term is the average number of methods per field. If every method touches every field the numerator is m − m = 0 and the result is 0, meaning perfectly cohesive. If each field is touched by exactly one method the result approaches 1. Low is cohesive. Undefined for a class with fewer than two methods or no fields.
In this harness. Computed by the CK tool, which parses source with Eclipse JDT. Only declared source classes are seen: library types are not, and neither is anything the parser fails on, so the class count in the validity group is worth checking beside any CK figure.
How to read it. The version to prefer when comparing arms whose classes differ in size.
Tight class cohesion (TCC)
ck_tcc_mean · ↑ higher is better · Bieman & Kang 1995, via CK
Line is the mean of ten runs. Band is one standard deviation. Click for full size.
The fraction of method pairs in a class that are directly connected through shared field access. It is reported precisely because its direction is inverted relative to LCOM: if a condition improves LCOM and worsens TCC, the improvement is an artefact of one definition rather than a real gain in cohesion.
Where. m is the number of visible methods. NP is therefore every possible pair of them. NDC is the number of pairs that are directly connected, meaning they access at least one instance variable in common. High is cohesive, which is the opposite sign to LCOM. Undefined, and blank, for a class with fewer than two methods.
In this harness. Computed by the CK tool, which parses source with Eclipse JDT. Only declared source classes are seen: library types are not, and neither is anything the parser fails on, so the class count in the validity group is worth checking beside any CK figure.
How to read it. Agreement with LCOM in the opposite direction is what makes a cohesion claim safe. Disagreement means one definition is doing the work.
Loose class cohesion (LCC)
ck_lcc_mean · ↑ higher is better · Bieman & Kang 1995, via CK
Line is the mean of ten runs. Band is one standard deviation. Click for full size.
The same as tight cohesion, but it also counts methods connected indirectly, through a chain of other methods. It is always at least as high as the tight version, and the gap between them is informative on its own.
Where. NIC is the number of pairs connected only indirectly: not sharing a field themselves, but linked through a chain of methods that do. NDC and NP are as in TCC. High is cohesive.
In this harness. Computed by the CK tool, which parses source with Eclipse JDT. Only declared source classes are seen: library types are not, and neither is anything the parser fails on, so the class count in the validity group is worth checking beside any CK figure.
How to read it. A large gap between LCC and TCC means the class holds together only through intermediaries, which is weaker cohesion than the LCC figure alone suggests.
Lack of cohesion of the handler class
ck_handler_lcom · ↓ lower is better · C&K 1994, via CK, pinned to the handler class
Line is the mean of ten runs. Band is one standard deviation. Click for full size.
Cohesion of the one class both architectures agree is the entry point. Codebase averages can be moved by adding files. This cannot.
Where. H is the handler class, matched by name in CK's per-class output. Same LCOM definition as the codebase mean. Low is cohesive.
In this harness. Computed by the CK tool, which parses source with Eclipse JDT. Only declared source classes are seen: library types are not, and neither is anything the parser fails on, so the class count in the validity group is worth checking beside any CK figure.
How to read it. The like-for-like cohesion comparison. A controller accumulating rules that touch disjoint state climbs here.
Tight cohesion of the handler class
ck_handler_tcc · ↑ higher is better · Bieman & Kang 1995, via CK, pinned to the handler class
Line is the mean of ten runs. Band is one standard deviation. Click for full size.
The inverted-sign cohesion check, on the handler class.
Where. Same TCC definition. High is cohesive. Undefined, and therefore blank, for a handler class with fewer than two methods, because there are no pairs to connect.
In this harness. Computed by the CK tool, which parses source with Eclipse JDT. Only declared source classes are seen: library types are not, and neither is anything the parser fails on, so the class count in the validity group is worth checking beside any CK figure.
How to read it. Sparse by construction in whichever arm keeps its handler minimal. The blanks are a result, not missing data: a handler with one method has no cohesion to measure.
Depth of inheritance tree
ck_dit_mean · ↓ lower is better · Chidamber & Kemerer 1994, via CK
Line is the mean of ten runs. Band is one standard deviation. Click for full size.
How deep the class hierarchy goes, on average. It is reported to show that neither architecture is achieving its structure through inheritance, which matters because none of the other metrics on this page would attribute complexity hidden in a hierarchy correctly.
ck_dit_mean = mean over classes of DIT(C)
Where. A class extending nothing has DIT = 1 in CK's convention, counting Object as the root. Interfaces implemented do not add depth.
In this harness. Computed by the CK tool, which parses source with Eclipse JDT. Only declared source classes are seen: library types are not, and neither is anything the parser fails on, so the class count in the validity group is worth checking beside any CK figure.
How to read it. Flat and low in both arms is the expected and desired result. A rise would mean complexity moved into a hierarchy.
No comments:
Post a Comment