SOLID Principles

Example: Repository Pattern

Consider a data access scenario where a service class needs to interact with a data repository.

Violating DIP

public class ProductRepository
{
    public void Add(Product product)
    {
        // Code to add product to database
    }

    public Product Get(int id)
    {
        // Code to get product from database
        return new Product();
    }
}

public class ProductService
{
    private ProductRepository _productRepository;

    public ProductService()
    {
        _productRepository = new ProductRepository();
    }

    public void AddProduct(Product product)
    {
        _productRepository.Add(product);
    }

    public Product GetProduct(int id)
    {
        return _productRepository.Get(id);
    }
}

In this example, the ProductService class directly depends on the ProductRepository class, violating DIP.

Adhering to DIP

Introduce an abstraction for the repository.


public interface IProductRepository
{
    void Add(Product product);
    Product Get(int id);
}

public class ProductRepository : IProductRepository
{
    public void Add(Product product)
    {
        // Code to add product to database
    }

    public Product Get(int id)
    {
        // Code to get product from database
        return new Product();
    }
}

public class ProductService
{
    private readonly IProductRepository _productRepository;

    public ProductService(IProductRepository productRepository)
    {
        _productRepository = productRepository;
    }

    public void AddProduct(Product product)
    {
        _productRepository.Add(product);
    }

    public Product GetProduct(int id)
    {
        return _productRepository.Get(id);
    }
}

In this design, the ProductService class depends on the IProductRepository interface. This makes it easy to swap out the ProductRepository for a different implementation if needed (e.g., a mock repository for testing).