E11043: method uses too many distinct injected types - extract to a dedicated component

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

Worked examples

Compilable examples demonstrating this error and the correct fix:

What went wrong

A single callable (method, operator, function, service operation, program) uses more than 4 distinct injected component types via method-local injection. This makes it difficult to understand and test - it has too many collaborators.

How to fix it

  1. Extract the method into a dedicated component with field injection
  2. Group related injected types into a facade component
  3. Split the method into smaller methods with fewer dependencies

See also

  • E11043: excessive injection types per method (this error)
  • E11040: excessive injection fields
  • E11041: promote to facade

Examples

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

Fails with E11043: method uses too many distinct injected types - extract to a dedicated component

#!ek9
defines module error.e11043.bad

  defines function

    orchestrate()
      <- rtn as Boolean?
      a as ServiceA!
      b as ServiceB!
      c as ServiceC!
      d as ServiceD!
      e as ServiceE!
      rtn: a.doA() and b.doB() and c.doC() and d.doD() and e.doE()

  defines component

    ServiceA as abstract
      doA() as abstract
        <- rtn as Boolean?
      default operator ?

    ServiceB as abstract
      doB() as abstract
        <- rtn as Boolean?
      default operator ?

    ServiceC as abstract
      doC() as abstract
        <- rtn as Boolean?
      default operator ?

    ServiceD as abstract
      doD() as abstract
        <- rtn as Boolean?
      default operator ?

    ServiceE as abstract
      doE() as abstract
        <- rtn as Boolean?
      default operator ?

Fixed: Let one injected facade coordinate the services

#!ek9
defines module error.e11043.good

  defines function

    orchestrate()
      <- rtn as Boolean?
      a as ServiceA!
      b as ServiceB!
      c as ServiceC!
      rest as Coordinator!
      rtn: a.doA() and b.doB() and c.doC() and rest.coordinate()

  defines component

    ServiceA as abstract
      doA() as abstract
        <- rtn as Boolean?
      default operator ?

    ServiceB as abstract
      doB() as abstract
        <- rtn as Boolean?
      default operator ?

    ServiceC as abstract
      doC() as abstract
        <- rtn as Boolean?
      default operator ?

    Coordinator as abstract
      coordinate() as abstract
        <- rtn as Boolean?
      default operator ?