E11017: low module cohesion - constructs share little commonality

Category: E11xxx Code quality and IR analysis · Reported in phase: PRE_IR_CHECKS · Classification: LOW_MODULE_COHESION · All error codes

What went wrong

Your module contains many unrelated constructs that don't share types. Constructs are "connected" if they reference each other's types.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 1337 (Why does EK9 reject a module whose constructs are all...)

Rationale

  • Measures connectivity between constructs in a module
  • Disconnected groups = constructs with no type relationships
  • Thresholds: >88% disconnection AND >30 groups, in a module of at least 60 constructs (smaller modules are exempt)

[REFACTORING PATTERN (Split Module)] Before: a 'utilities' module with 60+ unrelated constructs After: one module per purpose - 'utilities.string' (StringHelper, ...), 'utilities.math' (MathHelper, ...), 'utilities.date' (DateFormatter, ...).

How to fix it

  1. Group constructs that share types into focused modules
  2. Each module should have one clear purpose
  3. If constructs don't share types, they probably don't belong together

Common causes

  • Module accumulated unrelated functionality over time
  • Utility/helper constructs mixed with domain logic
  • Original module scope was too broad

See also

  • E11017: module construct disconnection (this error)
  • E11016: module coupling (external module dependencies)
  • E11014: class cohesion (unrelated methods)

Examples

Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.

Fails with E11017: low module cohesion - constructs share little commonality

#!ek9
//Module-level error: 61 disconnected groups out of 61 constructs (100% > 88%)
defines module error.e11017.bad

  //61 independent records - none reference each other's types
  //Each forms its own disconnected group

  defines record
    Record01
      mainValue as Integer: 1
      default operator ?

    Record02
      mainValue as Integer: 2
      default operator ?

    Record03
      mainValue as Integer: 3
      default operator ?

    Record04
      mainValue as Integer: 4
      default operator ?

    Record05
      mainValue as Integer: 5
      default operator ?

    Record06
      mainValue as Integer: 6
      default operator ?

    Record07
      mainValue as Integer: 7
      default operator ?

    Record08
      mainValue as Integer: 8
      default operator ?

    Record09
      mainValue as Integer: 9
      default operator ?

    Record10
      mainValue as Integer: 10
      default operator ?

    Record11
      mainValue as Integer: 11
      default operator ?

    Record12
      mainValue as Integer: 12
      default operator ?

    Record13
      mainValue as Integer: 13
      default operator ?

    Record14
      mainValue as Integer: 14
      default operator ?

    Record15
      mainValue as Integer: 15
      default operator ?

    Record16
      mainValue as Integer: 16
      default operator ?

    Record17
      mainValue as Integer: 17
      default operator ?

    Record18
      mainValue as Integer: 18
      default operator ?

    Record19
      mainValue as Integer: 19
      default operator ?

    Record20
      mainValue as Integer: 20
      default operator ?

    Record21
      mainValue as Integer: 21
      default operator ?

    Record22
      mainValue as Integer: 22
      default operator ?

    Record23
      mainValue as Integer: 23
      default operator ?

    Record24
      mainValue as Integer: 24
      default operator ?

    Record25
      mainValue as Integer: 25
      default operator ?

    Record26
      mainValue as Integer: 26
      default operator ?

    Record27
      mainValue as Integer: 27
      default operator ?

    Record28
      mainValue as Integer: 28
      default operator ?

    Record29
      mainValue as Integer: 29
      default operator ?

    Record30
      mainValue as Integer: 30
      default operator ?

    Record31
      mainValue as Integer: 31
      default operator ?

    Record32
      mainValue as Integer: 32
      default operator ?

    Record33
      mainValue as Integer: 33
      default operator ?

    Record34
      mainValue as Integer: 34
      default operator ?

    Record35
      mainValue as Integer: 35
      default operator ?

    Record36
      mainValue as Integer: 36
      default operator ?

    Record37
      mainValue as Integer: 37
      default operator ?

    Record38
      mainValue as Integer: 38
      default operator ?

    Record39
      mainValue as Integer: 39
      default operator ?

    Record40
      mainValue as Integer: 40
      default operator ?

    Record41
      mainValue as Integer: 41
      default operator ?

    Record42
      mainValue as Integer: 42
      default operator ?

    Record43
      mainValue as Integer: 43
      default operator ?

    Record44
      mainValue as Integer: 44
      default operator ?

    Record45
      mainValue as Integer: 45
      default operator ?

    Record46
      mainValue as Integer: 46
      default operator ?

    Record47
      mainValue as Integer: 47
      default operator ?

    Record48
      mainValue as Integer: 48
      default operator ?

    Record49
      mainValue as Integer: 49
      default operator ?

    Record50
      mainValue as Integer: 50
      default operator ?

    Record51
      mainValue as Integer: 51
      default operator ?

    Record52
      mainValue as Integer: 52
      default operator ?

    Record53
      mainValue as Integer: 53
      default operator ?

    Record54
      mainValue as Integer: 54
      default operator ?

    Record55
      mainValue as Integer: 55
      default operator ?

    Record56
      mainValue as Integer: 56
      default operator ?

    Record57
      mainValue as Integer: 57
      default operator ?

    Record58
      mainValue as Integer: 58
      default operator ?

    Record59
      mainValue as Integer: 59
      default operator ?

    Record60
      mainValue as Integer: 60
      default operator ?

    Record61
      mainValue as Integer: 61
      default operator ?

Fixed: Keep a module to constructs that work together; move unrelated ones to their own modules

#!ek9
defines module error.e11017.good

  defines record

    Address
      street as String: String()
      city as String: String()

      default operator ?

    Customer
      name as String: String()
      address as Address: Address()

      default operator ?

  defines function

    label()
      -> customer as Customer
      <- rtn as String: `${customer.name}, ${customer.address.city}`