O Princípio de Inversão de Dependência verso sobre acoplamento entre partes do software e como ele deve ser minimizado. Mais especificamente dita duas regras:
Partes do software de mais alto nível não devem depender de partes de mais baixo nível. Ambas devem dependender de abstrações
Abstrações não devem depender dos detalhes de implementação. Detalhes de implementação devem depender das abstrações.
O princípio vale para quaisquer partes do software: podem ser módulos, pacotes ou classes. Quando falamos de "Partes do software de mais alto nível" estavamos falando das partes do software que definem comportamento e contratos e quando falamos de "Partes do software de mais baixo nível" falamos de implementações concretas.
O termo Abstrações é geral e se refere a uma abstração em qualquer um dos níveis. No nível da classe se refere a interfaces.
Então, para classes podemos reescrever assim:
Classes de mais alto nível não devem depender de classes de mais baixo nível. Ambas devem dependender de interfaces.
Interfaces não devem depender dos detalhes de implementação. Detalhes de implementação devem depender das interfaces.
O importante do princípio de inversão é que os detalhes não devem ditar o contrato estabelecido. É como vermos uma asbtração ser corrompida por parametros - muitas vezes booleanos
- que visam modificar algum detalhe da implementação. Ou seja, em vez do contrato estar apenas dizendo que operação deve ser feita, ele está também dizendo como deve ser feita.
É muito comum quando se pensa em uma interface já pensar como será possível satisfazer essa interface em uma implementação, e quando o programador não tem experiencia e não segue o Princípio de Inversão de Dependência a interface vai ficar cheia de detalhes relativos à implementação e sem os quais a implementação não é possível ( da forma como o programador pensou). É o famoso "eu passo este parametro e for true
, ele faz assim…". Isto é a violação do princípio da inversão de dependencia.
Se olharmos o primeiro ponto do Princípio da Inversão de Dependência atentamente ele diz que se A chama B, A não pode dependender de B, nem B depender de A. Ambos devem depender de um terceiro, a abstração, I.
Quando pensamos tadicionalmente em camadas, as camadas superiores chamam as camadas inferiores. Contudo, ha uma dupla dependencia. O chamador conhece o contrato de quem está chamando. O implementador define que contrato apresentar. "você me dá … e te devolvo…".
O Princípio da Inversão de Dependência aponta que este tipo de lógica está errada e deve ser invertida. Ou seja, uma terceira abstração deve ser introduzida. Ela não é ditada pela implementação. É puramente abstrata. Apenas deve satisfazer a necessidade dos chamadores. Depois, a implementação tem que corretamente implementar a abstração e não ao contrário.
A razão disto é que uma interface pode ser implementada de várias formas, por várias classes. O seu contraro não pode específico a uma delas, pois não vai funcionar para as outras. Ou vai funcionar, mas à custa de violação de outros princípios como o de Substituição de Liskov e/ou o de Segregação de Interfaces
Portanto, em vez de termos uma dependencia linear do topo para baixo
A --(depende de) → B --(depende de) → C
temos uma dependencia invertida
A --(depende de) → I ← (implementada por ) — B — (depende de) → Y ← (implementada por ) — C
Este princípio está na base da organização moderna de camadas presentes nas arquiteturas planas.
O Príncipio de Inversão de Dependência foi proposto por Robert C. Martin num paper, em 1994.
Também pela mão de Robert C. Martin este princípio entrou para o top 5 dos Principios de Orientação de Objetos, juntos conhecidos como os "Principios SOLID" (SOLID Principles) num trocadilho de palavras sugerindo que seguir os princípios SOLID, tornaria o código sólido, por oposição a frágil. O Princípio de Inversão de Dependência corresponde ao D pelo seu nome em inglês: Dependency Inversion Principle.