Last active
August 8, 2021 13:24
-
-
Save elnygren/6c52fe652a58f5dae8b186e91ce84269 to your computer and use it in GitHub Desktop.
Simple Dependency Injection in Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# I'm using Django models as inspiration in this example | |
from mymodels import User, Org | |
# You could also call these Getters or DAOs etc | |
# The point is that they perform some kind of | |
# side effect like talking to a DB or an API | |
@dataclass(frozen=True) | |
class UserConnector: | |
def get_user(id: str) -> User: | |
return User.objects.get(id=id) | |
@dataclass(frozen=True) | |
class OrgConnector: | |
def get_org(id: str) -> Org: | |
return Org.objects.get(id=id) | |
# Service is a collection of business logic | |
# that we want to have Dependency Injection support | |
# By injecting all the Connectors, | |
# we have good separation of concerns | |
# and testing becomes simple | |
@dataclass(frozen=True) | |
class UserService: | |
# We can pass in the default implementations here and | |
# replace them in tests or if we do a UserService V2 | |
# that coexists with V1 but has different Connectors. | |
user_connector: UserConnector = UserConnector() | |
org_connector: OrgConnector = OrgConnector() | |
def get_user_with_org(self, id: str) -> User: | |
return { | |
'user': self.user_connector.get_user(id), | |
'org': self.org_connector.get_org(id) | |
} | |
if __name__ == '__main__': | |
# can be parametrised with Mock user_connector and org_connector | |
s = UserService() | |
user = s.get_user_with_org("123") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment