PrincipleChapter I · Principles · Building block 5 of 6

Dependency Inversion

Dependency inversion aligns important technical logic with stable, own contracts. Technical adapters fulfill these contracts and thus depend on the specialist core.

  1. Own contractThe expert core defines what it needs.
  2. AdaptivesTechnically implements the contract and is interchangeable.
  3. DirectionThe source code shows from the technology to the specialist core.

Context

Why this is important

If the payment logic depends directly on the provider API, every change of the provider draws it; tests also need the real provider. Dependency inversion is the principle, dependency injection only a mechanism. Foreign terms translated by the building block ACL.

This building block explains the direction of technical dependencies. For the business translation of foreign models, see Anti-Corruption Layer.

At a glance · Adapters depend on the core domain

The core domain defines the contract it needs; technical adapters fulfil it and thus point towards the core.
Shop example · Building blocks and relationships

Reverse dependence on the payment provider

The payment module requires the ability to authorize an amount. It defines its own contract for this; an adapter translates it to an external payment provider.

This is how you read the picture

  1. Own contract The box authorize payment in the area specialist core.
  2. Adaptives Provider adapter and test adapter implement the same contract; the adapter calls the payment provider.
  3. Direction In the picture “This is how the direction is reversed”, the arrow crosses the border inwards, beforewards outwards.

Wide diagram · Move laterally if necessary

The contract belongs to the specialist core; the provider adapter implements it.
Read diagram as text
  • Payment logic: Business status (Specialist core)
  • Authorize payment: Own contract (Specialist core)
  • Provider adapter: Translated call and answer (Technique)
  • Payment provider: External API (External)
  • Test adapters: Predictable answers (Test)
  • Payment logic → Authorize payment: Used
  • Provider adapter → Authorize payment: Implemented
  • Provider adapter → Payment provider: Calls for
  • Test adapters → Authorize payment: Implemented
The contract belongs to the specialist core; the provider adapter implements it.

Then the direction is reversed.

  1. Payment logicBusiness Rules and Status
    Payment logic Knows SDK types Provider API.
  2. Provider APIforeign SDK, foreign types

The dependency points from the inside out over the border; every change of provider meets the payment logic.

An arrow means “depends on” in the source code. Notice in which direction the arrow crosses the dashed boundary.

Benefits & limitations

Helps if:

  • Business rules are tightly coupled to specific database or network libraries.
  • An independent test or replacement of an infrastructure component is a proven goal.

Boundaries

  • An additional contract costs implementation and maintenance. Examine its usefulness based on Module boundaries and actual testing or exchange needs.
  • A contract expressed in infrastructure terms can still tie business logic to infrastructure. Use domain language and preserve Separation of Concerns between the rule and its technical effects.

In practice

  1. Locate the concrete dependency. Identify infrastructure concepts in business logic that make tests harder. This shows whether a contract can remove a real source of coupling.
  2. Express the required capability as a contract. Define a business operation with clear inputs and results. Place it in the core and align the dependency with Module Boundaries.
  3. Add an adapter and an independent test. Implement the contract at the infrastructure boundary and test business behaviour with a controlled implementation. Hexagonal Architecture provides a suitable structural perspective.
Read the detailed explanation

Dependency Inversion arranges dependencies so that business logic defines the contracts it needs, while technical adapters integrate concrete libraries. Source code depends on a contract expressed in business terms. Adapters implement that contract outside the core. Hexagonal Architecture organises ports and adapters; Separation of Concerns separates reasons for change.

At runtime, the core can still call the technical implementation, while the source code dependency points from the adapter to the core contract. This allows business behaviour to be tested independently. Interfaces should provide a real testing or replacement benefit; excessive abstraction adds concepts without a corresponding gain.

Three terms are often confused. Dependency Inversion is the principle: business logic depends on its own abstractions rather than concrete infrastructure. Dependency Injection is a mechanism: the appropriate adapter is supplied from outside, for example by a framework such as Spring. Inversion of Control is the broader concept: the framework calls your code rather than the other way round. Injection alone does not provide dependency inversion. Injecting a provider SDK directly into payment logic still leaves the dependency pointing outwards; only the way the object is obtained has changed.

Check your understanding

Test yourself in three stages

  1. ReadingCheck in the picture

    In what direction does the arrow cross the border before and after?

    View the solution with justification

    Before that, it shows from the payment logic (inside) to the provider API (outside). Afterwards he shows from the provider adapter (outside) to the contract (inside).

  2. ApplyingTransferred to a new situation

    In the test, the payment of B-1042 Without a real provider. What are you doing?

    View the solution with justification

    You are using the test adapter. He fulfills the same contract and provides predictable answers; the payment logic remains unchanged.

  3. EvaluateWeighing an alternative

    The team injects the provider SDK directly into the payment logic via spring and calls it dependency inversion. Is that true?

    View the solution with justification

    No. This is injection without its own abstraction: The payment logic still knows SDK types, the dependency shows to the outside. Inversion only arises when the specialist core defines its own contract and the adapter fulfills it.

Continue on the learning path

Next in Principles & boundaries: Simplicity & complexity budget.