Skip to content

Instantly share code, notes, and snippets.

@lsfernandes92
Last active October 1, 2019 18:38
Show Gist options
  • Save lsfernandes92/c30325b272a66d5b9dbe42ebb7ce7847 to your computer and use it in GitHub Desktop.
Save lsfernandes92/c30325b272a66d5b9dbe42ebb7ce7847 to your computer and use it in GitHub Desktop.
solid.md

SOLID

Single Responsability Principle

  • Foca principalmente em coesão e encapsulamento
  • Métodos principais com ajuda de métodos privados
  • Feature envy

Uma classe coesa é aquela que possui uma única responsabilidade

Colocar cada regras em classes diferentes, isolando implementação e lógicas

Métodos privados são excelentes para melhorar a legibilidade de um método maior Se você percebeu que existem duas diferentes responsabilidades em uma mesma classe, separe-os de verdade.

A solução nesse momento não importa, contanto que você perceba que a legibilidade do método público ficou muito melhor(métodos privados)

Novamente, o principal aqui é entender o problema resolvido e não tanto a implementação. Se seu código exige que uma mudança seja feita em vários pontos diferentes para que ela seja propagada, talvez você esteja passando por um problema de projeto. Refatore seu código e encapsule esse comportamento em um único lugar

Lembre-se de que o programador não deve nunca usar CTRL+F para programar e buscar pelos pontos de mudança.

Algumas vezes não temos como não alterar em mais de um ponto. Por exemplo, sempre que você muda uma entidade no seu sistema, provavelmente essa mudança deverá ser propagada para um método do seu controller, e para uma JSP que representa sua view. Não há como fugir.

Evitar o comportamento de uma classe fazer chamadas de outra classe(feature envy)

Dois comportamentos "pertencem" ao mesmo conceito/ responsabilidade se ambos mudam juntos

Para identificar classes não coesas procure por classes que possuem muitos métodos diferentes; por classes que são modificadas com frequência; por classes que não param nunca de crescer


Dependency Inversion Principle

  • Ter classes pouco acopladas
  • Sempre que uma classe for depender de outra, ela deve depender sempre de outro módulo mais estável do que ela mesma
  • Depender de abstrações, por serem coesas e instaveis
  • 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 não devem depender de detalhes. Detalhes devem depender de abstrações.

O grande problema do acoplamento é que uma mudança em qualquer uma das classes pode impactar em mudanças na classe principal, propagando problemas, e assim por diante.

A partir do momento em que uma classe possui muitas dependências, todas elas podem propagar problemas para a classe principal

O reúso dessas classes também fica cada vez mais difícil, afinal, se quisermos reutilizar uma determinada classe em outro lugar, precisaremos levar junto todas suas dependências

A classe, quando possui muitas dependências, torna-se muito frágil, fácil de quebrar.

Será que conseguimos acabar com o acoplamento? Ou seja, fazer com que as classes não dependam de nenhuma outra? É impossível.

Acoplar-se a classes, interfaces, módulos, que sejam estáveis, que tendam a mudar muito pouco.

Acoplamento é geralmente olhar quais classes de que uma determinada classe depende. Contar isso é importante para detectarmos classes muito acopladas. O outro lado, que é olhar quantas classes dependem de uma classe, nos ajuda a dizer se a classe é ou não estável.

Interfaces são um bom caminho para isso porque tendem a mudar pouco

Se você está programando alguma classe qualquer com regras de negócio, e precisa depender de outro módulo, idealmente esse outro módulo deve ser uma abstração. Tente ao máximo não depender de outras implementações (afinal, elas são instáveis).

Abstrações não devem depender de implementações! Abstrações devem ser estáveis

Open closed principle

  • A classe deve estar pronto para extensão e fechada para modificações

Não confundir o processo de mover código ou refatorar com o processo de adicionar uma nova funcionalidade

A ideia é que suas classes sejam abertas para extensão. Ou seja, estender o comportamento delas deve ser fácil. Mas, ao mesmo tempo, elas devem ser fechadas para alteração. Ou seja, ela não deve ser modificada (ter seu código alterado) o tempo todo.

Sempre que instanciamos classes diretamente dentro de outras classes, perdemos a oportunidade de trocar essa implementação em tempo de execução(focar em passar a implementações por construtor)

Liskov Substitutive Principle

  • Não descarte herança, apenas favoreça a composição
  • Falta de encapsulamento da classe pai para as filhas
  • Não podemos nunca apertar uma precondição, e nem afrouxar uma pós-condição.

Crie suas classes pensando em herança, ou então proíba-a

Classes filhas precisam respeitar os contratos definidos pela classe pai

Toda classe ou método tem as suas pré e pós-condições. Por precondições, entenda os dados que chegam nela.

As pós-condições são o outro lado da moeda. O que aquele comportamento devolve?

Por isso, ao pensar em modelar hierarquias de classe usando herança, lembre-se do acoplamento entre classe pai e filho. Modele hierarquias nas quais as classes filhos precisam conhecer pouco (ou não conhecer nada) dos detalhes da classe pai.

O ideal seria o método ter a sua própria implementação, sem depender da implementação do pai

Lembre-se, portanto, de tentar ao máximo reduzir o acoplamento entre a classe pai e a classe filho.

Se a classe filho conhece demais da implementação da classe pai, é porque ela não encapsulou bem seus detalhes de implementação.

Queremos mesmo permitir que a classe filho altere atributos da classe pai sem qualquer tipo de controle?

A composição tem vantagens. A relação da classe principal com a classe dependida não é tão íntima quanto a relação existente entre classes pai e filho, portanto, quebrar o encapsulamento é mais difícil.

Herança deve ser usada quando existe realmente a relação de X é um Y. Por exemplo, Gerente é um Funcionário, ou ICMS é um Imposto. Não use herança caso a relação seja de composição, ou seja, X tem um Y, ou X faz uso de Y.

Interface Segregation Principle

  • Acoplamento, coesão, simplicidade e encapsulamento fazem sentido não só para classes concretas, mas também para interfaces

Interfaces gordas são aquelas interfaces que contêm muitas responsabilidades diferentes

Evitar que classes clientes quebrem contratos com interfaces, ou seja, uma classe tem q fazer uso dos metodos da interface senão provavelmente temos um problema de encapsulamento/coesão

Se uma classe não é coesa, dividimo-la em duas ou mais classes; se uma interface não é coesa, também a dividimos em duas ou mais interfaces

Interfaces coesas são aquelas que possuem também apenas uma única responsabilidade.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment