Bağımlılık enjeksiyonu, nesnelerin veya servislerin (burada bağımlılıklar kastedilir) sınıf tarafından içeride oluşturulması yerine dışarıdan sağlandığı bir tasarım desenidir. Bu, bileşenlerin birbirinden ayrılmasını sağlar.
Python'da bağımlılık enjeksiyonu kullanmanın şu gibi birçok faydası vardır:
Modülerlik: Kodunuz daha küçük, yeniden kullanılabilir parçalara ayrılır.
Test edilebilirlik: Gerçek parçayı sahte (mock) olanlarla değiştirebildiğiniz için kodunuzu test etmek daha kolaydır.
Sürdürülebilirlik: Kodunuzun bazı bölümlerini sistemin geri kalanını bozmadan güncelleyebilir veya değiştirebilirsiniz.
Bu eğitimde, basit ve pratik örneklerle Python'da bağımlılık enjeksiyonunun nasıl kullanılacağını göstereceğim.
Python'da Bağımlılık Enjeksiyonunu Anlamak
Bağımlılık enjeksiyonunun nasıl uygulanacağını anlamak için onu yöneten temel ilkeleri kavramanız gerekir.
Bağımlılık enjeksiyonu, Kontrolün Tersine Çevrilmesi (IoC) denilen prensibe dayanır; bu da bir sınıfın bağımlılıklarını kendisinin oluşturup yönetmesi yerine, bunları harici bir kaynaktan alması anlamına gelir. Bu, tek bir göreve odaklanmaya yardımcı olur ve kodunuzu temiz tutar.
Python'da bağımlılık enjeksiyonu en yaygın olarak şu yollarla yapılır; başkaları da vardır:
Kurucu enjeksiyonu: Bağımlılıkları sınıfın kurucusundan geçirin.
Setter enjeksiyonu: Nesne oluşturulduktan sonra bir setter yöntemiyle bağımlılıkları ayarlayın.
Metot enjeksiyonu: Bağımlılıkları doğrudan ihtiyaç duyan metoda geçirin.
Python'da Neden Bağımlılık Enjeksiyonu Kullanılır?
Bir geliştirici olarak, bağımlılık enjeksiyonunu anlamak ve uygulamak, kod tasarımınızda büyük fark yaratabilir. Bağımlılık enjeksiyonunun bazı faydalarına bakalım.
Modülerlik, yeniden kullanılabilirlik ve esneklik
Bağımlılık enjeksiyonu, kodunuzu daha küçük ve odaklı bileşenlere ayırmanıza olanak tanır; böylece daha fazla esneklik ve modülerlik sağlar.
Her parça veya bileşen belirli bir görevi üstlenir ve harici bağımlılıklara dayanır; bu da onu sizin ya da başkasının uygulamasının farklı bölümlerinde yeniden kullanmayı kolaylaştırır
Örneğin, mesaj gönderen bir sınıfınız olduğunu düşünün. E-posta veya SMS mantığını doğrudan servisinizin içine inşa etmek yerine, bir e-posta ya da SMS gönderici sınıfını enjekte edebilirsiniz.
Artık mesaj gönderen sınıfınız, mesajın nasıl gönderildiğiyle ilgilenmez; yalnızca kendisine sağlanan göndericiyi kullanır. Bu da, mesaj göndericinizi farklı e-posta veya SMS göndericilerle kullanabileceğiniz anlamına gelir.
Sürdürülebilirlik ve test edilebilirlik
Bağımlılık enjeksiyonu kullanırken, test sırasında gerçek bağımlılıkları kolayca sahte verilerle değiştirebilirsiniz. Bu sayede API'lere veya veritabanlarına bağlı kalmadan birim testleri yazmak daha basit hale gelir.
Bir düşünce egzersizi olarak, verileri veritabanına kaydeden bir sınıfınız olduğunu varsayalım. Test amacıyla, testinizi üretim veritabanına bağlamamak için gerçek bir veritabanı yerine sahte bir veritabanı enjekte edebilirsiniz.
Bağımlılık enjeksiyonu, kodunuzun belirli bölümlerini tüm sistemi bozmadan değiştirmenizi sağlar. Bu, özellikle Stripe'tan PayPal'a gibi bir uygulamada ödeme sağlayıcısını değiştirme gereksinimi olduğunda, geri kalan kodu değiştirmeden işinize yarar.
Kontrolün tersine çevrilmesi ve değiştirilebilir bağımlılıklar
Kontrolün tersine çevrilmesi fikri şudur: bağımlılık enjeksiyonu, bağımlılıkların oluşturulması ve yönetilmesi sorumluluğunu harici bir kaynağa kaydırır.
Bu da bir uygulamayı diğerinin yerine kolayca koyabileceğiniz anlamına gelir; örneğin, raporları biçimlendiren ve dışa aktaran bir ReportGenerator sınıfınız varsa.
Sınıfın hangi biçime dışa aktaracağına karar vermesi yerine, içine PDFExporter, ExcelExporter veya CSVExporter gibi bir dışa aktarıcı sınıf enjekte edebilirsiniz.
ReportGenerator sınıfı dışa aktarmanın nasıl gerçekleştiğiyle ilgilenmez; bu yüzden bir biçimi değiştirmek için, enjekte ettiğiniz dışa aktarıcıyı değiştirmeniz yeterlidir; ReportGenerator'ı hiç değiştirmeden.
Python'da Bağımlılık Enjeksiyonunun Uygulanması
Artık bağımlılık enjeksiyonunun ne olduğuna ve neden faydalı olduğuna dair net bir fikir edindiğinize göre, bunu Python'da nasıl uygulayabileceğinize bakalım. En basit yöntemle başlayalım: manuel bağımlılık enjeksiyonu.
Manuel bağımlılık enjeksiyonu
Manuel bağımlılık enjeksiyonunda, bağımlılıkları siz oluşturur ve onlara ihtiyaç duyan sınıf veya fonksiyona geçirirsiniz.
Bu yöntem küçük uygulamalar için iyi çalışır, ancak uygulamanız büyüdükçe hatalardan kaçınmak için bir bağımlılık enjeksiyonu çerçevesi kullanmanız gerekir.
İşte bağımlılık enjeksiyonu olmadan yazılmış bir kod örneği
classEmailService:defsend_email(self, message):print(f"Sending email: {message}")classUserNotifier:def__init__(self):
self.email_service = EmailService()# Creates its own dependencydefnotify(self, message):
self.email_service.send_email(message)
notifier = UserNotifier()
notifier.notify("Welcome!")Altyapı:
Yukarıdaki örnekte, UserNotifier sınıfı EmailService'e sıkı sıkıya bağlıdır. Test için EmailService'i kolayca değiştirip sahte bir servis kullanamazsınız.
İşte manuel bağımlılık enjeksiyonu ile yazılmış başka bir sürüm.
Yukarıdaki sürüm esnektir ve çeşitli mesajlaşma servislerini enjekte etmenize olanak tanır; testlerde EmailService'i bir sahte ile de değiştirebilirsiniz.
dependency-injector çerçevesini kullanma
Uygulamanız büyüdükçe, bağımlılıkları yönetmek karmaşık ve dağınık hale gelir.
Container, örneklerin nasıl oluşturulduğunu tanımlar
Singleton, yalnızca bir adet EmailService örneği olmasını sağlar
Factory, EmailService'i otomatik olarak enjekte ederek yeni bir UserNotifier oluşturur.
Bağlama (wiring) mekanizması
@dekoratörler gibi @inject kullanarak manuel bağımlılık geçirme ihtiyacını azaltabilirsiniz.
Önceki örneğin başka bir sürümü aşağıdadır:
from dependency_injector import containers, providers
# Define servicesclassEmailService:defsend_email(self, message):print(f"Sending email: {message}")classUserNotifier:def__init__(self, email_service: EmailService):
self.email_service = email_service
defnotify(self, message):
self.email_service.send_email(message)# Create containerclassContainer(containers.DeclarativeContainer):
email_service = providers.Singleton(EmailService)
user_notifier = providers.Factory(UserNotifier, email_service=email_service)from dependency_injector.wiring import inject, Provide
@injectdefmain(notifier: UserNotifier = Provide[Container.user_notifier]):
notifier.notify("Hello!")if __name__ =="__main__":
container = Container()
container.wire(modules=[__name__])# This wires the current module
main()Altyapı:
Bu sürümde;
Bağımlılığı elle eklemeye gerek kalmadan, @inject dekoratörü fonksiyonun veya sınıfın bağımlılığını otomatik olarak enjekte eder.
Provide sınıfı, dependency-injector'a hangi bağımlılığın enjekte edileceğini söyler.
Bu yaklaşım, bağımlılıkların konteynerden manuel bağlanması ihtiyacını ortadan kaldırır.
Birden fazla bileşene bağlı olabilen servislerin bulunduğu daha büyük uygulamalarda (dolayısıyla otomatik başlatma ihtiyacı) faydalıdır.
Popüler Python Çatılarında Bağımlılık Enjeksiyonu
Çoğu modern Python çatısı, daha temiz ve daha test edilebilir kod yazmanıza olanak tanıyan bağımlılık enjeksiyonu ile çalışmayı kolaylaştırır.
Bu bölümde, Flask, Django ve FastAPI'de bağımlılık enjeksiyonunun nasıl uygulandığını öğreneceksiniz.
Flask'te bağımlılık enjeksiyonu
Flask'in yerleşik bağımlılık enjeksiyonu desteği yoktur; ancak aşağıdaki adımlarla dependency-injector kütüphanesini kullanarak bunu uygulayabilirsiniz.
Adım 2: Bağımlılık enjeksiyonu konteynerinizi kurun
from dependency_injector import containers, providers
classContainer(containers.DeclarativeContainer):
greeting_service = providers.Factory(GreetingService)Altyapı:
Adım 3: Flask uygulamasını oluşturun ve bağımlılıkları enjekte edin.
from flask import Flask, request
from dependency_injector.wiring import inject, Provide
container = Container()
app = Flask(__name__)@app.route("/greet")@injectdefgreet(greeting_service: GreetingService = Provide[Container.greeting_service]):
name = request.args.get("name","World")return greeting_service.get_greeting(name)
container.wire(modules=[__name__])if __name__ =="__main__":
app.run(debug=True)Altyapı:
Yukarıdaki koda göre:
name = request.args.get(“name”, “World”) fonksiyonu, sorgu dizgisinden name'i alır ve sağlanmadıysa varsayılan olarak ”World” değerini kullanır.
return greeting_service.get_greeting(name), enjekte edilen servisteki metodu çağırır ve bir selamlama mesajı döndürür.
container.wire(modules=[__name__]), bağımlılık enjektörüne bu modülü @inject dekoratörleri ve Provide[...] işaretleyicileri için taramasını ve bunları gerçek sağlayıcılara bağlamasını söyler.
Adım 4: Uygulamayı test edin
Uygulamayı terminalinizde python <name_of_file>.py komutuyla çalıştırın ve http://localhost:5000/greet?name=Jacob URL'sini ziyaret edin.
Şunu görmelisiniz.
Django'da bağımlılık enjeksiyonu
Tıpkı Flask gibi, Django da yerleşik bağımlılık enjeksiyonu sunmaz. Ancak, sınıf tabanlı görünümlerini, ara katman yazılımlarını ve uygulama yapısını kullanarak bağımlılık enjeksiyonunu manuel olarak veya dependency-injector kütüphanesi ile entegre edebilirsiniz.
İşte Django'da bağımlılık enjeksiyonunu uygulamak için adım adım bir prosedür.
Adım 1: Servisinizi tanımlayın
Uygulama klasörünüz altında, iş mantığınızı içeren basit bir servisi services.py adlı yeni bir dosyada oluşturun.
Sunucunuzu uvicorn main:app –reload komutuyla başlatın ve http://localhost:8000/greet?name=FastAPI URL'sini ziyaret edin. Aşağıdaki yanıtı görmelisiniz.
Farklı güçleri, sözdizimleri ve kullanım alanları olan çeşitli Python bağımlılık çerçeveleri vardır. Doğru çerçeveyi seçmek, projenizin boyutuna ve yapısına bağlıdır.
İşte bazı yaygın Python bağımlılık enjeksiyonu çerçevelerinin bir karşılaştırması.
Görünümler ve ara katmanlar için bağımlılık enjeksiyonu sağlar
injector'a bağımlıdır
İleri Düzey Uygulama Kalıpları
Uygulama kod tabanınız büyüdükçe, bağımlılık enjeksiyonunu sürdürmek zorlaşır.
İstek kapsamlı kaynaklar, temizleme (cleanup) ve sorumluluk ayrımı gibi görevleri ele almak için ileri seviye bağımlılık enjeksiyonunu kullanabilirsiniz.
Kapsamlı bağımlılıklar
Kapsamlı bağımlılıklar, bir bağımlılığın ne kadar süreyle kalacağını kontrol etmenizi sağlar; örneğin, istek başına yeni bir nesne, uygulamanın ömrü boyunca paylaşılan bir nesne veya veritabanı bağlantıları gibi kaynakların otomatik temizliği.
Çoğu bağımlılık enjektörü çerçevesi şu kapsamları destekler:
Singleton: Tüm uygulama için tek bir örnek.
Factory: Her enjeksiyonda yeni bir örnek.
İş parçacığı yereli veya istek: İş parçacığı/istek başına tek bir örnek.
Kaynak: Kurulum ve yıkım (teardown) mantığıyla yönetilir.
Aşağıda, dependency-injector kullanarak iç içe konteynerlerle kapsamlı bağımlılıklara bir örnek verilmiştir.
from dependency_injector import containers, providers, resources
# A simple resource that needs setup and cleanupclassMyResource:def__enter__(self):print("Setting up the resource")return self
def__exit__(self, exc_type, exc_val, exc_tb):print("Cleaning up the resource")# Create a container to manage the resourceclassMyContainer(containers.DeclarativeContainer):
resource = providers.Resource(MyResource)# Using the resource with a context manager
container = MyContainer()with container.resource()as r:print("Using the resource")Altyapı:
Yukarıdaki örnekte, MyResource bir dosyayı/veritabanını açıp kapatma gibi kurulum ve yıkım gerektiren bir sınıfı taklit eder.
container, providers.Resource kullanarak kaynağı sağlar ve with container.resource() kullandığınızda, bağlama doğru şekilde girilip çıkılır.
Bu kalıp, dosya tanıtıcıları, veritabanı bağlantıları veya ağ oturumları gibi kaynakların temiz bir şekilde yönetilmesini sağlar.
Geçerli istek için bir veritabanı oturumuna veya istek özelinde bağlamı olan bir kaydediciye (logger) ihtiyaç duyan bir API uç noktası hayal edin.
Kapsamlı bağımlılıklarla, çatı istek başladığında istek kapsamlı bir konteyner oluşturur ve tüm bağımlılıkları bu kapsamdan çözümler.
İstek bittiğinde, veritabanı oturumlarının kapatılması gibi gerekli tüm temizlik işlemleri otomatik olarak gerçekleşir. Bu, istekler arasında durum paylaşımını önler ve kaynak sızıntılarından kaçınır.
Asenkron enjeksiyon
G/Ç bağlı görevleri verimli şekilde ele almak için asenkron yürütmeye ihtiyaç vardır. FastAPI ve dependency-injector gibi çerçevelerdeki bağımlılık enjeksiyonu sistemleri, async/await kullanarak asenkron enjeksiyonu destekler.
Asenkron enjeksiyon, async def fonksiyonları olan bağımlılıkların enjekte edilmesi veya asenkron veritabanı bağlantıları, harici API'ler ya da arka plan görevleri gibi async resources'ların yönetilmesi anlamına gelir.
Bunları eşzamanlı çözmek yerine, bağımlılık enjeksiyonu sistemi enjekte etmeden önce çözümlenmelerini bekler.
Aşağıda FastAPI'de bir asenkron bağımlılığa örnek verilmiştir:
FastAPI, get_user'ın asenkron çözümlemesini otomatik olarak ele alır ve sonucu enjekte eder.
dependency-injector da AsyncResource sağlayıcılarını kullanarak asenkron yaşam döngüsü yönetimini destekler.
from dependency_injector import containers, providers, resources
classAsyncDB:asyncdefconnect(self):print("Connected")return self
asyncdefdisconnect(self):print("Disconnected")classAsyncDBResource(resources.AsyncResource):asyncdefinit(self)-> AsyncDB:
db = AsyncDB()returnawait db.connect()asyncdefshutdown(self, db: AsyncDB):await db.disconnect()classContainer(containers.DeclarativeContainer):
db = providers.Resource(AsyncDBResource)# Usageasyncdefmain():
container = Container()await container.init_resources()
db =await container.db()# Get the AsyncDB instance# Use db here...await container.shutdown_resources()Altyapı:
Yukarıdaki kodda:
resources.AsyncResource, async kurulum/yıkım mantığı için kullanılır.
await container.init_resources(), tüm kaynakları başlatır ve init'i çağırır.
await container.shutdown_resources(), tüm kaynakları temizler.
await container.db(), gerçek kaynak örneğini, yani AsyncDB'yi alır.
Asenkron bağımlılık enjeksiyonu kullanmak, asenkron rotalarda eşzamanlı G/Ç'den kaçınarak uygulamanızın performansını yüksek tutmaya yardımcı olur ve mantığınızda bağımlılıkları elle await etmeye gerek bırakmaz.
Güvenlik Etkileri
Bağımlılık enjeksiyonu modülerliği ve test edilebilirliği artırsa da, dikkatli yönetilmezse potansiyel güvenlik riskleri doğurabilir.
Önemli bir risk, kötü niyetli paketlerin meşru olanları taklit ettiği bağımlılık karışıklığıdır. Örneğin, saldırganlar, PyPI'ye, kurumsal iç sistemlerde kullanılan adlarla paketler yükleyerek uygulamaları kötü amaçlı sürümü kullanmaları için kandırmışlardır.
Güvende kalmak için, asla güvenilmeyen veya kullanıcı kontrolündeki bileşenleri enjekte etmeyin ve ortam değişkenleri gibi yapılandırma kaynaklarını enjekte edilmeden önce doğrulayın.
requirements.txt veya poetry.lock dosyalarını kullanarak sürümleri sabitleyin ve bağımlılık değişikliklerinde güvenlik taramalarını otomatikleştirin. Ayrıca bağımlılıklarınızı düzenli olarak zafiyetler için denetlediğinizden emin olun.
Bağımlılıklarınızın kontrolünü merkezîleştirmek de önemlidir; bu, uygulamalarınız arasında tutarlılık sağlar ve güvenlik yamalarının veya sürüm güncellemelerinin daha kolay uygulanmasını mümkün kılar. Kod tabanının farklı yerlerinde farklı şekillerde enjekte edilen "gölge bağımlılıkları"nı önlemeye yardımcı olur.
Birkaç araç, riskleri tespit edebilir ve güvenlik duruşunuzu iyileştirebilir:
Snyk: Python paketlerindeki bilinen zafiyetleri tarar ve düzeltmeler önerir.
Safety: Güvensiz paketleri ve kod zafiyetlerini kontrol eder.
Bandit: Güvenlik odaklı bir Python statik kod analizörü.
Gerçek Dünya Uygulamaları
Bağımlılık enjeksiyonu yalnızca teorik bir desen değildir; üretim sistemlerinde karmaşıklığı yönetmek, esnekliği artırmak ve testleri kolaylaştırmak için yaygın olarak kullanılır.
Web servisi yapılandırması
Modern web uygulamalarında, kimlik doğrulama, günlükleme (logging) ve veritabanı erişimi gibi standart servislerin yönetiminde bağımlılık enjeksiyonu kritik bir rol oynar.
FastAPI gibi çerçeveler, rotaların ve bağımlılıkların çözümlemesinde önemli bir rol oynar.
Aşağıdaki örnek, FastAPI'de merkezîleştirilmiş bir kimlik doğrulama uygulamasını göstermektedir.
from fastapi import Depends, HTTPException
defget_current_user(token:str= Depends(oauth2_scheme)):
user = verify_token(token)ifnot user:raise HTTPException(status_code=401)return user
@app.get("/protected")defprotected_route(user:dict= Depends(get_current_user)):return{"message":f"Hello {user['name']}"}Altyapı:
Yukarıdaki kodda, get_current_user() bir rota bağımlılığı olarak enjekte edilir; ancak belirteci (token) kontrol etme mantığı merkezîdir ve yeniden kullanılabilir.
Aynısını veritabanı erişimi için de yapabilirsiniz; böylece veritabanı oturumları otomatik olarak yönetilir ve temizlenir.
İşte veritabanı erişimini merkezîleştirmek için bağımlılık enjeksiyonunu nasıl kullanabileceğinize bir örnek.
from sqlalchemy.ext.asyncio import AsyncSession
asyncdefget_db_session()-> AsyncSession:asyncwith async_session()as session:yield session
@app.get("/items")asyncdefread_items(db: AsyncSession = Depends(get_db_session)):returnawait db.execute("SELECT * FROM items")Altyapı:
Yukarıdaki kodda, get_db_session bir bağımlılık sağlayıcısıdır. read_items rotası çağrıldığında, FastAPI db parametresini otomatik olarak enjekte eder; böylece rota, oturum kurulumunu veya yıkımını elle yönetmeden veritabanına erişebilir.
Test güdümlü geliştirme
Bağımlılık enjeksiyonu, bileşenlerin aldığı bağımlılıkları değiştirmenizi kolaylaştırır; bu da test ederken önemlidir.
Test sırasında gerçek servisleri mocklarla değiştirebilir, bu da kodunuzu daha modüler ve test etmesi kolay hale getirir.
FastAPI ve dependency-injector, test zamanında bağımlılıkların geçersiz kılınmasını destekler.
İşte FastAPI'de bir örnek.
from fastapi.testclient import TestClient
from main import app, get_db_session
defoverride_db():return TestDBSession()
app.dependency_overrides[get_db_session]= override_db
client = TestClient(app)
response = client.get("/items")assert response.status_code ==200Altyapı:
Yukarıdaki kod örneğinde, get_db_session test sırasında sahte bir veritabanıyla geçersiz kılınır; böylece üretim kodunu yamalamaya veya değiştirmeye gerek kalmaz.
Aynı şekilde depedency-injector'da da, test amacıyla gerçek veritabanınızı sahte bir veritabanıyla geçersiz kılabilirsiniz; aşağıdaki örnekte olduğu gibi.
from containers import Container
deftest_service_behavior():
container = Container()
container.db.override(providers.Factory(TestDB))
service = container.service()assert service.get_data()=="mocked"Altyapı:
override() yöntemi, gerçek bağımlılığı sahte bir bağımlılıkla değiştirir; bu temiz, kontrollü ve geri alınabilirdir.
Bağımlılık geçersiz kılmaları için kullanmanız gereken bazı stratejiler şunlardır:
Kurucu enjeksiyonu: Mock'ları doğrudan kurucuya geçtiğinizden emin olun.
Çerçeve geçersiz kılmaları: FastAPI'de FastAPI.dependency_overrides veya dependency-injector'da dependency_injector.override() gibi yerleşik geçersiz kılma araçlarını kullanın.
Fixture'lar:pytest gibi test çerçevelerini kullanarak yeniden kullanılabilir mock'lar oluşturun ve bunları fixture'lar aracılığıyla enjekte edin.
En İyi Uygulamalar ve Anti-Pattern'ler
Bağımlılık enjeksiyonu kodu modüler ve test etmesi kolay hâle getirmek için tasarlanmış olsa da, hatalara yol açabilir veya kodda karmaşıklık yaratabilir.
Önerilen uygulamalar
Bağımlılıklar oluştururken uymanız gereken bazı en iyi uygulamalar şunlardır:
Uygulamalara değil, arayüzlere göre programlayın: Bağımlılıkları, karmaşık uygulamalar yerine soyut temel sınıflar veya arayüzler kullanarak tanımlayın. Bu, kodunuzu test etmeyi kolaylaştırır ve birim testlerinde mock kullanımını teşvik eder.
Miras almaktan ziyade bileşimi tercih edin: Karmaşık sınıf hiyerarşileri inşa etmek yerine, bileşenleri küçük ve odaklı tutmak için enjekte edilmiş bağımlılıklarla nesneleri birleştirin.
Merkezî bağımlılık yapılandırması: Bağımlılıkları tanımlamak ve yönetmek için tek bir konteyner veya modül kullanın; bu, geçersiz kılmayı ve test etmeyi kolaylaştırır.
Döngüsel bağımlılıklardan kaçının: Somutlaştırmayı ertelemek için fabrika fonksiyonları veya sağlayıcılar kullanarak bağımlılık grafiğinizi dikkatli tasarlayın.
Yaygın tuzaklar
Bağımlılık enjeksiyonu kullanırken kaçınmanız gereken bazı yaygın tuzaklar şunlardır.
Servis bulucu anti-pattern'i: Bağımlılıkları dinamik olarak almak için genel bir konteyner kullanmaktan kaçının; bu, bağımlılıkları gizleyebilir ve kodun anlaşılmasını ve test edilmesini zorlaştırabilir.
Aşırı enjeksiyon: Tek bir sınıfa veya fonksiyona çok fazla servis enjekte etmekten kaçının; bu, şişkin kuruculara ve test etmesi zor mantığa yol açar.
Kapsam yönetimi hatası ve durum sızıntısı: Kullanıcılar veya testler arasında durum paylaşımını önlemek için her zaman doğru kapsamı kullandığınızdan emin olun.
Python'da Bağımlılık Enjeksiyonu Testi
Bağımlılık enjeksiyonu, birim testlerini basitleştirerek bileşenlerinize sahte nesneler enjekte etmeyi kolaylaştırır. Bu, temel bileşenleri teste özel olanlardan ayırmanızı sağlar.
Bağımlılık enjeksiyonu ile testler belirleyicidir, yan etki içermez ve daha hızlı yürütülür.
İşte testlerinizde bu bağımlılıkların sahte, stub veya fake sürümlerini enjekte etmek için Bağımlılık Enjeksiyonunu nasıl kullanabileceğinizi gösteren bir örnek.
Testlerde, EmailService'i bir mock ile değiştirin:
classTestEmailService:defsend_email(self, to, message):
self.sent_to = to
deftest_notifier_sends_email():
test_email = TestEmailService()
notifier = Notifier(test_email)
notifier.alert("[email protected]")assert test_email.sent_to =="[email protected]"Altyapı:
Sürdürülebilirlik için bağımlılık enjeksiyonunu sıkça kullanın ve iç isimler değiştiğinde kırılmaları önlemek için monkey patching'den kaçının.
Sonuç
Küçük projeler için başlangıçta bağımlılık enjeksiyonuna ihtiyaç duymayabilirsiniz; ancak proje büyüyüp ölçeklendikçe, bağımlılık enjeksiyonunun sunduğu yapı ve modülerlikten fayda sağlayabilirsiniz.
İleriye baktığımızda, Python'da bağımlılık enjeksiyonunun geleceği umut verici görünmektedir; gelişmiş bir tip sistemi ve geliştirilmiş asenkron yaşam döngüsü yönetimiyle devam etmesini bekleyebiliriz.
Bağımlılık enjeksiyonunu ustalıkla kullanmak, yetkin bir Python geliştiricisi olmanın temelidir. Ancak bununla bitmez; Python becerilerinizi bir üst seviyeye taşıyabilecek birçok ileri konsept daha vardır.
Öğrenme yolculuğunuzu hızlandırmanıza yardımcı olmak için göz atmanız gereken bazı kaynaklarımız şunlardır.
Python, R ve makine öğrenmesi alanlarında uzmanlığa sahip, deneyimli veri bilimi eğitmeni ve Biyostatistikçi.
SSS
Bağımlılık enjeksiyonu nedir?⌄
Bağımlılık enjeksiyonu, sınıf içinde oluşturulabilecek bağımlılıkların dışarıdan geçilebilmesini sağlayarak daha temiz kod yazmanıza imkân veren bir tasarım desenidir; bu da kodunuzu yönetmeyi ve değiştirmeyi kolaylaştırır.
Bağımlılık enjeksiyonunun başlıca faydaları nelerdir?⌄
Bağımlılık enjeksiyonu kodunuzu modüler, test edilebilir ve sürdürülebilir kılar.
Python'da bağımlılık enjeksiyonunu nasıl uygulayabilirim?⌄
Python'da bağımlılık enjeksiyonunu ya manuel olarak ya da dependency_injector gibi kütüphaneleri kullanarak uygulayabilirsiniz.
Asenkron enjeksiyon nedir?⌄
Asenkron enjeksiyon, async def fonksiyonları olan bağımlılıkların enjekte edilmesi veya asenkron veritabanı bağlantıları, harici API'ler ya da arka plan görevleri gibi async resources'ların yönetilmesi anlamına gelir.
Bağımlılık enjeksiyonunun güvenlik riskleri nelerdir ve nasıl ele alabilirim?⌄
Önemli bir risk, kötü niyetli paketlerin meşru olanları taklit ettiği bağımlılık karışıklığıdır. Bunu önlemek için Snyk, Xygeni, Safety veya Bandit gibi araçları kullanarak kodunuzu ve paketlerinizi zafiyetler açısından tarayabilirsiniz.
Algoritmalar, sistem tasarımı ve davranışsal senaryoları kapsayan bu temel sorularla teknik mülakat sürecine hakim olun. Uzman cevapları, kod örnekleri ve kanıtlanmış hazırlık stratejileri edinin.
Git deponuzu temiz tutmak için .gitignore’u nasıl kullanacağınızı öğrenin. Bu eğitim; temelleri, yaygın kullanım durumlarını ve başlamanıza yardımcı olacak pratik örnekleri kapsar!
Bağımlılık enjeksiyonu, nesnelerin veya servislerin (burada bağımlılıklar kastedilir) sınıf tarafından içeride oluşturulması yerine dışarıdan sağlandığı bir tasarım desenidir. Bu, bileşenlerin birbirinden ayrılmasını sağlar.
Python'da bağımlılık enjeksiyonu kullanmanın şu gibi birçok faydası vardır:
Bu eğitimde, basit ve pratik örneklerle Python'da bağımlılık enjeksiyonunun nasıl kullanılacağını göstereceğim.
Python'da Bağımlılık Enjeksiyonunu Anlamak
Bağımlılık enjeksiyonunun nasıl uygulanacağını anlamak için onu yöneten temel ilkeleri kavramanız gerekir.
Bağımlılık enjeksiyonu, Kontrolün Tersine Çevrilmesi (IoC) denilen prensibe dayanır; bu da bir sınıfın bağımlılıklarını kendisinin oluşturup yönetmesi yerine, bunları harici bir kaynaktan alması anlamına gelir. Bu, tek bir göreve odaklanmaya yardımcı olur ve kodunuzu temiz tutar.
Python'da bağımlılık enjeksiyonu en yaygın olarak şu yollarla yapılır; başkaları da vardır:
Python'da Neden Bağımlılık Enjeksiyonu Kullanılır?
Bir geliştirici olarak, bağımlılık enjeksiyonunu anlamak ve uygulamak, kod tasarımınızda büyük fark yaratabilir. Bağımlılık enjeksiyonunun bazı faydalarına bakalım.
Modülerlik, yeniden kullanılabilirlik ve esneklik
Bağımlılık enjeksiyonu, kodunuzu daha küçük ve odaklı bileşenlere ayırmanıza olanak tanır; böylece daha fazla esneklik ve modülerlik sağlar.
Her parça veya bileşen belirli bir görevi üstlenir ve harici bağımlılıklara dayanır; bu da onu sizin ya da başkasının uygulamasının farklı bölümlerinde yeniden kullanmayı kolaylaştırır
Örneğin, mesaj gönderen bir sınıfınız olduğunu düşünün. E-posta veya SMS mantığını doğrudan servisinizin içine inşa etmek yerine, bir e-posta ya da SMS gönderici sınıfını enjekte edebilirsiniz.
Artık mesaj gönderen sınıfınız, mesajın nasıl gönderildiğiyle ilgilenmez; yalnızca kendisine sağlanan göndericiyi kullanır. Bu da, mesaj göndericinizi farklı e-posta veya SMS göndericilerle kullanabileceğiniz anlamına gelir.
Sürdürülebilirlik ve test edilebilirlik
Bağımlılık enjeksiyonu kullanırken, test sırasında gerçek bağımlılıkları kolayca sahte verilerle değiştirebilirsiniz. Bu sayede API'lere veya veritabanlarına bağlı kalmadan birim testleri yazmak daha basit hale gelir.
Bir düşünce egzersizi olarak, verileri veritabanına kaydeden bir sınıfınız olduğunu varsayalım. Test amacıyla, testinizi üretim veritabanına bağlamamak için gerçek bir veritabanı yerine sahte bir veritabanı enjekte edebilirsiniz.
Bağımlılık enjeksiyonu, kodunuzun belirli bölümlerini tüm sistemi bozmadan değiştirmenizi sağlar. Bu, özellikle Stripe'tan PayPal'a gibi bir uygulamada ödeme sağlayıcısını değiştirme gereksinimi olduğunda, geri kalan kodu değiştirmeden işinize yarar.
Kontrolün tersine çevrilmesi ve değiştirilebilir bağımlılıklar
Kontrolün tersine çevrilmesi fikri şudur: bağımlılık enjeksiyonu, bağımlılıkların oluşturulması ve yönetilmesi sorumluluğunu harici bir kaynağa kaydırır.
Bu da bir uygulamayı diğerinin yerine kolayca koyabileceğiniz anlamına gelir; örneğin, raporları biçimlendiren ve dışa aktaran bir
ReportGeneratorsınıfınız varsa.Sınıfın hangi biçime dışa aktaracağına karar vermesi yerine, içine
PDFExporter,ExcelExporterveyaCSVExportergibi bir dışa aktarıcı sınıf enjekte edebilirsiniz.ReportGeneratorsınıfı dışa aktarmanın nasıl gerçekleştiğiyle ilgilenmez; bu yüzden bir biçimi değiştirmek için, enjekte ettiğiniz dışa aktarıcıyı değiştirmeniz yeterlidir;ReportGenerator'ı hiç değiştirmeden.Python'da Bağımlılık Enjeksiyonunun Uygulanması
Artık bağımlılık enjeksiyonunun ne olduğuna ve neden faydalı olduğuna dair net bir fikir edindiğinize göre, bunu Python'da nasıl uygulayabileceğinize bakalım. En basit yöntemle başlayalım: manuel bağımlılık enjeksiyonu.
Manuel bağımlılık enjeksiyonu
Manuel bağımlılık enjeksiyonunda, bağımlılıkları siz oluşturur ve onlara ihtiyaç duyan sınıf veya fonksiyona geçirirsiniz.
Bu yöntem küçük uygulamalar için iyi çalışır, ancak uygulamanız büyüdükçe hatalardan kaçınmak için bir bağımlılık enjeksiyonu çerçevesi kullanmanız gerekir.
İşte bağımlılık enjeksiyonu olmadan yazılmış bir kod örneği
Yukarıdaki örnekte,
UserNotifiersınıfıEmailService'e sıkı sıkıya bağlıdır. Test içinEmailService'i kolayca değiştirip sahte bir servis kullanamazsınız.İşte manuel bağımlılık enjeksiyonu ile yazılmış başka bir sürüm.
Yukarıdaki sürüm esnektir ve çeşitli mesajlaşma servislerini enjekte etmenize olanak tanır; testlerde
EmailService'i bir sahte ile de değiştirebilirsiniz.dependency-injector çerçevesini kullanma
Uygulamanız büyüdükçe, bağımlılıkları yönetmek karmaşık ve dağınık hale gelir.
dependency-injectorçerçevesi yapılandırılmış bir yaklaşım sunar.Konteyner–sağlayıcı mimarisi
dependency-injectorçerçevesi, konteyner–sağlayıcı mimarisiyle çalışır.Yukarıdaki örnekte:
Container, örneklerin nasıl oluşturulduğunu tanımlarSingleton, yalnızca bir adetEmailServiceörneği olmasını sağlarFactory,EmailService'i otomatik olarak enjekte ederek yeni birUserNotifieroluşturur.Bağlama (wiring) mekanizması
@dekoratörler gibi
@injectkullanarak manuel bağımlılık geçirme ihtiyacını azaltabilirsiniz.Önceki örneğin başka bir sürümü aşağıdadır:
Bu sürümde;
Bağımlılığı elle eklemeye gerek kalmadan,
@injectdekoratörü fonksiyonun veya sınıfın bağımlılığını otomatik olarak enjekte eder.Providesınıfı,dependency-injector'a hangi bağımlılığın enjekte edileceğini söyler.Bu yaklaşım, bağımlılıkların konteynerden manuel bağlanması ihtiyacını ortadan kaldırır.
Birden fazla bileşene bağlı olabilen servislerin bulunduğu daha büyük uygulamalarda (dolayısıyla otomatik başlatma ihtiyacı) faydalıdır.
Popüler Python Çatılarında Bağımlılık Enjeksiyonu
Çoğu modern Python çatısı, daha temiz ve daha test edilebilir kod yazmanıza olanak tanıyan bağımlılık enjeksiyonu ile çalışmayı kolaylaştırır.
Bu bölümde, Flask, Django ve FastAPI'de bağımlılık enjeksiyonunun nasıl uygulandığını öğreneceksiniz.
Flask'te bağımlılık enjeksiyonu
Flask'in yerleşik bağımlılık enjeksiyonu desteği yoktur; ancak aşağıdaki adımlarla
dependency-injectorkütüphanesini kullanarak bunu uygulayabilirsiniz.Adım 1: Servislerinizi tanımlayın
Adım 2: Bağımlılık enjeksiyonu konteynerinizi kurun
Adım 3: Flask uygulamasını oluşturun ve bağımlılıkları enjekte edin.
Yukarıdaki koda göre:
name = request.args.get(“name”, “World”)fonksiyonu, sorgu dizgisindenname'i alır ve sağlanmadıysa varsayılan olarak”World”değerini kullanır.return greeting_service.get_greeting(name), enjekte edilen servisteki metodu çağırır ve bir selamlama mesajı döndürür.container.wire(modules=[__name__]), bağımlılık enjektörüne bu modülü@injectdekoratörleri veProvide[...]işaretleyicileri için taramasını ve bunları gerçek sağlayıcılara bağlamasını söyler.Adım 4: Uygulamayı test edin
Uygulamayı terminalinizde
python <name_of_file>.pykomutuyla çalıştırın vehttp://localhost:5000/greet?name=JacobURL'sini ziyaret edin.Şunu görmelisiniz.
Django'da bağımlılık enjeksiyonu
Tıpkı Flask gibi, Django da yerleşik bağımlılık enjeksiyonu sunmaz. Ancak, sınıf tabanlı görünümlerini, ara katman yazılımlarını ve uygulama yapısını kullanarak bağımlılık enjeksiyonunu manuel olarak veya
dependency-injectorkütüphanesi ile entegre edebilirsiniz.İşte Django'da bağımlılık enjeksiyonunu uygulamak için adım adım bir prosedür.
Adım 1: Servisinizi tanımlayın
Uygulama klasörünüz altında, iş mantığınızı içeren basit bir servisi
services.pyadlı yeni bir dosyada oluşturun.Adım 2: Bağımlılık enjektörü konteynerini kurun
Uygulama dizininizde,
dependency-injectorkütüphanesini kullanarakcontainers.pyadlı yeni bir dosyada bir konteyner oluşturun.Adım 3: Enjekte edilmiş bağımlılıklarla bir View oluşturun
views.pyiçinde bağımlılıkları almak için@injectdekoratörünü kullanın.Adım 4: urls.py'ı güncelleyin
Proje klasörünüz altında,
urls.pydosyasına gidin ve bağımlılık enjektörünüzü Django'nun URL yönlendirme sistemine bağlayın.Adım 5: apps.py içinde konteyneri bağlayın
apps.py'a gidin ve konteyneri uygulamaya bağlayın.Ardından
INSTALLED_APPSaltındaki uygulama yapılandırmanıza gidin ve uygulamanızı ekleyin.Adım 6: Görünümü test edin
Django sunucunuzu başlatın ve görünümü
http://localhost:8000/greet/?name=DjangoURL'si üzerinden açın.Şunu görmelisiniz.
FastAPI'de Bağımlılık Enjeksiyonu
FastAPI, bir fonksiyonun döndürdüğünü enjekte eden özel
Depends()işaretleyicisi aracılığıyla yerleşik bağımlılık enjeksiyonu desteğine sahiptir.İşte FastAPI bağımlılık enjeksiyonu için adım adım bir rehber.
Adım 1: Bir servis tanımlayın
Adım 2: Bağımlılık fonksiyonunu oluşturun
Adım 3: FastAPI uygulamasını kurun ve Bağımlılık Enjeksiyonu kullanın
Adım 4: Uygulamayı çalıştırın ve test edin
Sunucunuzu
uvicorn main:app –reloadkomutuyla başlatın vehttp://localhost:8000/greet?name=FastAPIURL'sini ziyaret edin. Aşağıdaki yanıtı görmelisiniz.Python Bağımlılık Enjektörü Çerçevelerinin Karşılaştırılması
Farklı güçleri, sözdizimleri ve kullanım alanları olan çeşitli Python bağımlılık çerçeveleri vardır. Doğru çerçeveyi seçmek, projenizin boyutuna ve yapısına bağlıdır.
İşte bazı yaygın Python bağımlılık enjeksiyonu çerçevelerinin bir karşılaştırması.
Çerçeve
En Uygun Alan
Güçlü Yanlar
Sınırlamalar
dependency-injectorÜretimde kullanılan karmaşık uygulamalar
Tam özellikli, hızlı ve yapılandırılabilir
Detaycı/uzun sözlü
injectorBasit ve minimum uygulamalar için uygun
Temiz sözdizimi
Diğerlerine göre daha az gelişmiş.
pinjectGelişmiş bağlama mantığı
Otomatik bağlama (auto-wiring)
Yansıtma (introspection) nedeniyle daha yavaş
punqBasit uygulamalar
Minimal ve hızlı
Diğerlerine kıyasla sınırlı özellikler
FastAPI
Depends()FastAPI uygulamaları
Async için yerleşik destek, ayrıca test edilebilir
FastAPI dışında yeniden kullanılamaz
Flask-injectorFlask uygulamaları
Flask uygulamalarıyla kolay entegrasyon
injector'a bağımlıdırdjango-injectorDjango projeleri
Görünümler ve ara katmanlar için bağımlılık enjeksiyonu sağlar
injector'a bağımlıdırİleri Düzey Uygulama Kalıpları
Uygulama kod tabanınız büyüdükçe, bağımlılık enjeksiyonunu sürdürmek zorlaşır.
İstek kapsamlı kaynaklar, temizleme (cleanup) ve sorumluluk ayrımı gibi görevleri ele almak için ileri seviye bağımlılık enjeksiyonunu kullanabilirsiniz.
Kapsamlı bağımlılıklar
Kapsamlı bağımlılıklar, bir bağımlılığın ne kadar süreyle kalacağını kontrol etmenizi sağlar; örneğin, istek başına yeni bir nesne, uygulamanın ömrü boyunca paylaşılan bir nesne veya veritabanı bağlantıları gibi kaynakların otomatik temizliği.
Çoğu bağımlılık enjektörü çerçevesi şu kapsamları destekler:
Aşağıda,
dependency-injectorkullanarak iç içe konteynerlerle kapsamlı bağımlılıklara bir örnek verilmiştir.Yukarıdaki örnekte,
MyResourcebir dosyayı/veritabanını açıp kapatma gibi kurulum ve yıkım gerektiren bir sınıfı taklit eder.container,providers.Resourcekullanarak kaynağı sağlar vewith container.resource()kullandığınızda, bağlama doğru şekilde girilip çıkılır.Bu kalıp, dosya tanıtıcıları, veritabanı bağlantıları veya ağ oturumları gibi kaynakların temiz bir şekilde yönetilmesini sağlar.
Geçerli istek için bir veritabanı oturumuna veya istek özelinde bağlamı olan bir kaydediciye (logger) ihtiyaç duyan bir API uç noktası hayal edin.
Kapsamlı bağımlılıklarla, çatı istek başladığında istek kapsamlı bir konteyner oluşturur ve tüm bağımlılıkları bu kapsamdan çözümler.
İstek bittiğinde, veritabanı oturumlarının kapatılması gibi gerekli tüm temizlik işlemleri otomatik olarak gerçekleşir. Bu, istekler arasında durum paylaşımını önler ve kaynak sızıntılarından kaçınır.
Asenkron enjeksiyon
G/Ç bağlı görevleri verimli şekilde ele almak için asenkron yürütmeye ihtiyaç vardır. FastAPI ve
dependency-injectorgibi çerçevelerdeki bağımlılık enjeksiyonu sistemleri,async/awaitkullanarak asenkron enjeksiyonu destekler.Asenkron enjeksiyon,
async deffonksiyonları olan bağımlılıkların enjekte edilmesi veya asenkron veritabanı bağlantıları, harici API'ler ya da arka plan görevleri gibiasync resources'ların yönetilmesi anlamına gelir.Bunları eşzamanlı çözmek yerine, bağımlılık enjeksiyonu sistemi enjekte etmeden önce çözümlenmelerini bekler.
Aşağıda FastAPI'de bir asenkron bağımlılığa örnek verilmiştir:
FastAPI,
get_user'ın asenkron çözümlemesini otomatik olarak ele alır ve sonucu enjekte eder.dependency-injectordaAsyncResourcesağlayıcılarını kullanarak asenkron yaşam döngüsü yönetimini destekler.Yukarıdaki kodda:
resources.AsyncResource, async kurulum/yıkım mantığı için kullanılır.await container.init_resources(), tüm kaynakları başlatır veinit'i çağırır.await container.shutdown_resources(), tüm kaynakları temizler.await container.db(), gerçek kaynak örneğini, yaniAsyncDB'yi alır.Asenkron bağımlılık enjeksiyonu kullanmak, asenkron rotalarda eşzamanlı G/Ç'den kaçınarak uygulamanızın performansını yüksek tutmaya yardımcı olur ve mantığınızda bağımlılıkları elle await etmeye gerek bırakmaz.
Güvenlik Etkileri
Bağımlılık enjeksiyonu modülerliği ve test edilebilirliği artırsa da, dikkatli yönetilmezse potansiyel güvenlik riskleri doğurabilir.
Önemli bir risk, kötü niyetli paketlerin meşru olanları taklit ettiği bağımlılık karışıklığıdır. Örneğin, saldırganlar, PyPI'ye, kurumsal iç sistemlerde kullanılan adlarla paketler yükleyerek uygulamaları kötü amaçlı sürümü kullanmaları için kandırmışlardır.
Güvende kalmak için, asla güvenilmeyen veya kullanıcı kontrolündeki bileşenleri enjekte etmeyin ve ortam değişkenleri gibi yapılandırma kaynaklarını enjekte edilmeden önce doğrulayın.
requirements.txtveyapoetry.lockdosyalarını kullanarak sürümleri sabitleyin ve bağımlılık değişikliklerinde güvenlik taramalarını otomatikleştirin. Ayrıca bağımlılıklarınızı düzenli olarak zafiyetler için denetlediğinizden emin olun.Bağımlılıklarınızın kontrolünü merkezîleştirmek de önemlidir; bu, uygulamalarınız arasında tutarlılık sağlar ve güvenlik yamalarının veya sürüm güncellemelerinin daha kolay uygulanmasını mümkün kılar. Kod tabanının farklı yerlerinde farklı şekillerde enjekte edilen "gölge bağımlılıkları"nı önlemeye yardımcı olur.
Birkaç araç, riskleri tespit edebilir ve güvenlik duruşunuzu iyileştirebilir:
Gerçek Dünya Uygulamaları
Bağımlılık enjeksiyonu yalnızca teorik bir desen değildir; üretim sistemlerinde karmaşıklığı yönetmek, esnekliği artırmak ve testleri kolaylaştırmak için yaygın olarak kullanılır.
Web servisi yapılandırması
Modern web uygulamalarında, kimlik doğrulama, günlükleme (logging) ve veritabanı erişimi gibi standart servislerin yönetiminde bağımlılık enjeksiyonu kritik bir rol oynar.
FastAPI gibi çerçeveler, rotaların ve bağımlılıkların çözümlemesinde önemli bir rol oynar.
Aşağıdaki örnek, FastAPI'de merkezîleştirilmiş bir kimlik doğrulama uygulamasını göstermektedir.
Yukarıdaki kodda,
get_current_user()bir rota bağımlılığı olarak enjekte edilir; ancak belirteci (token) kontrol etme mantığı merkezîdir ve yeniden kullanılabilir.Aynısını veritabanı erişimi için de yapabilirsiniz; böylece veritabanı oturumları otomatik olarak yönetilir ve temizlenir.
İşte veritabanı erişimini merkezîleştirmek için bağımlılık enjeksiyonunu nasıl kullanabileceğinize bir örnek.
Yukarıdaki kodda,
get_db_sessionbir bağımlılık sağlayıcısıdır.read_itemsrotası çağrıldığında, FastAPIdbparametresini otomatik olarak enjekte eder; böylece rota, oturum kurulumunu veya yıkımını elle yönetmeden veritabanına erişebilir.Test güdümlü geliştirme
Bağımlılık enjeksiyonu, bileşenlerin aldığı bağımlılıkları değiştirmenizi kolaylaştırır; bu da test ederken önemlidir.
Test sırasında gerçek servisleri mocklarla değiştirebilir, bu da kodunuzu daha modüler ve test etmesi kolay hale getirir.
FastAPI ve
dependency-injector, test zamanında bağımlılıkların geçersiz kılınmasını destekler.İşte FastAPI'de bir örnek.
Yukarıdaki kod örneğinde,
get_db_sessiontest sırasında sahte bir veritabanıyla geçersiz kılınır; böylece üretim kodunu yamalamaya veya değiştirmeye gerek kalmaz.Aynı şekilde
depedency-injector'da da, test amacıyla gerçek veritabanınızı sahte bir veritabanıyla geçersiz kılabilirsiniz; aşağıdaki örnekte olduğu gibi.override()yöntemi, gerçek bağımlılığı sahte bir bağımlılıkla değiştirir; bu temiz, kontrollü ve geri alınabilirdir.Bağımlılık geçersiz kılmaları için kullanmanız gereken bazı stratejiler şunlardır:
FastAPI.dependency_overridesveyadependency-injector'dadependency_injector.override()gibi yerleşik geçersiz kılma araçlarını kullanın.pytestgibi test çerçevelerini kullanarak yeniden kullanılabilir mock'lar oluşturun ve bunları fixture'lar aracılığıyla enjekte edin.En İyi Uygulamalar ve Anti-Pattern'ler
Bağımlılık enjeksiyonu kodu modüler ve test etmesi kolay hâle getirmek için tasarlanmış olsa da, hatalara yol açabilir veya kodda karmaşıklık yaratabilir.
Önerilen uygulamalar
Bağımlılıklar oluştururken uymanız gereken bazı en iyi uygulamalar şunlardır:
Yaygın tuzaklar
Bağımlılık enjeksiyonu kullanırken kaçınmanız gereken bazı yaygın tuzaklar şunlardır.
Python'da Bağımlılık Enjeksiyonu Testi
Bağımlılık enjeksiyonu, birim testlerini basitleştirerek bileşenlerinize sahte nesneler enjekte etmeyi kolaylaştırır. Bu, temel bileşenleri teste özel olanlardan ayırmanızı sağlar.
Bağımlılık enjeksiyonu ile testler belirleyicidir, yan etki içermez ve daha hızlı yürütülür.
İşte testlerinizde bu bağımlılıkların sahte, stub veya fake sürümlerini enjekte etmek için Bağımlılık Enjeksiyonunu nasıl kullanabileceğinizi gösteren bir örnek.
Testlerde,
EmailService'i bir mock ile değiştirin:Sürdürülebilirlik için bağımlılık enjeksiyonunu sıkça kullanın ve iç isimler değiştiğinde kırılmaları önlemek için monkey patching'den kaçının.
Sonuç
Küçük projeler için başlangıçta bağımlılık enjeksiyonuna ihtiyaç duymayabilirsiniz; ancak proje büyüyüp ölçeklendikçe, bağımlılık enjeksiyonunun sunduğu yapı ve modülerlikten fayda sağlayabilirsiniz.
İleriye baktığımızda, Python'da bağımlılık enjeksiyonunun geleceği umut verici görünmektedir; gelişmiş bir tip sistemi ve geliştirilmiş asenkron yaşam döngüsü yönetimiyle devam etmesini bekleyebiliriz.
Bağımlılık enjeksiyonunu ustalıkla kullanmak, yetkin bir Python geliştiricisi olmanın temelidir. Ancak bununla bitmez; Python becerilerinizi bir üst seviyeye taşıyabilecek birçok ileri konsept daha vardır.
Öğrenme yolculuğunuzu hızlandırmanıza yardımcı olmak için göz atmanız gereken bazı kaynaklarımız şunlardır.
Kurslar:
Blog Yazıları: