SOLID principles: Princípios da programação orientada a objetos

Princípios SOLID (SOLID principles) são cinco postulados práticos para a escrita de códigos limpos e flexíveis na programação orientada a objetos. Eles tornam os códigos mais eficientes e facilitam a manutenção. Ao seguir esses princípios, é possível desenvolver códigos que permanecem fáceis de entender mesmo depois de longos períodos de desenvolvimento.

SOLID principles: Princípios SOLID

Todo bom código fonte deve começar com regras, paradigmas de programação e um estilo de programação adequado para que o código seja eficiente e limpo. E, exatamente para isso, foram criados os cinco princípios SOLID com base nas ideias de Robert C. Martin, Bertrand Meyer e Barbara Liskov. Ao usar linguagens como Python ou Java, quem segue esses princípios na programação orientada a objetos (OOP) escreve códigos melhores, assegura a manutenção mais eficiente em longo prazo e contribui para a sustentabilidade, flexibilidade e segurança do software.

O acrônimo SOLID designa uma base sólida de desenvolvimento para todas as pessoas que querem aprender a programar. Além disso, SOLID é um acrônimo composto pelas primeiras letras do nome em inglês de cada um dos cinco princípios (formulados por Michael Feathers). Os princípios SOLID podem ser resumidos da seguinte forma:

  • Princípio de responsabilidade única: uma classe deve ter somente uma responsabilidade (não confundir responsabilidade com tarefa) e deve haver somente um motivo para alterar a classe.
  • Princípio de aberto/fechado: as classes devem ser abertas para expansões e fechadas para alterações.
  • Princípio da substituição de Liskov: as subclasses devem poder implementar todos os métodos e propriedades das classes superiores.
  • Princípio da segregação de interfaces: as interfaces não devem ter mais métodos do que os necessários para as classes que as implementam.
  • Princípio da inversão de dependência: as classes não devem ser dependentes de outras classes, mas sim de interfaces ou classes abstratas.

Vantagens dos princípios SOLID

Quando não há regras, reina o caos – é muito fácil ver isso na programação. Mesmo os menores erros, imprecisões e omissões podem tornar um bom código fonte completamente inútil em longo prazo. Basta que o código tenha classes complexas que dificultem a implementação ou subclasses com propriedades individuais que a classe superior não tenha. Para evitar esses problemas e muitos outros, os princípios SOLID visam garantir que um código precise do mínimo possível de mudanças em refatoração.

Benefícios de se adotar os princípios SOLID em códigos:

  • Código claro, limpo e fácil de entender: ao programar seguindo os princípios, os softwares e códigos ficam mais compreensíveis, eficientes e bem escritos.
  • Facilidade de manutenção: com uma estrutura fácil de entender e clara, a manutenção de códigos novos e antigos fica muito mais simples, mesmo se for realizada por várias pessoas.
  • Adaptação, expansão, reutilização: como o código é mais fácil de ler, menos complexo, tem menos responsabilidades e menor dependência de classes, é mais fácil editar, fazer adaptações, expansões por meio de interfaces e reutilizá-lo de maneira flexível.
  • Menor probabilidade de erros: em um código limpo e com estrutura simples, as alterações feitas em uma determinada área não terão efeitos indesejados em outras áreas ou funções.
  • Mais segurança e confiabilidade: com a redução ou a eliminação de pontos fracos, incompatibilidades e erros, é possível aumentar a funcionalidade, a confiabilidade e, consequentemente, também a segurança dos sistemas.

Princípios SOLID em detalhes

Os princípios SOLID são regras de ouro para uma boa programação. Portanto, todos que trabalham com programação orientada a objetos devem estar bem familiarizados com eles. Veja a seguir uma apresentação detalhada de todos os cinco princípios.

SRP: Single Responsibility Principle (Princípio de responsabilidade única)

A definição original conforme Robert C. Martin em seu livro “Agile Software Development: Principles, Patterns and Practices” pode ser traduzida da seguinte forma:

Citação

“Nunca deve haver mais de um motivo para alterar uma classe.”

O SRP afirma que cada classe na programação orientada a objetos deve ter somente uma única responsabilidade. Assim, só deve haver um único motivo para alterar a classe. Para evitar mal-entendidos, uma distinção importante deve ser feita: o princípio não defende que cada classe ou cada módulo deva ter somente uma tarefa, mas sim que cada classe tenha uma única responsabilidade na execução de uma tarefa específica, evitando ao máximo sobreposições com outras áreas.

Uma sobreposição de responsabilidades ocorre, por exemplo, ao disponibilizar várias funções para diferentes áreas comerciais. Caso seja preciso alterar uma dessas áreas, as alterações terão efeitos nas funcionalidades da classe de maneira geral. A atribuição de mais de uma responsabilidade e várias dependências fazem com que a alteração em uma área do código requeira que várias outras alterações sejam feitas ou pode gerar erros.

Assim, o SRP tem como objetivo o desenvolvimento de módulos coerentes, responsáveis por tarefas ou objetos bem definidos. Com um formato claramente estruturado, com o mínimo possível de dependências e com implementações independentes, quaisquer alterações e modulações futuras poderão ser executadas de maneira mais simples e rápida.

Nota

As classes, também conhecidas como tipos de objetos, constituem o elemento central da programação orientada a objetos (OOP). Elas podem ser compreendidas como o plano de construção com atributos para criar objetos reais, semelhantes ou em construção nos softwares. Algumas vezes também chamadas de módulos, as classes frequentemente são comparadas a tipos de arquivos.

OCP: Open Closed Principle (Princípio de aberto/fechado)

No livro “Object Oriented Software Construction”, Bertrand Meyer e Robert C. Martin definem o OCP como:

Citação

“Entidades de software (classes, módulos, funções, etc.) devem ser, ao mesmo tempo, abertas para expansões e fechadas para modificações.”

O OCP tem como objetivo garantir que não seja necessário reescrever as partes principais de um software para implementar alterações. A realização de modulações profundas no código traz o risco de gerar erros difíceis de identificar ou code smell, ou seja: características que indicam problemas complexos no código. Um código bem-estruturado deve poder integrar interfaces para ser expandido com funções adicionais conforme o conceito essencial de herança de classes.

Novos recursos e expansões a serem implementados podem ser incorporados em uma classe superior na forma de subclasses, usando uma interface. Isso faz com que novas funções e métodos sejam mais fáceis de visualizar. Assim, nunca será preciso fazer gambiarras em um código já escrito e estável. Esse princípio facilita a manutenção e as alterações em programas, além de gerar elementos de código estáveis, reutilizáveis e muito mais eficientes devido às interfaces.

LSP: Liskov Substitution Principle (Princípio da substituição de Liskov)

Em seu livro “Behavioral Subtyping Using Invariants and Constraints”, Barbara H. Liskov e Jeannette M. Wing definem o LSP como:

Citação

“Se q(x) for uma propriedade do objeto x do tipo T, então q(y) deve ser válida para todos os objetos do tipo S, sendo S um subtipo de T.”

Apesar da definição parecer um problema de matemática, o princípio é bem fácil de entender: subclasses vinculadas ou expandidas devem funcionar como suas classes superiores. Isso significa que toda subclasse deve herdar suas propriedades das respectivas classes superiores e essas propriedades não devem precisar ser alteradas para valer para as subclasses. Por princípio, deve ser possível substituir a classe base por uma subclasse – daí o nome princípio da substituição. Ao contrário das subclasses, as classes superiores devem ser modificadas pelas alterações.

O clássico exemplo do retângulo e do quadrado de Robert C. Martin explica bem esse princípio. Nas aulas de geometria aprendemos que todo quadrado é um retângulo, mas nem todo retângulo é um quadrado. Um quadrado compartilha a propriedade “ângulos retos” com sua classe superior “Retângulo”, mas têm adicionalmente a propriedade “lados iguais”.

Na programação, as coisas funcionam de outro jeito: estabelecer referências ou dependências entre classes parecidas ou aparentemente idênticas leva a erros, mal-entendidos e um código complicado. Por isso, na programação, “Retângulo” não deve ser uma classe superior para a classe “Quadrado”. Ambas as classes devem ser desvinculadas e implementadas independentemente. Se as classes forem integradas separadamente, não poderão ocorrer mal-entendidos que causem erros afetando a classe de maneira geral. Isso aumenta a segurança e a estabilidade ao mudar implementações em subclasses e classes superiores, sem causar efeitos indesejados no código.

ISP: Interface Segregation Principle (Princípio da segregação da interface)

O ISP é definido por Robert C. Martin no livro “The Interface Segregation Principle” como:

Citação

“Clientes não devem ser obrigados a ser dependentes de interfaces que não usam.”

O ISP afirma que os usuários não devem ser obrigados a usar interfaces que não precisam. Em outras palavras: para disponibilizar aos clientes as funções de determinadas classes, devem ser criadas novas interfaces menores adaptadas aos requisitos concretos. Assim, é possível evitar que as interfaces fiquem grandes demais e sejam geradas dependências excessivas entre as classes. Outra vantagem: é mais fácil fazer a manutenção de softwares com classes desvinculadas e diversas interfaces menores adaptadas aos requisitos concretos.

DIP: Dependency Inversion Principle (Princípio da inversão de dependências)

O quinto e último princípio SOLID foi definido por Robert C. Martin em seu livro “The Dependency Inversion Principle” e pode ser traduzido da seguinte forma:

Citação

“A. Os módulos de níveis mais altos não devem ser dependentes de módulos de níveis mais baixos. Ambos devem ser dependentes de abstrações. B. As abstrações não devem ser dependentes de detalhes. Os detalhes devem ser dependentes das abstrações.”

O DIP assegura que as dependências e as funções concretas de diferentes níveis do código fonte não sejam baseadas umas nas outras ou em interfaces abstratas. Explicando: as arquiteturas de software fazem uma distinção geral entre níveis mais altos (de usuário) e níveis profundos (mais abstratos). Pela lógica, assumimos que a base abstrata deve determinar o comportamento dos níveis mais altos. Mas o DIP indica que assumir isso pode causar erros, pois isso faz com que os níveis mais altos sejam dependentes dos níveis profundos.

Ao invés de vincular níveis mais altos aos níveis profundos, tanto as classes de níveis mais altos quanto as de níveis profundos devem ser dependentes de interfaces abstratas encaixadas entre os níveis. As interfaces devem chamar e disponibilizar as funcionalidades dos níveis profundos que forem necessárias nos níveis mais altos. Dessa forma, é possível evitar uma hierarquia de baixo para cima nas dependências, o que pode causar erros no código. Isso facilita o reaproveitamento de módulos e permite alterar classes inferiores sem afetar as classes superiores.

Hospedagem web com consultor pessoal

Rápido e escalável, confie na hospedagem da IONOS, que inclui domínio grátis no primeiro ano e endereço de e-mail!

  • Domínio
  • SSL Wildcard
  • Suporte 24 horas

Por que usar princípios SOLID?

O objetivo de todo desenvolvedor de software deve ser escrever um código limpo e compreensível para facilitar ao máximo a leitura e a manutenção. Se regras como os princípios SOLID forem ignoradas, a qualidade do código piora ao longo do tempo devido ao acúmulo de pontos fracos, redundâncias, erros e dependências. Na pior das hipóteses, o código pode até se tornar inútil. Isso é um grande problema principalmente no desenvolvimento de software ágil, pois muitas pessoas diferentes trabalham em um mesmo código complexo.

Algumas das principais consequências de um código mal escrito ou de uma manutenção ruim nos códigos são:

  • Code smell: os pontos fracos acumulados ao longo do tempo em um código mal escrito são conhecidos como code smell. Esses pontos fracos levam a erros de funções e programas incompatíveis.
  • Code rot: sem uma boa manutenção por refatoração ou uma dispendiosa revisão de código, um código pode “apodrecer”, perdendo completamente sua funcionalidade. Outro termo frequentemente usado para se referir a um código ilegível e confuso é código espaguete.
  • Falhas de segurança: além de erros, complexidade de manutenção e incompatibilidades, os códigos mal escritos abrem brechas para softwares maliciosos, como a vulnerabilidade de dia zero.

Quem desenvolveu os princípios SOLID?

Os princípios SOLID foram desenvolvidos a partir de diversos princípios definidos por Robert C. Martin (também chamado de Uncle Bob), um dos criadores da programação ágil, em seu artigo “Design Principles and Design Patterns” publicado em 2000. O conjunto de SOLID principles é resultado do trabalho de Robert C. Martin, Bertrand Meyer e Barbara Liskov. O acrônimo SOLID, amplamente utilizado hoje em dia, é composto pelas cinco primeiras letras dos princípios formulados por Michael Feathers em uma reorganização das ideias principais.

Princípios semelhantes na programação

No desenvolvimento de software há outros princípios que funcionam como recomendações de práticas, diretrizes mais gerais ou concretas. Assim como os princípios SOLID, que constituem um conjunto de orientações para o paradigma da programação orientada a objetos, outros princípios de programação para códigos limpos são:

  • Princípio DRY (Don’t repeat yourself) para que as funções sejam apresentadas de forma única e inequívoca.
  • Princípio KISS (Keep it simple, stupid) para que os códigos sejam construídos da forma mais simples possível.
Este artigo foi útil?
Para melhorar a sua experiência, este site usa cookies. Ao acessar o nosso site, você concorda com nosso uso de cookies. Mais informações
Page top