Skip to content

Dependency Inversion Principle ​

Depend on abstractions, not concretions.

Intent ​

High-level modules (policy) and low-level modules (details) both depend on abstractions. Details implement those abstractions.

Problem ​

Research wants John’s children. If it walks relationships.relations tuples directly, it is glued to how storage is laid out. Change the list → break research.

Solution ​

Introduce RelationshipBrowser.find_all_children_of.
Relationships implements it. Research only talks to the browser.

Structure ​

PieceRole
ResearchHigh-level use case
RelationshipBrowserAbstraction
RelationshipsLow-level store
Person / RelationshipDomain bits

Compare code ​

Violation — dig into relations storage

python
class Research:
    def __init__(self, relationships: Relationships):
        for r in relationships.relations:
            if r[0].name == "John" and r[1] == Relationship.PARENT:
                print(f"John has a child called {r[2].name}")

Compliant — this repo

python
class Research:
    def __init__(self, browser: RelationshipBrowser):
        for p in browser.find_all_children_of("John"):
            print(f"John has a child called {p}")

Walkthrough ​

Quick check ​

Which change follows DIP?

Run locally ​

bash
uv run dip

Expected:

text
John has a child called Chris
John has a child called Matt

Source: main.py · tutorial README

Takeaway ​

  • Policy must not scrape infrastructure internals
  • Share an abstraction both sides depend on
  • Details implement the abstraction — they don’t own the high-level