Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Solid Design Principles

Everton Carlos
October 30, 2024
1

Solid Design Principles

The SOLID principles are essential for any developer aiming to build robust, flexible, and maintainable systems. In this presentation, I explored each of the five object-oriented design principles that make up SOLID:

Single Responsibility Principle
Open/Closed Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
Applying these principles results in more modular code, adaptable to changes, making software development more efficient. In this session, I shared practical examples and use cases, demonstrating how SOLID can be applied in day-to-day development to improve system architecture.

Everton Carlos

October 30, 2024
Tweet

Transcript

  1. Corporativo | Interno @zupinnovation zup.com.br <> Single Responsability Princípios SOLID

    Open Closed Liskov Substitution Interface Segregation Dependency Inversion
  2. Corporativo | Interno Benefícios @zupinnovati on zup.com.br Facilidade em manter.

    Facilidade em ajustar. Facilidade em estender. Facilidade em testar. Facilidade em entender. Facilidade em reaproveitar.
  3. Corporativo | Interno @zupinnovation zup.com.br <> Uma classe deve ter

    uma, e apenas uma razão para mudar. Single Responsability Principle Princípio da Responsabilidade única S
  4. Corporativo | Interno @zupinnovation zup.com.br <> Um módulo deve ser

    responsável por um, e apenas um, ator. Single Responsability Principle Princípio da Responsabilidade única S
  5. Corporativo | Interno @zupinnovation zup.com.br <> Problema 1 – Duplicação

    acidental - - calcularPagamento e quantidadeHoras compartilham de um algoritmo para calcular horas regulares de trabalho. - - Ambos usam o algoritmo regulaHoras. - - O financeiro decide que o método regulaHoras precisa ser ajustado. - - O Rh não gostaria dessa alteração, pois ele usa as horas para um propósíto diferente. - - A mudança é feita. - - O RH continua usando regulaHoras, agora com números incorretos. - - O RH fica sabendo. Problema 2 – Colisão - - a equipe de DBA determina uma mudança simples na tabela Empregado. - - A equipe do Rh pede uma mudança no regulaHoras. - - dois devs, de equipes diferentes, verificam a classe e começam fazer as mudanças. - - As mudanças colidem. - class Empregado(){ fun calcularPagamento(){} fun quantidadeHoras(){} fun save(){} //calcularPagamento - é especificada pelo contabilidade, // subordinada ao financeiro. //quantidadeHoras - é especificada pelo RH, subordinado a people. // save - É especificado pelos adms da base de dados, // subordinados ao setor técnico. }
  6. Corporativo | Interno @zupinnovation zup.com.br <> Entidades de software (classes,

    módulos, funções, etc) devem ser abertas para extensão, mas fechadas para modificação. Open Closed Princípio Aberto/Fechado O
  7. Corporativo | Interno @zupinnovation zup.com.br <> Problema – Acrescentar contas

    - - ah!!! Mas é só acrescentar um if, o que custa??? - - Custa!!! Essa classe já esta funcionando, esta testada e deve estar fechada para modificação. Solução - - - Criar uma classe abstrata do tipo DebitoConta - - Criar um numeroTransacao para retornar após efetuar o debito. - - - Um método abstrato Debitar, que mostra como fazer o debito da conta, mas que não debita. - - Com isso DebitoContaCorrente, herda debito em Conta. - - DebitoContaPoupança, herda debito em Conta. - - DebitoContaJurifica, herda debito em Conta. - Com isso, ela está aberta para extensão e fechada para modificação. Pergunta – Por que não poderia ser uma interface? - Porque não seria possível sobrescrever os métodos. - class DebitoemConta(){ fun debitar(valor: Double, conta: String, TipoContaEnum: tipoConta){} if (tipoConta == TipoContaEnum.Corrente){} //Debita conta corrente if (tipoConta == TipoConta.Poupanca){} //Valida aniversário da Conta //Debita Conta Poupança }
  8. Corporativo | Interno @zupinnovation zup.com.br <> As classes base devem

    ser substituíveis por suas classes derivadas. Liskov Substituion Princípio da Substituição de Liskov L
  9. Corporativo | Interno @zupinnovation zup.com.br <> O Exemplo do quadrado!

    - O quadrado herdar o calculo de área do retângulo, por serem iguais, não faz do quadrado um retângulo. Problema- O problema do PATO - “Se você nada como um pato, voa como um pato, porém precisa de baterias, provavelmente você possui um problema de abstração. Dica- - “As classes filhas, nunca devem infligir o comportamento da classe pai.” open class Retangulo(){ var altura = {} var largura = {} var area = {} } class Quadrado() : Retangulo(){ }
  10. Corporativo | Interno @zupinnovation zup.com.br <> Clientes não devem ser

    forçados a depender de métodos que não usam. Interface segregation principle O princípio da segregação de Interface I
  11. Corporativo | Interno @zupinnovation zup.com.br <> Depender de algo que

    contém itens desnecessários pode causar problemas inesperados! interface CadastroRepository{ fun validarDados() fun salvarBanco() fun enviarEmail() } class Cliente(private val cadastroRepository: CadastroRepository){ //validaDados //salvarBanco //enviarEmail } class Produto(private val cadastroRepository: CadastroRepository){} //validaDados //salvaBancos //enviarEmail??????
  12. Corporativo | Interno @zupinnovation zup.com.br <> - 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. Dependency Inversion Principle Princípio da inversão de dependência D
  13. Corporativo | Interno @zupinnovation zup.com.br <> Arquitetura de software estáveis

    são aquelas que evitam depender de implementações concretas, que favorecem o uso de interfaces abstratas estáveis. Conjunto de práticas - - Não se refira a classes concretas voláteis – Refira-se a interfaces abstratas. - - Não derive de classes concretas voláteis – Trata-se de um complemento a regra anterior que merece atenção especial. - - Não sobrescreva funções concretas- Funções concretas muitas vezes exigem dependências de código-fonte. Quando você faz o override dessas funções, você não elimina essas dependências (na verdade você herda). Para controlar essas dependências, converta a função em abstrata e crie múltiplas implementações. - - Nunca mencione o nome de algo que seja concreto e volátil. Essa é apenas uma reafirmação do próprio princípio. - AtualizadorCarteira ------ ConectorBolsa - AtualizadorCarteira ---- Abstração ConexaoBolsa ------- ConectorBolsa
  14. Corporativo | Interno @zupinnovation zup.com.br <> Considerações finais • Use

    os princípios como guia. Não leve tudo ao pé da letra. • Após conhecê-los, cuidado com a vontade de sair refatorando tudo. • Não tenha muito apego pelo design de código que você criou, mude caso seja necessário. • Ficou ruim para testar ??? Reavalie!
  15. Corporativo | Interno @zupinnovation zup.com.br <> Orientação a Objetos e

    SOLID para Ninjas (Projetando classes flexíveis) Use a Cabeça! Padrões de Projetos Design Patterns (Elements of Reusable Object-Oriented Sofware Indicações de leitura