Cohesion and coupling judged, RFC 0002 step 3 (0.20.0) #38

Merged
mi merged 1 commits from mihoe/cohesion-coupling-gate into main 2026-10-04 12:25:18 +02:00
Owner

Related Links

The Problem

Since PR#36 cohesion and coupling are measured and since PR#37 shown, but nothing kept a class from falling further apart or depending on ever more classes.
The first measurement of hsadmin-ng also showed that LCOM4 as published counts every method without state as a group of its own: of 66 classes with LCOM4 of 2 or more, most owed it to a toString through a static helper, a bean factory or the methods of an anonymous class.

The Scenarios

  • @MC-CK-010 a group of methods that uses no instance field at all does not count; a class with only such methods has no LCOM4.
  • @MC-CK-011 the gate judges LCOM4 and outgoing coupling against maxLcom4 and maxEfferentCoupling; a violation names class and dimension; a class exactly at a limit passes.
  • @MC-CK-012 a dimension without a limit is reported, not judged; without any limit the gate is inactive, as before.
Verified by
  • DesignAnalysisTest methodsWithoutStateDoNotCount
  • GateTest cohesionAndCouplingHaveLimitsOfTheirOwn, aDimensionWithoutALimitIsOnlyReported, classLimitsNeedTheSectionClasses
  • GateFunctionalTest cohesionAndCouplingLimitsReachTheGate

The Solution

  • Cohesion keeps only the groups that use an instance field.
  • GateConfig has the optional limits maxLcom4 and maxEfferentCoupling; the gate judges the methods only with maxMutationCrap and the classes only with one of the new limits.
    The failure line counts "limit(s) exceeded", as it now covers classes too.
  • The Gradle DSL has maxLcom4 and maxEfferentCoupling; a limit below its minimum fails the check with a message.
  • werkcrappit-pit applies the Gradle plugin 0.19.0, so its own city shows the metrics of step 2.
  • Version 0.20.0.

Follow-up PRs

  • Ratchets for werkcrappit itself, once 0.20.0 is released: maxLcom4 = 3, maxEfferentCoupling = 21.
  • hsadmin-ng, in its pilot branch: maxLcom4 = 4, maxEfferentCoupling = 26.

Attachments

LCOM4 and Ce, measured from the class files on 2026-10-04

LCOM4 max, as published → without stateless groups Classes with LCOM4 of 2 or more Ce max
hsadmin-ng (267 classes, generated code left out) 12 → 4 66 → 19 26 (HsAccountController)
werkcrappit-pit (58 classes) 3 → 3 9 → 4 21 (MutationCrapListener)

The top of hsadmin-ng now shows real candidates: HsOfficeContact (4) with its independent e-mail, phone and postal address, HsOfficeRelationSearchCriteria (4) with four independent search fields.

🤖 Generated with Claude Code

## Related Links - [RFC 0002](../rfcs/0002-cohesion-and-coupling.md), step 3; [PR#36](2026-10-04-PR%2336-cohesion-coupling-measured.md), [PR#37](2026-10-04-PR%2337-cohesion-coupling-city.md) ## The Problem Since PR#36 cohesion and coupling are measured and since PR#37 shown, but nothing kept a class from falling further apart or depending on ever more classes. The first measurement of hsadmin-ng also showed that LCOM4 as published counts every method without state as a group of its own: of 66 classes with LCOM4 of 2 or more, most owed it to a `toString` through a static helper, a bean factory or the methods of an anonymous class. ## The Scenarios - `@MC-CK-010` a group of methods that uses no instance field at all does not count; a class with only such methods has no LCOM4. - `@MC-CK-011` the gate judges LCOM4 and outgoing coupling against `maxLcom4` and `maxEfferentCoupling`; a violation names class and dimension; a class exactly at a limit passes. - `@MC-CK-012` a dimension without a limit is reported, not judged; without any limit the gate is inactive, as before. ##### Verified by - [DesignAnalysisTest](../../werkcrappit-pit/src/test/java/de/javagil/werkcrappit/pit/design/DesignAnalysisTest.java) `methodsWithoutStateDoNotCount` - [GateTest](../../werkcrappit-pit/src/test/java/de/javagil/werkcrappit/pit/gate/GateTest.java) `cohesionAndCouplingHaveLimitsOfTheirOwn`, `aDimensionWithoutALimitIsOnlyReported`, `classLimitsNeedTheSectionClasses` - [GateFunctionalTest](../../werkcrappit-gradle-plugin/src/functionalTest/java/de/javagil/werkcrappit/gradle/GateFunctionalTest.java) `cohesionAndCouplingLimitsReachTheGate` ## The Solution - `Cohesion` keeps only the groups that use an instance field. - `GateConfig` has the optional limits `maxLcom4` and `maxEfferentCoupling`; the gate judges the methods only with `maxMutationCrap` and the classes only with one of the new limits. The failure line counts "limit(s) exceeded", as it now covers classes too. - The Gradle DSL has `maxLcom4` and `maxEfferentCoupling`; a limit below its minimum fails the check with a message. - werkcrappit-pit applies the Gradle plugin 0.19.0, so its own city shows the metrics of step 2. - Version 0.20.0. ## Follow-up PRs - Ratchets for werkcrappit itself, once 0.20.0 is released: `maxLcom4 = 3`, `maxEfferentCoupling = 21`. - hsadmin-ng, in its pilot branch: `maxLcom4 = 4`, `maxEfferentCoupling = 26`. ## Attachments ### LCOM4 and Ce, measured from the class files on 2026-10-04 | | LCOM4 max, as published → without stateless groups | Classes with LCOM4 of 2 or more | Ce max | |---|---|---|---| | hsadmin-ng (267 classes, generated code left out) | 12 → 4 | 66 → 19 | 26 (`HsAccountController`) | | werkcrappit-pit (58 classes) | 3 → 3 | 9 → 4 | 21 (`MutationCrapListener`) | The top of hsadmin-ng now shows real candidates: `HsOfficeContact` (4) with its independent e-mail, phone and postal address, `HsOfficeRelationSearchCriteria` (4) with four independent search fields. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
mi added 1 commit 2026-10-04 12:14:20 +02:00
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mi merged commit 8a4568e34d into main 2026-10-04 12:25:18 +02:00
mi deleted branch mihoe/cohesion-coupling-gate 2026-10-04 12:25:18 +02:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mi/werkcrappit#38