WorkspaceLow-Level Design
← Course overview

Course navigation

On this page

Low-Level Design / SOLID Principles

foundation · 12 MIN READ

Dependency Inversion

High-level policy should depend on a stable abstraction rather than directly construct a low-level detail. Both policy and detail agree on the boundary contract.

Reading completion is independent of quizzes and challenges.

What you’ll understand

  • High-level policy should depend on a stable abstraction rather than directly construct a low-level detail. Both policy and detail agree on the boundary contract.
  • Inject a sender that fulfills the message contract instead of constructing a provider inside policy code.
  • Evaluate the tradeoff: An abstraction boundary adds wiring and requires contract tests. Dependency injection is one implementation technique; the principle is the direction of dependency.

Useful first: Classes and Objects

The idea and when to recognize it

High-level policy should depend on a stable abstraction rather than directly construct a low-level detail. Both policy and detail agree on the boundary contract.

  • Requirement: Receipt delivery policy should work without depending on a concrete email provider.
  • Change to anticipate: Substitute SMS delivery without editing the receipt service.
  • Design goal: Inject a sender that fulfills the message contract instead of constructing a provider inside policy code.

Start with the concrete problem

Receipt delivery policy should work without depending on a concrete email provider.

Substitute SMS delivery without editing the receipt service.

Direct implementationRevised design
Constructing the email SDK in the receipt method prevents substitution and isolated testing.Inject a sender that fulfills the message contract instead of constructing a provider inside policy code.
The baseline case can hide the problem. Compare the extension and boundary fixtures before accepting this design.An abstraction boundary adds wiring and requires contract tests. Dependency injection is one implementation technique; the principle is the direction of dependency.

Responsibilities and contracts

Inject a sender that fulfills the message contract instead of constructing a provider inside policy code.

  • ReceiptService: Depends on the sender contract. Public operations: send(message)
  • Sender: Defines message delivery. Public operations: send(message)
  • EmailSender: Implements the same contract. Public operations: send(message)

Read the design

Select a participant to inspect its responsibility and public operations. Follow the labeled relationships; an arrow indicates direction, while the legend distinguishes ownership, substitution, and temporary use.

Preparing the design walkthrough…

Follow the interaction

Choose a supplied workload and compare the direct and revised implementations. Step through the same operation in both languages. Object values are recorded after each highlighted statement; previous steps remain unchanged.

Preparing the design walkthrough…

Implementation and expected output

Read the complete example alongside its input and expected output. The implementation selector changes the displayed program; the language selector preserves your current scenario and playback position.

Preparing the design walkthrough…

Try the idea in another setting

An order policy can depend on a repository contract realized by an in-memory test repository and a database implementation.

  • Name the new client contract before adapting the example.
  • Identify which state belongs to each object and who controls its lifetime.
  • Write one normal case and one boundary case before extending the design.

Tradeoffs and interview takeaways

An abstraction boundary adds wiring and requires contract tests. Dependency injection is one implementation technique; the principle is the direction of dependency.

Common mistake: Constructing the email SDK in the receipt method prevents substitution and isolated testing.

  • Explain the choice: Inject a sender that fulfills the message contract instead of constructing a provider inside policy code.
  • Challenge your choice: An abstraction boundary adds wiring and requires contract tests. Dependency injection is one implementation technique; the principle is the direction of dependency.
  • Describe a requirement that would make the simpler implementation sufficient.

Design challenge and knowledge check

Preparing the design walkthrough…

Make it your own

Saved on this device · 0/20,000

Reading completion is independent of quizzes and challenges.