Entenda os princípios S.O.L.I.D para melhorar a manutenção e escalabilidade do seu sistema

Entenda os princípios S.O.L.I.D para melhorar a manutenção e escalabilidade do seu sistema

S.O.L.I.D. são 5 princípios da orientação a objetos que visam facilitar a manutenção e tornar seu sistema altamente escalável.

Seu acrônimo define os diferentes princípios, sendo eles:

SRP – Single Responsibility Principle – Princípio de responsabilidade única

OCP – Open Closed Principle – Princípio Aberto-Fechado

LSP – Liskov Substitution Principle – Princípio de Substituição de Liskov

ISP – Interface Segregation Principle – Princípio de Segregação de Interface

DIP – Dependency Inversion Principle – Princípio de Inversão de dependência

Iremos ver os principios em uma série de 5 posts, um para cada principio.

 

Single Responsibility Principle (SRP)

O Princípio de Responsabilidade única diz:

A component should have one, and only one, reason to change.

Um componente deve ter uma, e apenas uma razão para mudar.

Antes de começarmos a falar sobre o que ele quer dizer ou como implementamos uma solução que atenda ao princípio, vamos entender o que ele quer dizer com componente e o que seria uma razão para mudar.

Um componente: Um componente pode ser identificado como uma classe, um pacote e até mesmo um módulo.

Razão para mudar: A razão para mudar pode ser identificado como possíveis problemas ou grupos de problemas que implicaria na mudança de implementação do componente.

Ok! Agora que compreendemos melhor as palavras descritas no princípio, podemos seguir com sua explicação.

Um componente deve ter apenas uma razão para mudanças, isso é, deve ter apenas uma única responsabilidade, evitando “problemas” que não dizem respeito às suas funções.

Essas características podem ser alcançadas elaborando um componente que tenha alto grau de coesão e baixo grau de acoplamento. Veremos esses dois conceitos a seguir:

 

Coesão

Coesão no mundo de software diz respeito ao grau que várias partes de um componente se relaciona. Observe a seguinte implementação:

<?php

class Quadrado {


public function calcularArea() { ... }

public function calcularPerimetro() { ... }

public function desenhar() { ... }

public function rotacionar() { ... }


}

Nesse exemplo, nosso componente é a classe Quadrado que implementa 4 (quatro) métodos (partes):

  • calcularArea: Responsável por calcular a área do quadrado;
  • calcularPerimetro: Responsável por calcular o perimetro do quadrado;
  • desenhar: Responsável desenhar o quadrado na tela; e
  • rotacionar: Responsável por rotacionar a imagem do quadrado.

Agora vamos entender qual o grau de coesão entre as partes:

Os métodos calcularArea e calcularPerimetro estão intimamente relacionados entre si, pois são métodos responsáveis por realizar os cálculos do quadrado, portanto há uma alto nível de coesão entre eles

Os métodos desenhar e rotacionar estão intimamente relacionados entre si, pois são métodos responsáveis por lidar com a exibição do quadrado, portanto há uma alto nível de coesão entre eles.

Agora, se olharmos os métodos como um todo, os métodos desenhar e rotacionar não estão intimamente relacionados com os métodos calcularArea e calcularPerimetro, pois um lado é responsável por lidar com o cálculo, enquanto o outro com a exibição.

Podemos dizer então que o grau de coesão do componente é baixo, pois nem todas suas partes são fortemente relacionadas.

Essa implementação fere, também, o próprio princípio em si, pois a classe possui mais de uma razão para mudar: Em caso de alteração na forma de calcular E em caso de alteração na forma de exibir.

Para resolver esse problema, mudaremos a implementação para a seguinte forma:

<?php

class QuadradoUI {


public function desenhar(){ ... }

public function rotacionar() { ... }


}


class Quadrado extends QuadradoUI {


public function calcularArea(){ ... }

public function calcularPerimetro(){ ... }


}

Dessa forma, a classe Quadrado possui apenas os métodos relacionados ao cálculo, que são intimamente relacionados entre si, enquanto sua classe pai possui os métodos responsáveis apenas pela exibição, que são relacionados intimamente relacionados entre si.

 

Acoplamento

Acoplamento é o nível de interdependência entre vários componentes de software. Vamos ao exemplo prático:


<?php

class Aluno {


public function salvar() {

    ...
    $query = $this->obterQuery();
    $this->conexao->exec($query);
    ...

}

public function obterIdEstudante() { ... }

public function definirIdEstudante() { ... }


}

Nesse exemplo temos um componente Aluno, com os seguintes métodos:

  • salvar: Responsável por armazenar as informações no repositório de dados
  • obterIdEstudante: Responsável por obter o id do estudante
  • definirIdEstudante: Responsável por definir o id do estudante

A classe Aluno é responsável pelas operações básicas pelo aluno e também pelas operações com a base de dados, fazendo com que tenha dependência sobre o gerenciamento do banco de dados.

Essa manipulação do repositório do aluno fere a definição de baixo acoplamento, levando em consideração a alta dependência de operações de baixo nível sobre como armazenar as informações no repositório de dados.

Fere, também, o princípio SRP em sí, uma vez que há mais de uma razão para mudar, uma referente a alterações na abstração do aluno e outra relacionada às operações da base de dados.

Para resolver isso, vamos desacoplar a dependência das operações e colocá-las em outro componente, conforme o exemplo a seguir:

<?php

class AlunoRepositorio {


public function salvar($aluno) {

    ...
    $query = $this->obterQuery();
    $this->conexao->exec($query);
    ...

}


}


class Aluno {


public function salvar() {

    $repositorio = new AlunoRepositorio();
    $repositorio->salvar($this);

}

public function obterIdEstudante() { ... }

public function definirIdEstudante() { ... }


}

Dessa forma, o componente Aluno lida apenas com as operações básicas do aluno, enquanto as operações de baixo nível ficam responsáveis apenas pela classe AlunoRepositorio.

Perceba que ambos possuem apenas uma razão para mudar: Em caso de mudança na abstração do aluno, alteramos sua classe e em caso de mudança na manipulação de seu repositório, alteramos o AlunoRepositorio.

E com isso concluimos o primeiro artigo sobre os principios do S.O.L.I.D.

Anterior Gerenciando custos e projetos com Kubernetes, Terraform e AWS
Próxima Black November 4Linux: 50% de desconto em todos os cursos para alavancar sua carreira!

About author

Você pode gostar também

DevOps

Entenda os Microsserviços: A Revolução no Desenvolvimento de Softwares

Vivemos em tempos onde a evolução das tecnologias e dos tipos de serviços com os quais estamos acostumados se transformam e mudam em uma velocidade impressionante. E isso tem sido

Desenvolvimento

Desenvolvendo uma API de transações de cartão de crédito com validações

Recentemente precisei desenvolver uma API que realizava transações de cartões de crédito passando por diversas validações, como por exemplo, se o valor solicitado pelo vendedor no momento da compra é maior

Treinamentos

Descubra o poder da programação concorrente com a linguagem Go

O mundo da tecnologia se encontra em uma constante corrida: a corrida das tecnologias,das ferramentas, das linguagens de programação. Novos problemas vão surgindo e, com eles, novas demandas, novas formas