Clean Python Architecture: Decoupling Code with Dependency Injection

ArjanCodes////2 min read

Beyond Rigid Constructors

Many developers trap themselves by initializing dependencies directly inside a class. This creates tight coupling, where a change in a low-level service forces a rewrite of high-level logic. For instance, an EmailSender class that creates its own or objects must know the specific arguments those services require. If suddenly needs an API key or an attachment flag, you have to modify the sender's core logic. This violates the Open-Closed Principle and makes your codebase a brittle mess.

The Dependency Injection Pattern

flips the script. Instead of a class "reaching out" to build what it needs, you "hand" the dependencies to the class. This typically happens in the __init__ method. By injecting a service that follows a specific , your class remains blissfully unaware of implementation details. It only cares that the object it receives has a send_email method.

Code Walkthrough: Before and After

The Coupled Approach

In the rigid version, an if-else block determines which service to instantiate. This grows uncontrollably as you add new providers like .

class EmailSender:
    def send_email(self, service_type, to, subject, body):
        if service_type == "mailchimp":
            service = MailChimp(attachment=True)
        elif service_type == "sendgrid":
            service = SendGrid()
        service.send(to, subject, body)

The Injected Approach

By moving the service creation outside the class, we achieve a clean, single-purpose method.

class EmailSender:
    def __init__(self, service: EmailService):
        self.service = service

    def send_email(self, to, subject, body):
        self.service.send(to, subject, body)

Syntax and Best Practices

Use to define a contract for your services. This ensures type-safety without strict inheritance. When writing unit tests, this pattern is a lifesaver. You can inject a mock service that doesn't actually send emails, allowing you to test the EmailSender logic in isolation without dealing with monkeypatching or network calls. This leads to faster, more reliable test suites and modular code that survives architectural shifts.

Topic DensityMention share of the most discussed topics 路 9 mentions across 7 distinct topics
22%products
22%programming
11%software
11%products
11%software
Other topics
22%
End of Article
Source video
Clean Python Architecture: Decoupling Code with Dependency Injection

Dependency Injection Makes Code Easier to Change and Test

Watch

ArjanCodes // 7:11

On this channel, I post videos about programming and software design to help you take your coding skills to the next level. I'm an entrepreneur and a university lecturer in computer science, with more than 20 years of experience in software development and design. If you're a software developer and you want to improve your development skills, and learn more about programming in general, make sure to subscribe for helpful videos. I post a video here every Friday. If you have any suggestion for a topic you'd like me to cover, just leave a comment on any of my videos and I'll take it under consideration. Thanks for watching!

What they talk about
AI and Agentic Coding News
Who and what they mention most
Python
33.3%5
Python
20.0%3
Python
20.0%3
Pydantic
13.3%2
2 min read0%
2 min read