E11017: low module cohesion - constructs share little commonality
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
- Group constructs that share types into focused modules
- Each module should have one clear purpose
- 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
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}`