Dependency Injection Nedir?

Dependency Injection (DI), yazılım geliştirmede sıkça karşılaşılan bağımlılık sorunlarını çözmek ve kodun esnekliğini artırmak için kullanılan bir programlama tekniğidir. Bu yöntem, bir nesnenin bağımlı olduğu diğer nesneleri dışarıdan enjekte etmesini sağlayarak, sıkı bağımlılıkları gevşetir ve yazılımın daha test edilebilir, bakımı kolay ve yeniden kullanılabilir olmasını sağlar.

Dependency Injection. https://upload.wikimedia.org/wikipedia/commons/4/44/Spring_Framework_Logo_2018.svg
Dependency Injection. https://upload.wikimedia.org/wikipedia/commons/4/44/Spring_Framework_Logo_2018.svg 

Dependency Injection, bir sınıfın ihtiyaç duyduğu diğer sınıfları kendi içinde oluşturmak yerine dışarıdan enjekte etmesini sağlayan bir programlama tekniğidir. Bu sayede sınıflar arasındaki bağımlılıklar minimize edilir ve kodun esnekliği artar.

Geleneksel olarak, bir sınıfın bağımlı olduğu nesneleri kendisi oluşturması sıkça kullanılan bir yöntemdir. Örneğin, bir AccountCreator sınıfının bağımlı olduğu AccountChecker ve AccountRepository sınıflarını kendisi oluşturması durumu söz konusu olabilir. Bu durumda, AccountCreator sınıfı bu iki sınıfın değişikliklerinden etkilenir ve kodun bakımı zorlaşır.

Dependency Injection ile AccountCreator sınıfının bu bağımlılıkları dışarıdan enjekte edilir. Bu sayede, AccountChecker ve AccountRepository sınıflarında yapılacak değişiklikler AccountCreator sınıfını etkilemez ve kodun bakımı daha kolay hale gelir.

Dependency Injection’ın Avantajları

DI kullanmanın birçok avantajı vardır. İşte bazıları:

Esneklik ve Genişletilebilirlik

DI ile bağımlılıklar minimize edilir ve sınıflar daha bağımsız hale gelir. Bu sayede, bir sınıfta yapılacak değişiklikler diğer sınıfları etkilemez ve kodun genişletilmesi daha kolay olur. Örneğin, yeni bir Engine sınıfı oluşturulduğunda, bu sınıfı kullanmak isteyen sınıflar sadece bu yeni sınıfı enjekte ederek kullanabilir.

Test Kolaylığı

DI, birim testlerin yazılmasını kolaylaştırır. Bağımlılıkları dışarıdan enjekte etmek, sınıfları izole bir şekilde test etmeyi mümkün kılar. Bağımlılıkları sahte (mock) nesnelerle değiştirerek, testlerin daha kontrol edilebilir ve güvenilir olmasını sağlar.

İlgini çekebilir:  Pure Java - Garbage Collection

Yeniden Kullanılabilirlik

DI ile kodun yeniden kullanılabilirliği artar. Sınıfların bağımlılıkları dışarıdan enjekte edildiği için, aynı sınıfı farklı bağımlılıklarla kullanmak mümkün hale gelir. Bu sayede, kod tekrarının önüne geçilir ve daha modüler bir yapı oluşturulur.

Bakım Kolaylığı

DI sayesinde, kodun bakımı daha kolay hale gelir. Bağımlılıkların dışarıdan enjekte edilmesi sayesinde, bir sınıfta yapılacak değişiklikler diğer sınıfları etkilemez. Bu sayede, kodun bakımı daha güvenli ve hatalara karşı daha dirençli hale gelir.

Dependency Injection Nasıl Uygulanır?

DI, genellikle üç ana türde uygulanır. DIn türlerini ayrı ayrı ele alalım ve her bir tür için Java kod örnekleri ve açıklamaları ekleyelim:

Constructor Injection

Constructor Injection, bağımlılıkları bir sınıfın yapıcı (constructor) metodları aracılığıyla enjekte etme yöntemidir. Bu, sınıfın oluşturulma anında bağımlılıkların belirtilmesini sağlar.

class DependentService {
    public void performAction() {
        System.out.println("Bağımlılık kullanıldı.");
    }
}

class MyService {
    private final DependentService dependentService;

    // Constructor Injection ile bağımlılık enjekte ediliyor
    public MyService(DependentService dependentService) {
        this.dependentService = dependentService;
    }

    public void doSomething() {
        dependentService.performAction();
    }
}

public class Main {
    public static void main(String[] args) {
        DependentService dependency = new DependentService();
        MyService service = new MyService(dependency);
        service.doSomething();
    }
}
Yukarıdaki örnekte, MyService sınıfı, DependentService bağımlılığını yapıcı metod aracılığıyla alır. Bu, MyService sınıfının oluşturulması sırasında bağımlılığın enjekte edilmesini sağlar.

Setter Injection

Setter Injection, bağımlılıkları sınıfın özel ayarlayıcı (setter) metodları aracılığıyla enjekte etme yöntemidir. Bu, bağımlılıkların sınıfın yaşam döngüsü boyunca değiştirilebilir olduğu durumlarda kullanışlıdır.

class DependentService {
    public void performAction() {
        System.out.println("Bağımlılık kullanıldı.");
    }
}

class MyService {
    private DependentService dependentService;

    // Setter Injection ile bağımlılık enjekte ediliyor
    public void setDependentService(DependentService dependentService) {
        this.dependentService = dependentService;
    }

    public void doSomething() {
        dependentService.performAction();
    }
}

public class Main {
    public static void main(String[] args) {
        DependentService dependency = new DependentService();
        MyService service = new MyService();
        
        // Setter aracılığıyla bağımlılık enjekte ediliyor
        service.setDependentService(dependency);
        
        service.doSomething();
    }
}

Yukarıdaki örnekte, MyService sınıfı, DependentService bağımlılığını bir setter metod aracılığıyla alır. Bu, bağımlılığın sınıfın yaşam döngüsü boyunca değiştirilebilmesine olanak tanır.

İlgini çekebilir:  ClassNotFoundException Hatası ve Çözümü

Method Injection

Method Injection, bağımlılıkları belirli metotların parametreleri olarak enjekte etme yöntemidir. Bu, bağımlılığın yalnızca belirli işlemlerde ihtiyaç duyulduğu durumlarda kullanışlıdır.

class DependentService {
    public void performAction() {
        System.out.println("Bağımlılık kullanıldı.");
    }
}

class MyService {
    public void doSomething(DependentService dependentService) {
        dependentService.performAction();
    }
}

public class Main {
    public static void main(String[] args) {
        DependentService dependency = new DependentService();
        MyService service = new MyService();
        service.doSomething(dependency);
    }
}

Yukarıdaki örnekte, MyService sınıfının doSomething metodu, DependentService bağımlılığını parametre olarak alır. Bu sayede bağımlılık sadece ihtiyaç duyulduğu metotlarda kullanılabilir.

Java ile Dependency Injection

Java, DI’ı uygulamak için çeşitli yol ve araçlar sunar. En yaygın kullanılan araçlardan biri “Spring Framework”tür. Ancak, DI’ı basit bir Java sınıfı ile de uygulayabilirsiniz. Yukarıdaki örnekten bir farkı yok ancak kod örneğini tekrar vereceğim.

// Bağımlılığı enjekte edeceğimiz sınıf
class DependentService {
    public void performAction() {
        // Bağımlılığı kullan
        System.out.println("Bağımlılık kullanıldı.");
    }
}

// DI yapılacak sınıf
class MyService {
    private final DependentService dependentService;

    // Constructor Injection ile bağımlılık enjekte ediliyor
    public MyService(DependentService dependentService) {
        this.dependentService = dependentService;
    }

    public void doSomething() {
        // Bağımlılığı kullan
        dependentService.performAction();
    }
}

public class Main {
    public static void main(String[] args) {
        // Bağımlılığı oluştur
        DependentService dependency = new DependentService();

        // Bağımlılığı enjekte ederek sınıfı oluştur
        MyService service = new MyService(dependency);

        // İşlemi gerçekleştir
        service.doSomething();
    }
}

Bu örnek, DI’ın Constructor Injection yöntemi ile nasıl uygulandığını göstermektedir. MyService sınıfı, DependentService‘i yapılandırıcı metodu aracılığıyla alır ve kullanır. Bu sayede MyService sınıfı DependentService‘e bağımlı hale gelir ve bu bağımlılık dışarıdan enjekte edilebilir.

Spring Boot ile Dependency Injection

Spring Boot, DI’ı uygulamak için kullanabileceğiniz güçlü bir Java framework’üdür. Spring, bağımlılıkların enjekte edilmesi için IOC (Inversion of Control) konteynerini kullanır ve bu sayede bağımlılıkların yönetimi kolaylaşır.

İlgini çekebilir:  Java Record Nedir? Nasıl Kullanılır?

Constructor Injection

Spring Boot, constructor enjeksiyonu kullanarak bağımlılıkları inject etmenize olanak tanır.

import org.springframework.stereotype.Service;

// Bağımlılığı enjekte edeceğimiz sınıf
@Service
public class DependentService {
    public void performAction() {
        System.out.println("Bağımlılık kullanıldı.");
    }
}

// DI yapılacak sınıf
@Service
public class MyService {
    private final DependentService dependentService;

    // Constructor Injection ile bağımlılık enjekte ediliyor
    public MyService(DependentService dependentService) {
        this.dependentService = dependentService;
    }

    public void doSomething() {
        dependentService.performAction();
    }
}

Yukarıdaki örnekte, @Service anotasyonu ile işaretlenmiş sınıflar Spring tarafından yönetilen bileşenlerdir. MyService sınıfının yapıcı metodu aracılığıyla DependentService bağımlılığı enjekte edilir.

Setter Injection

Spring Boot ayrıca setter enjeksiyonunu da destekler

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

// Bağımlılığı enjekte edeceğimiz sınıf
@Service
public class DependentService {
    public void performAction() {
        System.out.println("Bağımlılık kullanıldı.");
    }
}

// DI yapılacak sınıf
@Service
public class MyService {
    private DependentService dependentService;

    // Setter Injection ile bağımlılık enjekte ediliyor
    @Autowired
    public void setDependentService(DependentService dependentService) {
        this.dependentService = dependentService;
    }

    public void doSomething() {
        dependentService.performAction();
    }
}

Yukarıdaki örnekte, @Autowired anotasyonu ile işaretlenmiş setter metodu aracılığıyla DependentService bağımlılığı enjekte edilir.

Spring Boot Uygulamasında Kullanım

DI’ı kullanmak için Spring Boot uygulamanızın başlatma sınıfına uygun @SpringBootApplication anotasyonunu eklemeniz yeterlidir. Spring Boot, sınıfları tarama ve bağımlılıkları otomatik olarak enjekte etme görevini üstlenir.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

Yukarıdaki örnekte, @SpringBootApplication anotasyonu ile işaretlenmiş sınıf, Spring Boot uygulamanızın başlatma noktasıdır ve bağımlılıkları otomatik olarak yönetir.

Spring Boot, DI’ı kolayca uygulamanıza olanak tanır ve kodunuzu daha esnek ve test edilebilir hale getirir. DI, kodunuzu daha esnek ve bakımı daha kolay hale getiren güçlü bir tasarım desenidir. Bu makalede sunduğumuz Java kod örneği ile temel bir anlayış edinmişsinizdir. DIn’ı daha fazla derinlemesine öğrenmek ve projelerinizde kullanmak için pratik yapmanız önerilir.

 

DI, yazılım geliştirme sürecinde büyük bir öneme sahip bir tekniktir. Bağımlılıkların dışarıdan enjekte edilmesi sayesinde kodun esnekliği artar, testlerin yazılması kolaylaşır ve bakımı daha kolay hale gelir. Bu sayede, daha kaliteli, daha güvenilir ve daha sürdürülebilir bir yazılım geliştirme süreci sağlanır. DI’ı kullanarak kodunuzun performansını ve kalitesini artırabilirsiniz.

More Reading

Post navigation