.NET - Inversão de controle e Injeção de dependência para iniciantes
Você já ouviu falar de Inversão de Controle (IC) ? e de Injeção de Dependência(ID) ? |
Já ouviu falar que que IC e ID são a mesma coisa ? ou não ?
Bem, este artigo trata do assunto de uma forma bem objetiva e sem rodeios apresentando os principais conceitos envolvidos nessa discussão.
A IC e a ID não são a mesma coisa.
A Inversão de controle(Ioc) é um princípio e injeção de dependência(ID) é um padrão que usamos para implementar a inversão de controle ou seja: geralmente fazemos a Inversão de controle utilizando a injeção de dependência.
Vamos montar um cenário bem ingênuo para explicar o assunto mais uma vez...
Considere a class DAL, cujo código vemos abaixo, na versão C# e VB .NET:
public class DAL { private cSqlServer _sql; public DAL() { _sql = new cSqlServer(); } } |
Public Class DAL Private _sql As cSqlServer Public Sub New() _sql = New cSqlServer() End Sub End Class |
C# | VB .NET |
No exemplo acima, onde temos a classe DAL. O construtor padrão da classe DAL cria um objeto da classe cSqlServer.
Isso significa que a classe DAL é responsável pela criação de um objeto da classe SqlServer.
Portanto, existe um forte acoplamento entre a classe DAL e classe SqlServer.
Isso nos trás os seguintes problemas...
1- A Classe DAL é
responsável pela criação de um objeto da classe SqlServer;
2- A Classe SqlServer está diretamente referenciada na classe
DAL;
3- A classe DAL deveria estar ciente do tipo de classe SqlServer;
Acoplamento
- Acoplamento é o nível de
dependência/conhecimento que pode existir entre as
classes; - Coesão é o
nível de integralidade interna de uma classe; (Veja o principio da
responsabilidade única - SRP) Portanto quanto mais forte o acoplamento e mais baixa a coesão de uma classe mais difícil ela será de entender, manter e ser reusada. |
Neste exemplo temos um forte acoplamento entre a classe DAL e a classe cSqlServer pois quem controla a criação de uma instância da classe cSqlServer é a classe DAL.
A classe DAL é responsável por obter uma referência a classe cSqlServer.
Qualquer alteração que ocorra na classe cSqlServer vai afetar diretamente a classe DAL pois esta possui uma referência a classe cSqlServer.
Como fazer com que a classe DAL não seja afetada pelas mudanças feitas na classe cSqlServer sem perder a referência para a classe cSqlServer ?
Como diminuir o acoplamento entre a classe DAL e a classe cSqlServer ?
A solução é mudar a parte da criação do objeto na classe DAL.
Precisamos mudar o controle de criação de objetos e podemos fazer isso usando o padrão inversão de controle (IoC).
Os princípios da Inversão de Controle (IoC) podem ser expressos da seguinte forma:
1- Classes principais agregando outras não devem depender da implementação direta dessas classes, ambas as classes devem depender de uma abstração;
2- Uma abstração não deve depender dos detalhes, os detalhes devem depender da abstração;
Mas onde entra a injeção de dependência nesta história ?
A Inversão de controle é implementada por meio da injeção de dependência, porque Inversão de controle é um princípio e a injeção de dependência é um padrão que usamos para implementar a IoC.
Como implementar o inversão de controle ?
Uma das formas de implementar a inversão de controle é através da injeção de dependência (DI) que nos trás os seguintes benefícios;
Em suma, a DI isola a implementação de um objeto da construção do objeto do qual ele depende.
Podemos implementar a injeção de dependência das seguintes maneiras:
A figura abaixo mostra um esquema de omo implementar a IoC(inversion of control) usando as 4 formas de injeção de dependência (DI-dependency injection):
Vejamos um resumo da aplicação de cada uma das formas de implementação da da IoC via DI:
1- Aplicando IoC com DI via Construtor
public class DAL { private ISql _sql; public DAL(ISql obj) { _sql = obj; } } |
Public Class DAL Private _sql As ISql Public Sub New(obj As ISql) _sql = obj End Sub End Class |
C# | VB .NET |
Nesta metodologia, passamos um objeto SQL para a classe DAL.
No código acima você pode ver que há um construtor com parâmetros na classe DAL.
Com isso não existe mais um acoplamento forte entre essas classes.
Este método não é útil se somente pode usar um construtor padrão.
2- Aplicando IoC com DI via get/set
public class DAL { private ISql _sql; public Isql Sql { set { _sql = value; } } } |
Public Class DAL Private _sql As ISql Public WriteOnly Property Sql() As Isql Set _sql = value End Set End Property End Class |
C# | VB .NET |
Neste método expomos um objeto SQL através dos métodos get/set da classe DAL.
Mas ela viola a regra de encapsulamento da OOP. Encapsulamento significa esconder detalhes internos de um objeto.
Então, aqui, em vez de esconder um objeto, estamos expondo um objeto.
3- Aplicando IoC com DI via Interface
interface ISqlDI { void setConnection(ISql obj); } public class DAL : ISqlDI { private ISql _sql; public void setConnection(ISql obj) { _sql = obj; } } |
Interface ISqlDI Sub setConnection(obj As ISql) End Interface Public Class DAL Implements ISqlDI Private _sql As ISql Public Sub setConnection1(obj As ISql) Implements ISqlDI.setConnection _sql = obj End Sub End Class |
C# | VB .NET |
Neste método implementamos uma interface que tem um método setConnection que define o objeto SQL.
A classe DAL implementa uma interface SQL. Assim, com a ajuda do método setConnection o cliente pode injetar um objeto SQL na classe DAL.
4- Aplicando IoC com DI via Service Locator
static class LocateConnection { public static ISql getConnection() { } } public class DAL { private ISql _sql; public DAL() { _sql = LocateConnection.getConnection(); } } |
NotInheritable Class LocateConnection Public Shared Function getConnection() As ISql End Function End Class Public Class DAL Private _sql As ISql Public Sub New() _sql = LocateConnection.getConnection() End Sub End Class |
C# | VB .NET |
Neste método criamos uma classe estática - LocateConnection - e um método estático - getConnection - nesta desta classe.
A classe DAL chama esse método estático do seu construtor padrão , e , desta forma o objeto SQL é injetado na classe DAL.
Dessa forma vimos um resumo sobre o conceito da Inversão de controle e as formas de implementar a IoC usando a injeção de dependência(DI).
Heb 2:1
Por isso convém atentarmos mais diligentemente para as coisas que ouvimos, para que em tempo algum nos desviemos delas.Heb 2:2
Pois se a palavra falada pelos anjos permaneceu firme, e toda transgressão e desobediência recebeu justa retribuição,Heb 2:3
como escaparemos nós, se descuidarmos de tão grande salvação? A qual, tendo sido anunciada inicialmente pelo Senhor, foi- nos depois confirmada pelos que a ouviram:Heb 2:4
testificando Deus juntamente com eles, por sinais e prodígios, e por múltiplos milagres e dons do Espírito Santo, distribuídos segundo a sua vontade.
Referências: