Skip to content

Dagger and component graph

Dagger and Component Graph Deep Dive

Overview

Dagger gives fine-grained control over dependency graph architecture. It is powerful for complex systems but requires strong design discipline.

Core Concepts

  • component defines injectable graph boundary
  • subcomponent models child lifecycle scope
  • module provides/binds dependencies
  • compile-time validation catches wiring errors early

Layer Responsibilities

  • Core platform modules:
  • provide shared infra services
  • Feature graph modules:
  • declare feature-specific implementations
  • Entry components:
  • expose required dependencies to Android boundary classes

Data Flow

  1. Root component initializes global graph.
  2. Child/subcomponent is created per feature or lifecycle scope.
  3. Requested object graph is resolved through providers/bindings.
  4. Injected classes execute domain/data flow.

Internal Architecture

Graph design decisions:

  • subcomponents vs component dependencies
  • multibinding for extensibility points
  • scope boundaries to prevent accidental object sharing

Complexity risks:

  • cyclic dependencies through bindings
  • over-centralized mega-modules
  • slow builds due to graph explosion

Code Examples

@Singleton
@Component(modules = [NetworkModule::class, RepositoryModule::class])
interface AppComponent {
    fun feedComponentFactory(): FeedComponent.Factory
}

@Subcomponent(modules = [FeedModule::class])
@FeatureScope
interface FeedComponent {
    @Subcomponent.Factory
    interface Factory {
        fun create(): FeedComponent
    }
}

Common Interview Questions

  • Q: When to use subcomponents vs component dependencies? A: Answer by defining boundaries and ownership first, then place business rules in the correct layer, and finish with testability and change-resilience tradeoffs.
  • Q: How do scopes map to Android lifecycles? A: State load and SLO assumptions first, identify the first bottleneck, choose scaling and consistency strategy, and explain fallback behavior for partial failures.
  • Q: Why might Dagger builds become slow? A: Frame it around graph ownership: prefer constructor injection, align scopes to lifecycle boundaries, keep contracts explicit, and validate with test replacements.
  • Q: How do you debug missing binding chains? A: Frame it around graph ownership: prefer constructor injection, align scopes to lifecycle boundaries, keep contracts explicit, and validate with test replacements.

Production Considerations

  • keep module ownership per team/feature
  • reduce public graph surface to essential contracts
  • fail PRs on unauthorized graph coupling
  • maintain graph diagrams for critical modules

Scalability Tradeoffs

  • Pros:
  • maximal flexibility and explicit control
  • strong compile-time graph safety
  • Cons:
  • high setup/maintenance complexity
  • steeper onboarding and debugging costs

Senior-Level Insights

Staff-level discussion should cover how graph governance evolves: ownership rules, build performance budgets, and strategies to prevent dependency sprawl.