Dependency Inversion (DIP) Prensibi

dependency inversion prensibi

Solid prensiplerinin sonuncusu bağımlılıkların tersine çevrilmesini de ele alarak ilk serinin sonuna geliyoruz. Bir önceki prensip Interface Segregation Prensibi incelemediyseniz bağlantıdan ulaşabilirsiniz. Dependency Inversion prensibi, Robert C. Martin aracılığıyla hayatımıza girmiş ve gevşek bağ (loosely coupled) terimini hayatımıza kazandırmıştır.

High-level modules should not depend on low-level modules. Both should depend on abstractions.

Robert C. Martin

Bu prensibe göre;

  • Yüksek seviyeli modüller, düşük seviyeli modüllere bağlı olmamalı; ikisinin de soyutlanması,
  • Soyutlamanın detaylara değil; detayların soyutlamaya bağlı olması beklenmektedir.

Maddeleri basitleştirecek olursak; sınıflar arası bağımlılıkların minimal seviyeye indirgenmesi ve bağımlılıkların sınıflar ile değil arayüzler (interface) ile kurulması gerektiğine dayanır. Sistemimizi bu şekilde tasarlamazsak yüksek seviyeli bileşenler, düşük seviyeli bileşenlere bağımlı kalacak ve düşük seviyeli bir bileşen içerisinde yapılacak olan değişikliğin zincirleme olarak bağımlı olan tüm yüksek seviye bileşenleri de değişikliğe zorlayacaktır. Dependency Inversion tam olarak da bu bağımlılığın tersine çevrilmesini amaçlamaktadır.

İlkeye aykırı olarak konuyu somutlaştırmak adına bir örnek yapalım. Senaryoya göre geleneksel 3 katmanlı mimariye sahip bir uygulamada UI katmanından Business katmanına ve buradan da Data Access katmanına sahip bir uygulamamız olduğunu düşünelim.

public class EntityDal
{
    public Entity Get(int id)
    {
        // Getting entity
    }

    public void Add(Entity entity)
    {
        // Adding a new entity
    }

    public void Update(Entity entity)
    {
        // Updating the entity
    }

    public void Remove(int id)
    {
        // Removing the entity
    }
}

Düşük seviyeli bileşene bağımlılığı olan yüksek seviyeli bileşenimizi de yazalım.

public class EntityManager
{
	private readonly EntityDal _entityDal;

	public EntityManager()
	{
		_entityDal = new EntityDal();
	}

	public Entity Get(int id)
	{
		return _entityDal.Get(id);
	}
    
	public void Add(Entity entity)
	{
		_entityDal.Add(entity);
	}

	public void Update(Entity entity)
	{
		_entityDal.Update(entity);
	}

	public void Remove(int id)
	{
		_entityDal.Remove(id);
	}
}

Mevcut kodumuzu inceleyecek olursak; ilk gözümüze çarpanın EntityManager sınıfının doğrudan EntityDal sınıfına bağımlı olduğunu görüyoruz. EntityDal içerisinde yapılacak olan bir değişiklik doğrudan EntityManager sınıfını da etkileyecektir. Şimdilik veritabanıyla yapılan işlemlerin ileride Xml olarak yapılacağını varsayarsak yine EntityManager içerisinde değişiklik yapmak zorunda kalacağız. Bu bağımlılığın ortadan kaldırması için soyutlama yapılmalıdır.

public interface IEntityRepository
{
    Entity Get(int id);
    void Add(Entity entity);
    void Update(Entity entity);
    void Remove(int id);
}
public class EntityDal : IEntityRepository
{
    public Entity Get(int id)
    {
        // Getting entity
    }

    public void Add(Entity entity)
    {
        // Adding a new entity
    }

    public void Update(Entity entity)
    {
        // Updating the entity
    }

    public void Remove(int id)
    {
        // Removing the entity
    }
}
public class EntityManager
{
	private readonly IEntityRepository _entityRepository;

	public EntityManager(IEntityRepository entityRepository)
	{
		_entityRepository = entityRepository;
	}

	public Entity Get(int id)
	{
		return _entityDal.Get(id);
	}
    
	public void Add(Entity entity)
	{
		_entityDal.Add(entity);
	}

	public void Update(Entity entity)
	{
		_entityDal.Update(entity);
	}

	public void Remove(int id)
	{
		_entityDal.Remove(id);
	}
}

Artık EntityManager sınıfı doğrudan IEntityRepository arayüzüne bağlıdır, ikinci maddede de belirtildiği gibi detaylar soyutlanmış, ileride farklı veri kaynaklarıyla çalışılmak istendiğinde yalnızca IEntityRepository uygulanarak modüller tak/çıkar mantığıyla kolaylıkla uygulanabilir.

You may also like...

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir