Innlegg
Kan avhengighetsineksjon gjøre meg til en bedre Python-programmerer?
16. februar 2025 • 3 min lesing
Avhengighetsineksjon er en hovedstøtte i statiske språk, men gir det mening å bruke det i Python? Vil det gjøre meg til en bedre Python-programmerer?
Og, vent, hva er avhengighetsineksjon igjen?
Først, la oss svare på spørsmålet: Hva er avhengighetsineksjon (DI)?
Avhengighetsineksjon er et mønster som, når det brukes, flytter konstruksjonen av et objekt utenfor klassen. I stedet tar klassen en avhengighet på en abstraksjon.
I statiske språk som C# og Java brukes avhengighetsineksjon mye for å redusere koblingen og lette testing. Faktisk vil du finne avhengighetsineksjonsrammeverk hvis eneste formål er å opprettholde avhengigheter og deres forhold til hverandre.
Avhengighetsineksjon tjener to hovedformål:
For det første reduserer det kompleksitet ved å ta en avhengighet på en abstraksjon.
For det andre tillater avhengighet på en abstraksjon at ulike implementeringer, inkludert mocks for testing, kan sendes inn i klassen eller funksjonen.
La meg demonstrere med noe kode:
# Before
class User:
def __init__(self):
self.database = SqlServerDatabase()
def get_details(self, user_id: int):
self.database.get_user_details(user_id)
# After
class User:
def __init__(self, database: Database):
self.database = database
def get_details(self, user_id: int):
self.database.get_user_details(user_id)
Dette er avhengighetsineksjon i sin enkleste form. Selv om konseptet er enkelt, ligger dens kraft i å muliggjøre fleksible design.
I Before-eksemplet er User-klassen tett koblet til SqlServerDatabase-klassen. Hvis vi vil teste User-klassen, må vi opprette en ny SqlServerDatabase-instans.
I After-eksemplet er User-klassen løst koblet til Database-abstraksjonen. Vi kan sende inn en annen implementering av Database-abstraksjonen til User-klassen.
La meg demonstrere denne fleksibiliteten med et praktisk eksempel som viser hvordan vi kan bytte mellom ulike databaseimplementeringer:
date_string = "2023-10-01" # Example date string
date_format = "%Y-%m-%d" # Input string format
birthday = datetime.strptime(date_string, date_format)
turn_of_the_century = datetime.strptime('2000-01-01', date_format)
database = PostgresDatabase("")
if birthday < turn_of_the_century:
database = SqlServerDatabase("")
user = User(database=database)
user.get_details(user_id=1)
På linje 6 (birthday < turn_of_the_century) tillater avhengighetsineksjon oss å bytte implementeringer enkelt basert på ulike forhold. Selv om denne fleksibiliteten er verdifull for produksjonskode, er en av de mest vanlige bruken for avhengighetsineksjon, spesielt i statiske språk, i testing.
Her er et eksempel:
class UserTests(unittest.TestCase):
def test_is_authenticated(self):
database = MockDatabase('connection_string')
is_authenticated = User(database).is_authenticated('user', 'pass')
self.assertTrue(is_authenticated)
Dette er et enkelt eksempel som bruker en MockDatabase-klasse. I Python kunne vi også bruke den innebygde Mock-klassen for å oppnå det samme resultatet.
Interessant nok ble avhengighetsineksjon ikke mye brukt i Python-prosjektene jeg har arbeidet med. Fra en bakgrunn med statiske språk var jeg overrasket – og det virket motintuitivt.
Imidlertid er det en grunn til denne begrensede adopsjonen. Pythons innebygde patch-funksjonalitet gir allerede utmerkede testmuligheter, noe som eliminerer en av avhengighetsineksjons hovedfordeler. Selv om avhengighetsineksjon fortsatt kan bidra til å redusere kompleksitet, har Python andre tilnærminger for å oppnå det samme målet.
Jeg sier ikke at avhengighetsineksjon ikke bør brukes i Python. Tvert imot, som alle verktøy og mønstre, er det en tid og plass å bruke dem. Og avhengighetsineksjon er bare et annet verktøy i verktøykassen din som vil forbedre kvaliteten på koden din.
Jeg tror avhengighetsineksjon generelt ville øke kodekvaliteten i de fleste Python-prosjekter.
Hvis du er interessert i å utforske avhengighetsineksjon videre, anbefaler jeg å sjekke ut to populære Python-rammeverk:
- Injector (github.com/python-injector/injector)
- Dependency Injector (python-dependency-injector.ets-labs.org)
Forfatter: Chuck Conway er en AI-ingeniør med nesten 30 års erfaring innen programvareutvikling. Han bygger praktiske AI-systemer—innholdspipelines, infrastrukturagenter og verktøy som løser virkelige problemer—og deler det han lærer underveis. Koble til ham på sosiale medier: X (@chuckconway) eller besøk ham på YouTube og på SubStack.