# 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.