How do I fix E11043 when a method injects too many distinct types?

← Code Quality · Ref: Q1304

A single method may inject at most 4 distinct types via the method-local '!' suffix. Injecting a 5th distinct type triggers E11043 (EXCESSIVE_INJECTION_TYPES_PER_METHOD) - the method has too many collaborators to understand or test.

Fix: group the related dependencies behind ONE dedicated facade component. Register the facade in the application, then inject the single facade type with '!'. The method now has one collaborator.

See Q203 for application wiring. See Q960 for the per-component injection-field limit (E11040). See Q311 for quality checks.

Example

defines module qa.quality.injection.types

  defines component

    Repository as abstract
      findAll() as abstract
        <- rtn as List of String?

      default operator ?

    InMemoryRepo extends Repository
      override findAll()
        <- rtn <- List() of String
        rtn += "order-1"

      default operator ?

    Logger as abstract
      log() as abstract
        -> message as String

      default operator ?

    ConsoleLogger extends Logger
      override log()
        -> message as String
        stdout <- Stdout()
        stdout.println(message)

      default operator ?

    Mailer as abstract
      send() as abstract
        -> message as String

      default operator ?

    SmtpMailer extends Mailer
      override send()
        -> message as String
        stdout <- Stdout()
        stdout.println(`sending: ${message}`)

      default operator ?

    //The facade groups the three collaborators behind ONE injectable type.
    //A method injects only the facade, keeping distinct injected types low.
    OrderFacade as abstract
      placeOrder() as abstract
        <- rtn as String?

      default operator ?

    DefaultOrderFacade extends OrderFacade
      repo as Repository!
      logger as Logger!
      mailer as Mailer!

      override placeOrder()
        <- rtn as String: "placed"
        orders <- repo.findAll()
        logger.log(`Found ${length orders} orders`)
        mailer.send("order confirmation")

      default operator ?

  defines application

    OrderApp
      register InMemoryRepo() as Repository
      register ConsoleLogger() as Logger
      register SmtpMailer() as Mailer
      register DefaultOrderFacade() as OrderFacade

  defines program

    //CORRECT: the method injects ONE facade type, not five distinct types.
    FacadeDemo() with application of OrderApp
      stdout <- Stdout()

      facade as OrderFacade!

      result <- facade.placeOrder()
      stdout.println(`Order ${result} via single facade injection`)
Other ways to ask this
  • What triggers E11043 EXCESSIVE_INJECTION_TYPES_PER_METHOD?
  • Why does EK9 reject a method that injects more than 4 distinct types?
  • How do I group method-local '!' injections behind a facade?

Coming from another language?

Java: Spring allows unlimited @Autowired locals; over-injection detected only by SonarQube/ArchUnit if configured. C#/.NET: Seemann recommends a low collaborator count but it is advisory. Go: Wire has no per-function limit, caught only in review. EK9: compiler-enforced limit of 4 distinct injected types per method, fixed by a facade component.

Keywords: injection, register, method, application, quality, component, E11043, facade