Middle+
Quais mecanismos ajudam a cumprir o princípio da inversão de dependências?
sobes.tech IA
Resposta da IA
O princípio da inversão de dependências (Dependency Inversion Principle - DIP) é cumprido através de vários mecanismos interrelacionados:
-
Abstrações:
- Interfaces e classes abstratas definem contratos, não implementações concretas. Módulos de alto nível dependem dessas abstrações, não de classes concretas de baixo nível.
-
Injeção de dependências (Dependency Injection - DI):
- Em vez de uma classe criar suas dependências diretamente, elas são passadas de fora. Isso permite substituir facilmente as implementações de dependências sem alterar o código da classe.
- Sintaxe C# para injeção via construtor:
public class HighLevelModule { private readonly ILowLevelDependency _dependency; // Dependência da abstração public HighLevelModule(ILowLevelDependency dependency) // Injeção via construtor { _dependency = dependency; } public void PerformAction() { _dependency.Execute(); // Uso da dependência via abstração } } - Sintaxe C# para injeção via propriedade:
public class AnotherHighLevelModule { public ILowLevelDependency Dependency { get; set; } // Injeção via propriedade public void PerformAction() { Dependency?.Execute(); // Uso da dependência via abstração } } - Sintaxe C# para injeção via método:
public class YetAnotherHighLevelModule { public void PerformAction(ILowLevelDependency dependency) // Injeção via método { dependency.Execute(); // Uso da dependência via abstração } }
-
Contêineres IoC (Inversion of Control Containers):
- Frameworks que automatizam o processo de gestão e injeção de dependências. Criam instâncias de classes e resolvem suas dependências de acordo com regras configuradas.
- Exemplo de uso de um contêiner IoC popular (por exemplo, StructureMap):
// Registro de dependência // container.Configure(cfg => // { // cfg.For<ILowLevelDependency>().Use<ConcreteLowLevelDependency>(); // Registro da abstração e sua implementação concreta // cfg.For<HighLevelModule>().Use<HighLevelModule>(); // }); // Obtenção de uma instância da classe com dependências resolvidas // var highLevelModule = container.GetInstance<HighLevelModule>(); // highLevelModule.PerformAction();
-
Fábricas:
- Classes que criam instâncias de outras classes. Podem ocultar detalhes de criação de implementações concretas e retornar abstrações.
- Sintaxe C# para exemplo de uso de uma fábrica:
public interface ILowLevelDependencyFactory { ILowLevelDependency Create(); } public class LowLevelDependencyFactory : ILowLevelDependencyFactory { public ILowLevelDependency Create() { return new ConcreteLowLevelDependency(); // Criação de uma implementação concreta } } public class HighLevelModuleWithFactory { private readonly ILowLevelDependency _dependency; public HighLevelModuleWithFactory(ILowLevelDependencyFactory factory) // Injeção da fábrica { _dependency = factory.Create(); // Uso da fábrica para criar a dependência } public void PerformAction() { _dependency.Execute(); } }
-
Princípio do menor conhecimento (Lei de Demeter):
- Embora não seja um mecanismo direto do DIP, seguir esse princípio (falar apenas com "seus amigos próximos") muitas vezes reduz as dependências diretas e facilita a aplicação do DIP.