Prin­cí­pios SOLID (SOLID prin­ci­ples) são cinco pos­tu­la­dos práticos para a escrita de códigos limpos e flexíveis na pro­gra­ma­ção orientada a objetos. Eles tornam os códigos mais efi­ci­en­tes e facilitam a ma­nu­ten­ção. Ao seguir esses prin­cí­pios, é possível de­sen­vol­ver códigos que per­ma­ne­cem fáceis de entender mesmo depois de longos períodos de de­sen­vol­vi­mento.

SOLID prin­ci­ples: Prin­cí­pios SOLID

Todo bom código fonte deve começar com regras, pa­ra­dig­mas de pro­gra­ma­ção e um estilo de pro­gra­ma­ção adequado para que o código seja eficiente e limpo. E, exa­ta­mente para isso, foram criados os cinco prin­cí­pios SOLID com base nas ideias de Robert C. Martin, Bertrand Meyer e Barbara Liskov. Ao usar lin­gua­gens como Python ou Java, quem segue esses prin­cí­pios na pro­gra­ma­ção orientada a objetos (OOP) escreve códigos melhores, assegura a ma­nu­ten­ção mais eficiente em longo prazo e contribui para a sus­ten­ta­bi­li­dade, fle­xi­bi­li­dade e segurança do software.

O acrônimo SOLID designa uma base sólida de de­sen­vol­vi­mento 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 prin­cí­pios (for­mu­la­dos por Michael Feathers). Os prin­cí­pios SOLID podem ser resumidos da seguinte forma:

  • Princípio de res­pon­sa­bi­li­dade única: uma classe deve ter somente uma res­pon­sa­bi­li­dade (não confundir res­pon­sa­bi­li­dade 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 al­te­ra­ções.
  • Princípio da subs­ti­tui­ção de Liskov: as sub­clas­ses devem poder im­ple­men­tar todos os métodos e pro­pri­e­da­des das classes su­pe­ri­o­res.
  • Princípio da se­gre­ga­ção de in­ter­fa­ces: as in­ter­fa­ces não devem ter mais métodos do que os ne­ces­sá­rios para as classes que as im­ple­men­tam.
  • Princípio da inversão de de­pen­dên­cia: as classes não devem ser de­pen­den­tes de outras classes, mas sim de in­ter­fa­ces ou classes abstratas.

Vantagens dos prin­cí­pios SOLID

Quando não há regras, reina o caos – é muito fácil ver isso na pro­gra­ma­ção. Mesmo os menores erros, im­pre­ci­sões e omissões podem tornar um bom código fonte com­ple­ta­mente inútil em longo prazo. Basta que o código tenha classes complexas que di­fi­cul­tem a im­ple­men­ta­ção ou sub­clas­ses com pro­pri­e­da­des in­di­vi­du­ais que a classe superior não tenha. Para evitar esses problemas e muitos outros, os prin­cí­pios SOLID visam garantir que um código precise do mínimo possível de mudanças em re­fa­to­ra­ção.

Be­ne­fí­cios de se adotar os prin­cí­pios SOLID em códigos:

  • Código claro, limpo e fácil de entender: ao programar seguindo os prin­cí­pios, os softwares e códigos ficam mais com­pre­en­sí­veis, efi­ci­en­tes e bem escritos.
  • Fa­ci­li­dade de ma­nu­ten­ção: com uma estrutura fácil de entender e clara, a ma­nu­ten­ção de códigos novos e antigos fica muito mais simples, mesmo se for realizada por várias pessoas.
  • Adaptação, expansão, reu­ti­li­za­ção: como o código é mais fácil de ler, menos complexo, tem menos res­pon­sa­bi­li­da­des e menor de­pen­dên­cia de classes, é mais fácil editar, fazer adap­ta­ções, expansões por meio de in­ter­fa­ces e reutilizá-lo de maneira flexível.
  • Menor pro­ba­bi­li­dade de erros: em um código limpo e com estrutura simples, as al­te­ra­ções feitas em uma de­ter­mi­nada área não terão efeitos in­de­se­ja­dos em outras áreas ou funções.
  • Mais segurança e con­fi­a­bi­li­dade: com a redução ou a eli­mi­na­ção de pontos fracos, in­com­pa­ti­bi­li­da­des e erros, é possível aumentar a fun­ci­o­na­li­dade, a con­fi­a­bi­li­dade e, con­se­quen­te­mente, também a segurança dos sistemas.

Prin­cí­pios SOLID em detalhes

Os prin­cí­pios SOLID são regras de ouro para uma boa pro­gra­ma­ção. Portanto, todos que trabalham com pro­gra­ma­ção orientada a objetos devem estar bem fa­mi­li­a­ri­za­dos com eles. Veja a seguir uma apre­sen­ta­ção detalhada de todos os cinco prin­cí­pios.

SRP: Single Res­pon­si­bi­lity Principle (Princípio de res­pon­sa­bi­li­dade única)

A definição original conforme Robert C. Martin em seu livro “Agile Software De­ve­lop­ment: Prin­ci­ples, 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 pro­gra­ma­ção orientada a objetos deve ter somente uma única res­pon­sa­bi­li­dade. Assim, só deve haver um único motivo para alterar a classe. Para evitar mal-en­ten­di­dos, uma distinção im­por­tante 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 res­pon­sa­bi­li­dade na execução de uma tarefa es­pe­cí­fica, evitando ao máximo so­bre­po­si­ções com outras áreas.

Uma so­bre­po­si­ção de res­pon­sa­bi­li­da­des ocorre, por exemplo, ao dis­po­ni­bi­li­zar várias funções para di­fe­ren­tes áreas co­mer­ci­ais. Caso seja preciso alterar uma dessas áreas, as al­te­ra­ções terão efeitos nas fun­ci­o­na­li­da­des da classe de maneira geral. A atri­bui­ção de mais de uma res­pon­sa­bi­li­dade e várias de­pen­dên­cias fazem com que a alteração em uma área do código requeira que várias outras al­te­ra­ções sejam feitas ou pode gerar erros.

Assim, o SRP tem como objetivo o de­sen­vol­vi­mento de módulos coerentes, res­pon­sá­veis por tarefas ou objetos bem definidos. Com um formato cla­ra­mente es­tru­tu­rado, com o mínimo possível de de­pen­dên­cias e com im­ple­men­ta­ções in­de­pen­den­tes, quaisquer al­te­ra­ções e mo­du­la­ções futuras poderão ser exe­cu­ta­das de maneira mais simples e rápida.

Nota

As classes, também co­nhe­ci­das como tipos de objetos, cons­ti­tuem o elemento central da pro­gra­ma­ção orientada a objetos (OOP). Elas podem ser com­pre­en­di­das como o plano de cons­tru­ção com atributos para criar objetos reais, se­me­lhan­tes ou em cons­tru­ção nos softwares. Algumas vezes também chamadas de módulos, as classes fre­quen­te­mente são com­pa­ra­das a tipos de arquivos.

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

No livro “Object Oriented Software Cons­truc­tion”, 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 mo­di­fi­ca­ções.”

O OCP tem como objetivo garantir que não seja ne­ces­sá­rio re­es­cre­ver as partes prin­ci­pais de um software para im­ple­men­tar al­te­ra­ções. A re­a­li­za­ção de mo­du­la­ções profundas no código traz o risco de gerar erros difíceis de iden­ti­fi­car ou code smell, ou seja: ca­rac­te­rís­ti­cas que indicam problemas complexos no código. Um código bem-es­tru­tu­rado deve poder integrar in­ter­fa­ces para ser expandido com funções adi­ci­o­nais conforme o conceito essencial de herança de classes.

Novos recursos e expansões a serem im­ple­men­ta­dos podem ser in­cor­po­ra­dos em uma classe superior na forma de sub­clas­ses, usando uma interface. Isso faz com que novas funções e métodos sejam mais fáceis de vi­su­a­li­zar. Assim, nunca será preciso fazer gam­bi­ar­ras em um código já escrito e estável. Esse princípio facilita a ma­nu­ten­ção e as al­te­ra­ções em programas, além de gerar elementos de código estáveis, reu­ti­li­zá­veis e muito mais efi­ci­en­tes devido às in­ter­fa­ces.

LSP: Liskov Subs­ti­tu­tion Principle (Princípio da subs­ti­tui­ção de Liskov)

Em seu livro “Beha­vi­o­ral Subtyping Using In­va­ri­ants and Cons­traints”, Barbara H. Liskov e Jeannette M. Wing definem o LSP como:

Citação

“Se q(x) for uma pro­pri­e­dade 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 ma­te­má­tica, o princípio é bem fácil de entender: sub­clas­ses vin­cu­la­das ou ex­pan­di­das devem funcionar como suas classes su­pe­ri­o­res. Isso significa que toda subclasse deve herdar suas pro­pri­e­da­des das res­pec­ti­vas classes su­pe­ri­o­res e essas pro­pri­e­da­des não devem precisar ser alteradas para valer para as sub­clas­ses. Por princípio, deve ser possível subs­ti­tuir a classe base por uma subclasse – daí o nome princípio da subs­ti­tui­ção. Ao contrário das sub­clas­ses, as classes su­pe­ri­o­res devem ser mo­di­fi­ca­das pelas al­te­ra­ções.

O clássico exemplo do retângulo e do quadrado de Robert C. Martin explica bem esse princípio. Nas aulas de geometria apren­de­mos que todo quadrado é um retângulo, mas nem todo retângulo é um quadrado. Um quadrado com­par­ti­lha a pro­pri­e­dade “ângulos retos” com sua classe superior “Retângulo”, mas têm adi­ci­o­nal­mente a pro­pri­e­dade “lados iguais”.

Na pro­gra­ma­ção, as coisas funcionam de outro jeito: es­ta­be­le­cer re­fe­rên­cias ou de­pen­dên­cias entre classes parecidas ou apa­ren­te­mente idênticas leva a erros, mal-en­ten­di­dos e um código com­pli­cado. Por isso, na pro­gra­ma­ção, “Retângulo” não deve ser uma classe superior para a classe “Quadrado”. Ambas as classes devem ser des­vin­cu­la­das e im­ple­men­ta­das in­de­pen­den­te­mente. Se as classes forem in­te­gra­das se­pa­ra­da­mente, não poderão ocorrer mal-en­ten­di­dos que causem erros afetando a classe de maneira geral. Isso aumenta a segurança e a es­ta­bi­li­dade ao mudar im­ple­men­ta­ções em sub­clas­ses e classes su­pe­ri­o­res, sem causar efeitos in­de­se­ja­dos no código.

ISP: Interface Se­gre­ga­tion Principle (Princípio da se­gre­ga­ção da interface)

O ISP é definido por Robert C. Martin no livro “The Interface Se­gre­ga­tion Principle” como:

Citação

“Clientes não devem ser obrigados a ser de­pen­den­tes de in­ter­fa­ces que não usam.”

O ISP afirma que os usuários não devem ser obrigados a usar in­ter­fa­ces que não precisam. Em outras palavras: para dis­po­ni­bi­li­zar aos clientes as funções de de­ter­mi­na­das classes, devem ser criadas novas in­ter­fa­ces menores adaptadas aos re­qui­si­tos concretos. Assim, é possível evitar que as in­ter­fa­ces fiquem grandes demais e sejam geradas de­pen­dên­cias ex­ces­si­vas entre as classes. Outra vantagem: é mais fácil fazer a ma­nu­ten­ção de softwares com classes des­vin­cu­la­das e diversas in­ter­fa­ces menores adaptadas aos re­qui­si­tos concretos.

DIP: De­pen­dency Inversion Principle (Princípio da inversão de de­pen­dên­cias)

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

Citação

“A. Os módulos de níveis mais altos não devem ser de­pen­den­tes de módulos de níveis mais baixos. Ambos devem ser de­pen­den­tes de abs­tra­ções. B. As abs­tra­ções não devem ser de­pen­den­tes de detalhes. Os detalhes devem ser de­pen­den­tes das abs­tra­ções.”

O DIP assegura que as de­pen­dên­cias e as funções concretas de di­fe­ren­tes níveis do código fonte não sejam baseadas umas nas outras ou em in­ter­fa­ces abstratas. Ex­pli­cando: as ar­qui­te­tu­ras 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 de­ter­mi­nar o com­por­ta­mento 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 de­pen­den­tes 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 de­pen­den­tes de in­ter­fa­ces abstratas en­cai­xa­das entre os níveis. As in­ter­fa­ces devem chamar e dis­po­ni­bi­li­zar as fun­ci­o­na­li­da­des dos níveis profundos que forem ne­ces­sá­rias nos níveis mais altos. Dessa forma, é possível evitar uma hi­e­rar­quia de baixo para cima nas de­pen­dên­cias, o que pode causar erros no código. Isso facilita o re­a­pro­vei­ta­mento de módulos e permite alterar classes in­fe­ri­o­res sem afetar as classes su­pe­ri­o­res.

Hos­pe­da­gem que se adapta às suas ambições
  • Fique online com 99,99% de tempo de atividade e segurança robusta
  • Aumente o de­sem­pe­nho com um clique à medida que o tráfego cresce
  • Inclui domínio gratuito, SSL, e-mail e suporte 24 horas por dia, 7 dias por semana

Por que usar prin­cí­pios SOLID?

O objetivo de todo de­sen­vol­ve­dor de software deve ser escrever um código limpo e com­pre­en­sí­vel para facilitar ao máximo a leitura e a ma­nu­ten­ção. Se regras como os prin­cí­pios SOLID forem ignoradas, a qualidade do código piora ao longo do tempo devido ao acúmulo de pontos fracos, re­dun­dân­cias, erros e de­pen­dên­cias. Na pior das hipóteses, o código pode até se tornar inútil. Isso é um grande problema prin­ci­pal­mente no de­sen­vol­vi­mento de software ágil, pois muitas pessoas di­fe­ren­tes trabalham em um mesmo código complexo.

Algumas das prin­ci­pais con­sequên­cias de um código mal escrito ou de uma ma­nu­ten­ção ruim nos códigos são:

  • Code smell: os pontos fracos acu­mu­la­dos ao longo do tempo em um código mal escrito são co­nhe­ci­dos como code smell. Esses pontos fracos levam a erros de funções e programas in­com­pa­tí­veis.
  • Code rot: sem uma boa ma­nu­ten­ção por re­fa­to­ra­ção ou uma dis­pen­di­osa revisão de código, um código pode “apodrecer”, perdendo com­ple­ta­mente sua fun­ci­o­na­li­dade. Outro termo fre­quen­te­mente usado para se referir a um código ilegível e confuso é código espaguete.
  • Falhas de segurança: além de erros, com­ple­xi­dade de ma­nu­ten­ção e in­com­pa­ti­bi­li­da­des, os códigos mal escritos abrem brechas para softwares ma­li­ci­o­sos, como a vul­ne­ra­bi­li­dade de dia zero.

Quem de­sen­vol­veu os prin­cí­pios SOLID?

Os prin­cí­pios SOLID foram de­sen­vol­vi­dos a partir de diversos prin­cí­pios definidos por Robert C. Martin (também chamado de Uncle Bob), um dos criadores da pro­gra­ma­ção ágil, em seu artigo “Design Prin­ci­ples and Design Patterns” publicado em 2000. O conjunto de SOLID prin­ci­ples é resultado do trabalho de Robert C. Martin, Bertrand Meyer e Barbara Liskov. O acrônimo SOLID, am­pla­mente utilizado hoje em dia, é composto pelas cinco primeiras letras dos prin­cí­pios for­mu­la­dos por Michael Feathers em uma re­or­ga­ni­za­ção das ideias prin­ci­pais.

Prin­cí­pios se­me­lhan­tes na pro­gra­ma­ção

No de­sen­vol­vi­mento de software há outros prin­cí­pios que funcionam como re­co­men­da­ções de práticas, di­re­tri­zes mais gerais ou concretas. Assim como os prin­cí­pios SOLID, que cons­ti­tuem um conjunto de ori­en­ta­ções para o paradigma da pro­gra­ma­ção orientada a objetos, outros prin­cí­pios de pro­gra­ma­ção para códigos limpos são:

  • Princípio DRY (Don’t repeat yourself) para que as funções sejam apre­sen­ta­das de forma única e inequí­voca.
  • Princípio KISS (Keep it simple, stupid) para que os códigos sejam cons­truí­dos da forma mais simples possível.
Ir para o menu principal