Princípio de Inversão de Dependência vs “Programe para uma interface, não para uma implementação”
12
Estou tentando entender como o Princípio da Inversão da Dependência difere do princípio "programa para uma interface, não uma implementação".
Entendo o que significa "Programa para uma interface, não para uma implementação". Também entendo como isso permite projetos mais flexíveis e sustentáveis.
Mas não entendo como o Princípio de Inversão de Dependência é diferente do princípio "Programa para uma interface, não uma implementação".
Eu li sobre o DIP em vários lugares da web e isso não esclareceu minha confusão. Ainda não vejo como os dois princípios diferem um do outro. Obrigado pela ajuda.
"Programar em uma interface" significa que não depende de um tipo concreto para fazer seu trabalho , mas não especifica como você deve obter sua dependência.
O "Princípio da inversão de dependência" diz que um objeto não deve controlar a criação de suas dependências, deve apenas anunciar de que dependência ele precisa e deixar que o chamador o forneça . Mas não especifica se a dependência deve ser um tipo concreto ou uma interface.
Ilustrarei as diferenças com algum código C #.
O exemplo a seguir depende de um tipo concreto e controla a criação da própria dependência. Segue-se nem "programa para uma interface" nem "inversão de dependência":
public class ThingProcessor
{
MyThing _myThing;
public ThingProcessor()
{
_myThing = new MyThing();
}
public void DoSomething()
{
_myThing.DoIt();
}
}
O exemplo a seguir depende de uma interface, mas controla a criação da própria dependência. Segue "programa para uma interface", mas não "inversão de dependência":
public class ThingProcessor
{
IMyThing _myThing;
public ThingProcessor()
{
_myThing = ThingFactory.GiveMeANewMyThing();
}
public void DoSomething()
{
_myThing.DoIt();
}
}
O exemplo a seguir depende de um tipo concreto, mas solicita que sua dependência seja criada e passada para ele. Segue "inversão de dependência", mas não "programa para uma interface":
public class ThingProcessor
{
MyThing _myThing;
public ThingProcessor(MyThing myThing)
{
_myThing = myThing;
}
public void DoSomething()
{
_myThing.DoIt();
}
}
O exemplo a seguir depende de uma interface e solicita que sua dependência seja criada e passada para ela. Segue "inversão de dependência" e "programa para uma interface":
public class ThingProcessor
{
IMyThing _myThing;
public ThingProcessor(IMyThing myThing) // using an interface
{
_myThing = myThing;
}
public void DoSomething()
{
_myThing.DoIt();
}
}
O que você está falando é sobre a injeção dependente. E inversão de dependência e injeção de dependência são duas coisas diferentes.
eufórico
1
@Euphoric Estou falando do Princípio da Inversão da Dependência, que é um conceito abstrato, usando a Injeção de Dependência como exemplo concreto de implementação. Eu entendo a diferença.
Eric Rei
1
@EricKing Então você deve dizer explicitamente que, em sua resposta, em vez de "O" Princípio da inversão de dependência "diz ...", o que obviamente está errado se você ler minha resposta.
eufórico
1
Eu concordo com eufórico. O Princípio da Inversão da Dependência diz que as camadas de código de nível superior devem depender de partes de código de nível inferior, e não vice-versa. Por exemplo, PrintStreamdeve depender da interface estabelecida por ByteOutputStream. A injeção de dependência não menciona nada sobre quem deve depender de quem.
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 nunca devem depender de detalhes. Os detalhes devem depender de abstrações.
Interface é uma abstração e implementação é um detalhe. Se você substituí-los nas duas instruções anteriores, obtém basicamente "o código deve depender de interfaces e não de implementações". E isso soa como a mesma coisa para mim.
Esta deve ser a resposta aceita, a outra resposta mais votada é enganosa
Sameh Deabes
2
As interfaces são uma maneira de implementar o DI. Se você especificar uma interface como parâmetro no método construtor de uma classe, poderá entregar qualquer objeto que desejar ao método construtor, desde que esse objeto implemente a interface do parâmetro construtor.
Em outras palavras, programar uma interface permite alterar a implementação dessa interface. É assim que podemos substituir objetos reais por objetos reais durante o teste de unidade, especificar diferentes provedores de dados e assim por diante.
PrintStream
deve depender da interface estabelecida porByteOutputStream
. A injeção de dependência não menciona nada sobre quem deve depender de quem.Eles são geralmente a mesma coisa. Se você ler O que é o Princípio da inversão de dependência e por que é importante? e princípio de inversão de dependência , você perceberá que os dois "princípios" falam basicamente da mesma coisa.
Interface é uma abstração e implementação é um detalhe. Se você substituí-los nas duas instruções anteriores, obtém basicamente "o código deve depender de interfaces e não de implementações". E isso soa como a mesma coisa para mim.
fonte
As interfaces são uma maneira de implementar o DI. Se você especificar uma interface como parâmetro no método construtor de uma classe, poderá entregar qualquer objeto que desejar ao método construtor, desde que esse objeto implemente a interface do parâmetro construtor.
Em outras palavras, programar uma interface permite alterar a implementação dessa interface. É assim que podemos substituir objetos reais por objetos reais durante o teste de unidade, especificar diferentes provedores de dados e assim por diante.
fonte