Article image
Diogo Barbosa
Diogo Barbosa07/03/2023 20:20
Compartilhe

Código Limpo, SOLID e Boas Práticas - Pilares da Programação Orientada a Objeto

  • #Desperte o potencial
  • #Boas práticas

Boa noite pessoal, essas são algumas das informações adquiridas na mentoria do dia 07 de Março, realizada pela Monique Trevisan, engenheira de software IOS do Banco PAN.

Fazendo um adendo, as informações dessa mentoria foram bastante técnicas. Pesquisem sobre e também anotem para lembrarem desses conceitos tão importantes. Vamos lá?

Código Limpo

Livro escrito pelo Robert Cecil Martin que destaca a importância de elaborar um código limpo desde o princípio do seu desenvolvimento. Um código deve ser fácil de ler, entender e manter pois isso se torna primordial para a colaboração entre os desenvolvedores, permitindo sua fácil manutenção e modificação.

Conceitos bases

Alguns dos conceitos bases da criação de um código limpo são:

  • Legibilidade - Ser fácil de ler e entender, com nomes definidos e descritivos, mesmo que isso aumente os nomes das variáveis nomeadas.
  • Padrões - Definir e seguir padrões de desenvolvimento. Podem ser pré-definidos, mas é mais indicado que cada time tenham os seus. Isso possibilita uma comunicação mais ampla e maior entendimento do código entre todos da equipe.
  • Separar configurações de código fonte - Evitar deixar arquivos de configuração no meio do código, além de uma questão de segurança, ajuda a manter a organização, evitando confusão e facilitando no momento de fazer alterações, sem que precise alterar o código em si.
  • Evitar repetições - Se algo já foi feito em algum momento, deve ser reutilizado e não copiado. Isso ajuda a agilizar o desenvolvimento.
  • Cuidado com comentários - O código se modifica com o passar do tempo, então comentários podem se tornar desatualizados. Evitar de fazer comentários desnecessários (salvos os de importância significativa) diminui a chance de erros futuros.
  • Tratamento de erros - Erros inesperados impactam o cliente, a usabilidade e o funcionamento do sistema. Entender que erros podem acontecer e tratá-los antes que se tornem um problema é indispensável para evitar desconforto na usabilidade do software.
  • Desenvolver testes limpos - Como são executados repetidamente, precisam ser ágeis. Não podem impactar o sistema inteiro como um efeito cascata, sendo totalmente independentes. Precisam ser passíveis de validação, retornando respostas verdadeiras e falsas. Precisam ser pontuais, devendo avaliar apenas um fluxo de código, um teste com muita responsabilidade também não é um bom teste.

SOLID

O solid é um acrônomo baseado nos 5 princípios da Programação Orientada a Objeto (POO), sendo eles:

Single responsibility principle (Princípio da responsabilidade única) - "Uma classe deve ter um, e somente um motivo, para mudar."

Uma classe pode ter vários métodos, porém ela deve ter apenas uma responsabilidade própria. Ao criar uma classe para salvar notas fiscais por exemplo, ela não poderá ser usada para outra coisa.

Seus benefícios envolvem:

  • Facilidade de manutenção
  • Código limpo e de fácil entendimento
  • Facilidade de desenvolvimento de testes
  • Redução de acoplamento
  • Complexidade reduzida

Open closed principle (Princípio do aberto e fechado) - "Você deve ser capaz de estender o comportamento de uma classe sem precisar modificá-la."

A partir do momento que eu tenho uma classe definida e em produção, quanto menos modificações ela receber, menor a chance do código sofrer algum tipo de erro.

Você não deveria precisar modificar uma classe para cada novo comportamento que ela precise ter, não altere algo que está pronto e funcionando bem.

Liskov substitution principle (Princípio da substituição de Liskov) - "As classes derivadas devem poder ser substituídas por sua classe base."

A frase em si não se auto explica tão bem, então vou dar um exemplo. Suponha que você crie uma classe chamada usuário que contenha informações como rg, cpf etc. Então você cria outra classe chamada funcionário que também utiliza rg, cpf etc. Não é interessante repetir as mesmas informações, nesse caso seria correto que a classe funcionário herdasse de usuário.

Esse seria o conceito de herança, onde temos uma classe pai que possui determinados atributos e uma classe filha, que herda esses mesmos atributos da classe pai e pode ter outros atributos próprios.

Ao definir que uma classe será herdada por outra sempre pense nesses pontos de atenção:

  • Todas as implementações do método da classe pai fazem sentido para a classe filho?
  • As condições de entrada dos métodos da classe filho se encaixam com a classe pai?
  • E as condições de saída?
  • Nós não podemos garantir que a classe ou método que usará nosso código irá tratar possíveis erros ou exceções. É importante observar possíveis futuros erros.

Interface segregation principle (Princípio da segregação de interfaces) - "Crie interfaces granulares e específicas para seus clientes."

Clientes não devem ser forçados a depender de interfaces que eles não usam. Da mesma forma, uma classe herdar atributos que para ela são inúteis vai contra o método solid.

Digamos que eu crie uma classe telefone e adicione: Tocar(), Discar() e TirarFoto(). Nesse caso, TirarFoto() não serviria, por exemplo, para um telefone comum fixo.

image

Imagem de exemplo utilizada na mentoria*

O correto seria dividir nossa interface em duas e implementar somente o que faz sentido para cada uma, adicionando seus atributos próprios.

image

Imagem de exemplo utilizada na mentoria*

Dependency inversion principle (Princípio da inversão de dependências) - "Dependa de abstrações e não de implementações."

Em outras palavras, os módulos que são classes superiores devem depender de abstrações independente de como funcionam pois mudam menos e facilitam as mudanças de comportamento e as evoluções de código.

Digamos que eu tenha uma classe ventilador que use outra classe interruptor. Dentro de um projeto, posso ter mais dispositivos que usam a classe interruptor e que podem estar em outros módulos do projeto. Então quanto mais dependências eu criar, mais complexo ficará o meu código.

image

Imagem de exemplo utilizada na mentoria*

Nesse exemplo, a classe interruptor não fica completamente dependente de nenhum dos dispositivos que podem utilizá-la.

Livros de referência sugeridos pela mentora

  • Código limpo
  • Agile Software Development
  • Arquitetura Limpa
  • Domain-Driven Design

Obrigado por lerem, boa sorte e sucesso a todos.

Compartilhe
Comentários (0)