# Orientação a Objetos e SOLID para Ninjas
###### tags: `Basement` `Clube do Livro`
## Capítulo 02 - A coesão e o tal do SRP
- Uma classe coesa é aquela que possui uma única responsabilidade.
- Possui menos código e seu reúso é maior.
- A chance de classes não coesas terem defeitos é enorme.
- Toda classe que não é coesa não para de crescer nunca.
- Só quebrar um método grande em vários pequenos não é reúso.
- O programador não deve nunca usar `CTRL+F` para programar e buscar pelos pontos de mudança.
- Existem exceções para decisões explícitas de design, como o padrão arquitetural MVC, etc.
- O problema são as dependências implícitas.
- Métodos privados servem de apoio aos métodos públicos.
- Eles ajudam a aumentar a legibilidade de nossos códigos.
- Se seu método público crescer muito ou sofrer alterações constantes, talvez valha a pena extraí-lo para uma classe específica.
- A boa prática para controllers é fazer com que essas classes apenas coordenem processos.
- O **SRP ou Single Responsibility Principle** é o principío do SOLID que nos lembra da coesão.
- A classe deve ter uma, e apenas uma, razão para mudar.
- É fácil entender que a classe deve ter apenas uma responsabilidade.
- O difícil é definir o que é uma responsabilidade.
- Dois comportamentos pertencem ao mesmo conceito/responsabilidade se mudam juntos.
- Escrever código de qualidade é incremental.
- Classes coesas são mais fáceis de serem mantidas, reutilizadas e tendem a ter menos bugs.
## Capítulo 03 - Acoplamento e o tal do DIP
- A máxima da orientação a objetos é que tenha classes que são muito coesas e pouco acopladas.
- O grande problema do acoplamento é que uma mudança em qualquer uma das classes pode impactar em mudanças na classe principal.
- A partir do momento em que uma classe possui muitas dependências, todas elas podem propagar problemas para a classe principal.
- As dependências de uma classe podem ter suas próprias dependências, gerando uma grande árvore de classes que devem ser levadas junto.
- Acoplamento bom é aquele em que a dependência é estável, como List e String.
- Muda muito pouco ou quase nunca muda.
- Acoplamento é geralmente olhar quais classes de que uma determinada classe depende.
- Programar voltado para interfaces faz com que o código seja flexível e estável.
- Interfaces coesas são aquelas cujos comportamentos são simples e bem definidos.
- Tendem a mudar menos e são mais reutilizáveis.
- A ideia de reduzir o problema do acoplamento não é deixar de acoplar, é começar a acoplar com módulos estáveis.
- **DIP ou Princípio da Inversão de Dependências** é aquele cuja ideia é: sempre que uma classe for depender de outra, ela deve depender sempre de outro módulo mais estável do que ela mesma.
- Se A depende de B, a ideia é que B seja mais estável que A.
- Mas B depende de C, logo a ideia é que C seja mais estável que B.
- Andar sempre em direção à estabilidade.
- Abstrações tendem a ser estáveis e implementações instáveis.
- O princípio diz:
- 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.
- Não confundir com injeção de dependência, que é a ideia de você ter os parâmetros no construtor e alguém injetar essas dependências para você.
## Capítulo 04 - Classes abertas e o tal do OCP
- Código deve estar sempre pronto para evoluir.
- A discussão é sobre balancear acoplamento e coesão.
- O que ajuda a ter classes coesas que evoluam facilmente é escrever classes que sejam abertas para extensão mas fechadas para modificação.
- **Open Closed Principle**.
- Flexibilizar o código que realmente precisa de códigos flexíveis.
- Seja criterioso, sejam simples em códigos que podem ser simples.
- Se está difícil de testar, o código pode ser melhorado.
- Classes abertas são aquelas que deixam explícitas suas dependências.
- Assim podemos mudar as implementações concretas que são passadas para ela a qualquer momento, o que faz com que o resultado final da execução mude de acordo com as classes que foram passadas pra ela.
- Mudar o comportamento sem mudar o código.
## Capítulo 05 - O encapsulamento e a propagação de mudanças
- Encapsulamento é o nome que damos à ideia de a classe esconder os detalhes de implementação.
- Como o método faz o trabalho dele.
- Traz dois ganhos:
- Facilidade para alterar a implementação.
- Se o código não está bem encapsulado, isso implica em regras de negócio espalhadas por lugares diferentes.
- Uma classe (ou método) bem encapsulada é aquela que esconde bem a maneira como faz as coisas.
- A classe deve apenas deixar claro o que ela faz, quais são as operações que ela provê para as classes que farão uso dela.
- Intimidade inapropriada são códigos que entendem mais do que deveriam sobre o comportamento de outra classe.
- Tell, don't ask.
- Sistemas difíceis de se manter são aqueles que não pensam na propagação de mudança.
- A Lei de Demeter sugere que evitemos o uso de invocações em cadeia.
- Para diminuir a propagação de mudanças.
- Antes de criar setters, pensar se eles não gerarão probelmas de encapsulamento no futuro.
- Fazer com que getters sempre devolvam cópias dos objetos originais ou bloqueiem a alteração de alguma forma.
- Como saber se classes e métodos estão encapsulados?
- Olhar pra ela e perguntar/responder: o quê? Como?
- O “o quê?” você tem que ser capaz de responder, porque o nome do método tem que lhe dizer isso.
- O “como?” você não tem que conseguir responder. Se conseguir responder, não está encapsulado.
## Capítulo 06 - Herança x composição e o tal do LSP
- "Crie suas classes pensando em herança, ou então proíba-a".
- Classes filhas precisam respeitar os contratos definidos pela classe pai.
- **Liskov Substitutive Principle**
- Toda classes tem as suas pré e pós-condições.
- Pré-condições são os dados que chegam nela.
- Quais são as restrições iniciais para que determinado método funcione corretamente?
- Pós-condições são o que o comportamento devolve.
- Uma pré-condição pode ser afrouxada, mas a pós-condição só pode ser apertada.
- É sobre isso que o princípio L discute, ao herdar você deve sempre lembrar do contrato estabelecido pela classe pai.
- Uma classe filho é totalmente acoplada à classe pai.
- Modele hierarquias nas quais as classes filhos precisam conhecer pouco ou nada dos detalhes da classe pai.
- Se a classe filho conhece demais da implementação da classe pai, é porque ela não encapsulou bem seus detalhes de implementação.
- Evitar o uso de protected.
- Usar composição ao invés de herança.
- São vantagens da composição:
- A relação da classe principal com a classe dependida não é tão íntima quanto a relação entre classes pai e filho.
- Quebrar o encapsulamento é mais difícil.
- Permite flexibilidade.
- Facilidade de escrever testes automatizados.
- Quando usar herança?
- Herança deve ser usada quando existe realmente a relação de X é um Y.
- 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.
- Use herança para reaproveitar código que realmente faz sentido, e composição para trechos de código que precisam de mais flexibilidade.
- Não descarte herança, apenas favoreça a composição.
## Capítulo 07 - Interfaces magras e o tal do ISP
- Princípio da segregação de Interface, ISP ou **Interface Segregation Principle**.
- Se uma interface não é coesa, dividimos em duas ou mais interfaces.
- Dessa forma, cada classes filha implementa quais interfaces forem necessárias, sem precisar fazer gambiarras.
- Interfaces coesas são aquelas que possuem também uma única responsabilidade.
- Possibilitam maior reúso e tendem a ser mais estáveis.
- Em Domain-Driven Design (DDD), Eric Evans comenta sobre os *repositórios*, que seriam abstrações para a camada de acesso a dados.
- Essa interface em particular nos seria bastante útil se tivéssemos a necessidade de mudar a maneira de acesso a dados.
- Interfaces são fundamentais em bons sistemas orientados a objetos. Tomar conta delas é importante.