DEV Community

Giovanne Barbosa
Giovanne Barbosa

Posted on • Updated on

SOLID - DIP

Princípio da inversão de dependência

Módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender de abstrações; Abstrações não devem depender de detalhes. Detalhes devem depender de abstrações.

Dependa de uma abstração e não de uma implementação.

Por exemplo:

Temos uma classe Petshop que recebe no seu construtor um PetRepositorioMySQL e possui o método CadastrarOuAtualizarPet() que verifica se o Pet informado já existe e o atualiza e caso contrário, cria um novo cadastro.

    public class Petshop
    {
        private readonly PetRepositorioMySQL _petRepositorioMySQL;
        public Petshop()
        {
            _petRepositorioMySQL = new PetRepositorioMySQL();
        }

        public void CadastrarOuAtualizarPet(string nome)
        {
            var pet = _petRepositorioMySQL.Get(nome);

            if (pet == null)
                _petRepositorioMySQL.Insert(pet);
            else
                _petRepositorioMySQL.Update(pet);
        }
    }
Enter fullscreen mode Exit fullscreen mode

O problema é que se um dia nós resolvêssemos usar uma PetRepositorioSQLServer no lugar da PetRepositorioMySQL, mesmo as duas possuindo os mesmos metódos, precisaríamos mudar a nossa classe Petshop. Nossa classe não deveria ter que saber como se instancia este repositório ou como que ele se comporta internamente. Só precisamos saber o que ele recebe e o que retorna.
Devido a isso, estamos quebrando o princípio da inversão de dependência.

Solução:

Criamos a interface IRepositorioGenerico e fazemos com que nossa classe PetRepositorioMySQL implementa-a.

    public class PetRepositorioMySQL : IRepositorioGenerico
    {
        public Pet Get(string nome)
        {
            throw new NotImplementedException();
        }

        public void Insert(Pet pet)
        {
            throw new NotImplementedException();
        }

        public void Update(Pet pet)
        {
            throw new NotImplementedException();
        }
    }
Enter fullscreen mode Exit fullscreen mode

Dentro da classe Petshop, nós injetamos nossa classe PetRepositorioMySQL representada pela sua interface IRepositorioGenerico.

    public class Petshop
    {
        private readonly IRepositorioGenerico _repositorio;
        public Petshop(IRepositorioGenerico repositorio)
        {
            _repositorio = repositorio;
        }

        public void CadastrarOuAtualizarPet(string nome)
        {
            var pet = _repositorio.Get(nome);

            if (pet == null)
                _repositorio.Insert(pet);
            else
                _repositorio.Update(pet);
        }
    }
Enter fullscreen mode Exit fullscreen mode

Assim a Petshop não é obrigada a instanciar o repositório, pois quem consumir esta classe deve passar as instâncias já criadas no construtor dela. E se caso um dia quisermos mudar o repositório, não precisaremos alterar a classe PetShop, desde que o novo repositório implemente a mesma interface. Desta forma, invertemos o controle.

Discussion (0)