Dependency isolation strategies

RoadmapsPython

Overview

**Memorizable line:** Dependency isolation means separating your core logic from outside services. When your code directly calls a database or an API, it is hard to test. We call these outside services `dependencies`. If the database is down, your test fails even if your logic is correct. Here is a function that checks if a student passed. It gets marks directly from a database. ```python def check_pass(student_id): # Direct dependency on an external database marks = db.get_marks(student_id) return marks > 40 ``` We isolate the dependency by passing the marks into the function instead. This is called Dependency Injection. ```python def check_pass(marks): # Now it does not depend on a database return marks > 40 ``` **Analogy:** Think of a chef making tea. If the chef goes to the farm to milk the cow, that is a hard dependency. If someone hands the chef a bottle of milk, that is isolation.

It makes your code easy to test. You can pass simple inputs instead of setting up a whole database.

Where used: pytest, FastAPI

Why learn this

Code walkthrough

def process_payment(amount, charge_card):
    if amount > 0:
        return charge_card(amount)
    return False

def fake_charge(amt):
    return f'Charged {amt}'

print(process_payment(50, fake_charge))

Focus: return charge_card(amount)

Aha moment

def run_task(task_func):
    return task_func()

def fake_task():
    return 'Done'

print(run_task(fake_task))

Prediction: What does this print?

Common guess: It crashes because there is no real task.

Because we pass a fake function in, the code runs perfectly without needing a real task.

Common mistakes

Recall questions

Understanding checks

What prints, and why?

10.0

The `calculate_tax` function is isolated. It uses the `fake_get_rate` function passed into it.

Which function is easier to test? A: `def get_discount(): price = api.get_price(); return price * 0.9` or B: `def get_discount(price): return price * 0.9`

B

Function B takes the price as an argument. You do not need to fake the API to test it.

Practice tasks

Isolate a dependency

Given this working code, change it so that `send_sms` is passed in as a parameter to `notify_user`.

Challenge

Pass a fake dependency

Write a function `get_total(price, add_tax_func)`. It should return price plus the result of calling `add_tax_func(price)`.

Continue learning

Previous: Defining functions and return values

Return to Python Roadmap