Princípio de Segregação de Interface
Olá pessoal, vou fazer alguns posts sobre S.O.L.I.D. O primeiro que gostaria de abordar com vocês é:
S O L ISP - Interface Segregation Principle D
A definição basicamente é:
“Clients should not be forced to depend upon interfaces that they do not use.”
Para mais detalhes sobre a definição, segue o link do artigo The Interface Segregation Principle que é um resumo de um capitulo do livro “Agile Principles, Patterns, and Practices in C#” de Martin C. Robert e Martin Micah.
Gostaria de mostrar um exemplo real onde o principio é quebrado. O exemplo está em C#.
O meu problema era que eu tinha uma interface onde todas as classes que precisavam fazer alguma persistência tinham que implementar, nesta interface eu tinha definido três métodos: Save, Delete e GetBy, porém, nem todas as classes precisavam implementar todos estes métodos.
1 | public interface IRepository<TEnt> |
O próximo código mostra uma interface para definir as operações que uma ordem poderá realizar na base de dados, já que a mesma estende da interface IRepository.
1 | public interface IOrderRepository : IRepository<Order> { } |
O código abaixo é a classe que irá implementar os métodos definidos na interface IOrderRepository que por sua vez irá implementar os métodos definidos na interface IRepository já que a interface IOrderRepository estende da interface IRepository.
1 | public class OrderRepository : IOrderRepository { |
Percebem que o método Delete tem um throw new NotImplementedException(), porque eu não vou usar este método para nada, ele só está ai porque está definido na minha interface IRepository, e por este motivo eu sou obrigado a implementá-lo, o problema é que quando eu for utilizar a classe OrderRepository não tem como eu saber se o método delete tem implementação ou não e quando eu chamar o mesmo irá gerar uma exceção. Este é um exemplo que quebra o principio ISP.
Abaixo uma forma de resolver este problema. Notem que eu quebrei a interface IRepository em outras três interfaces:
- IDeleteRepository: Que irá conter a definição do método Delete.
- IGetRepository: Que irá conter a definição do método GetBy.
- ISaveRepository: Que irá conter a definição do método Save.
A interface IRepository agora estende das três interfaces definidas acima, caso tenha alguma interface que precise definir as três operações, pode estender da interface IRepository.
1 | public interface IDeleteRepository<in TEnt> |
Notem agora que a interface IOrderRepository não estende mais a interface IRepository e sim as interfaces: IGetRepository e ISaveRepository.
1 | public interface IOrderRepository |
Agora a nossa classe OrderRepository não contém mais o método Delete.
1 | public class OrderRepository : IOrderRepository { |
Vocês podem notar que para resolver o problema do throw new NotImplementedException() eu tive que criar interfaces mais especificas, e a nossa classe final contém agora apenas os métodos que realmente precisa.
O código abaixo não é importante para o nosso exemplo, será mostrando apenas para completar os códigos acima.
Está é a classe base das minhas entidades. Como podem notar a interface IRepository pede a definição de um tipo que herde está classe.
Note que ela contém uma propriedade chamada Id do tipo int, caso você tenha a necessidade de ter em cada entidade uma propriedade Id de um tipo diferente você precisa apenas deixar genérico o tipo desta propriedade, como é apenas um exemplo não adicionei está complexidade a minha classe.
1 | public class Entity { |
A classe abaixo é a minha classe de Order, note que ela herda da classe Entity que foi explicada acima.
1 | public class Order : Entity { } |
Obrigado pela visita e espero que tenha gostado, qualquer dúvida é só entrar em contato.