Polimorfismo em Componentes Web — Uma maneira errada de escrever componentes

Sidnei Junior Anastácio
Mercafacil
Published in
7 min readSep 29, 2022

Quem nunca foi dar manutenção em algum componente e ficou perdido por causa da quantidade de ifs que ele tinha? Muitas vezes o componente possui muitas propriedades de entrada (props) e tantas condições que dificultam saber se o componente é um caminhão ou o Optimus Prime. Partindo desse princípio, vou explicar como escrever componentes web, tornando-os reutilizáveis sem que isso dificulte sua manutenção e a escalabilidade da aplicação.

O que são componentes web?

Um componente é um bloco de código isolado de responsabilidade única que pode ser reutilizado em várias partes de uma aplicação web. Pense em um formulário qualquer, com um campo de e-mail e um campo de senha. Cada um desses campos responderá à entrada do usuário e exibirá o que está sendo digitado sem que haja interferência no campo seguinte. Esses campos de textos podem ser componentes, que serão utilizados para ambos os casos. O comportamento desses componentes é ser um campo de texto que exibe o que o usuário digita, mas a forma como o texto é exibido será diferente para o e-mail e para a senha, já que geralmente os campos de senha possuem asteriscos (*) no lugar de cada caractere.

Exemplo de formulário com campo de usuário e senha

Quando usar componentes web?

  1. Quando sabe-se que um trecho de código será reutilizado em diversos lugares da sua aplicação, e o comportamento será o mesmo para todos esses lugares;
  2. Quando se quer compartilhar estilos visuais previamente definidos na aplicação;
  3. Para separar as responsabilidades, isolando funcionalidades do código em componentes;
  4. Para diminuir a complexidade do código, tornando-o mais fácil de dar manutenção e escalar.

Como funcionam os múltiplos comportamentos de um componente web?

Um dos superpoderes de um componente é adaptar as características de acordo com seu uso, como por exemplo: na página X o componente possui a cor laranja, na página Y a cor dele é azul, assim podemos reutilizar o mesmo código e enviar propriedades como a cor para que ele apresente características diferentes. No entanto, todo super herói com superpoderes possui fraquezas, e com os componentes a história se repete.

A principal fraqueza de um componente é adotar múltiplos comportamentos, por exemplo, assumindo um comportamento diferente dependendo de onde ele é utilizado. Na maioria das vezes isso acontece porque o componente não foi bem definido na sua concepção, ou quando ele é mudado conforme a aplicação cresce.

Podemos emprestar o termo polimorfismo da programação orientada a objetos aqui e associá-lo aos componentes com múltiplos comportamentos, já que polimorfismo significa múltiplas formas. Para os objetos, é legal definir múltiplos comportamentos e fazer com que eles se adaptem a diferentes usos, já para os componentes web isso não é tão benéfico, pois, podemos criar uma dependência grande de um código fora desse componente, a manutenção pode ficar muito difícil e podemos gastar horas tentando entender como ele funciona. O custo será de horas de manutenção por uma reutilização de código ineficiente.

Antes de começar a escrever um componente web, devemos nos fazer algumas perguntas, como:

  • Qual a principal funcionalidade deste componente?
  • Essa funcionalidade vai ser alterada a cada uso?
  • Caso minha aplicação cresça ou algum requisito dela mude, como meu componente vai se comportar?

Se mais de uma resposta para essas perguntas não estão claras, talvez o seu componente esteja assumindo múltiplos comportamentos.

Uma maneira errada de escrever um componente web

Pense em duas tabelas que possuam algumas colunas, a primeira tabela possui informações do cliente e a segunda tabela possui informações de lojas, ambas tabelas possuem nome. Podemos criar um componente de tabela genérico que vai ser reutilizado tanto para o cliente quanto para a loja, já que o comportamento de exibir essas colunas com os cabeçalhos em negrito por exemplo, é comum para as duas tabelas. Mas a única coluna comum para essas tabelas é o nome, o restante das colunas são diferentes. É possível exibir ou esconder as colunas para cada tabela usando as estruturas condicionais (if), mas se essa for a solução adotada então esse componente possui dois comportamentos diferentes: um quando o valor do if é verdadeiro, e outro quando é falso. Olhe os códigos abaixo:

Exemplo 1 de um componente confuso

Olhando o exemplo acima, conseguimos ver como é difícil definir o que esse componente faz sem analisar detalhadamente seu código. Se você estiver trabalhando com Typescript vamos ter mais um problema: o objeto dados fica sem definição de tipo, pois ele pode possuir tanto dados de clientes quanto de lojas.

O mesmo código acima pode ser escrito dinamicamente com Javascript, mas isso não deixa o código mais simples:

Exemplo 2 de um componente confuso

Caso existam novas funcionalidades para a tabela de lojas que não serão aplicadas a tabela de clientes, esse componente vai ficar “sujo” com regras de negócio específicas da tabela de lojas. Não estou dizendo que é errado utilizar ifs nos componentes, somente quero destacar que eles devem ser utilizados com cautela para que não tirem a característica principal para o qual o componente foi pensado.

Quando formos escrever nossos componentes, também precisamos dar uma atenção especial à estilização. Não é recomendado definir margens por exemplo, pois isso afeta os lugares que usarão seu componente, e faz que seja necessário sobrescrever o estilo do seu componente sempre que ele for utilizado.

Uma maneira correta de escrever um componente web

Com tudo isso em mente, podemos querer criar um componente para compartilhar as definições de estilo entre as tabelas, por exemplo, o cabeçalho em negrito. Ainda que seus comportamentos sejam completamente diferentes, eles não deixarão de ser uma tabela. Uma alternativa, então, é escrever o componente de forma que o seu uso defina as suas características. Podemos chamar esses componentes de componentes abstratos* (um termo emprestado da orientação a objetos), onde seu comportamento não está completo enquanto ele não é utilizado por um componente pai. No exemplo citado na seção anterior, para resolver o problema das duas tabelas de cliente e loja, podemos criar um componente abstrato que vai receber as colunas e funções pertencentes a cada tabela quando ele for utilizado, isso faz desse componente um componente abstrato*. No Vue.js é possível alcançar esse objetivo com o uso de slots. Veja no exemplo abaixo a definição do componente:

Definição do componente de tabela

Agora observe o uso desse componente no caso dos clientes e em sequência, das lojas.

Exemplo de uso para a tabela de Clientes
Exemplo de uso para a tabela de Lojas

Podemos ver claramente a diferença entre o componente com vários ifs e esse último. Não é necessário analisar cuidadosamente o código para ver o que cada um faz, assim fica mais fácil dar manutenção ou adicionar novas funcionalidades para esse componente.

* É importante citar que o termo componente abstrato não é um termo oficial adotado pelos frameworks de desenvolvimento web, foi um termo que eu encontrei para explicar essa situação.

Limitações

Meu objetivo foi destacar uma forma ruim de escrever componentes web. Isso não significa que múltiplos comportamentos para um componente seja algo ruim. Além do que eu escrevi aqui, existe o Atomic Design que pode orientar de maneira mais profunda os conceitos para criar componentes web. Também destaco a importância dos testes automatizados para garantir que um componente possa crescer sem perder suas funcionalidades originais caso esse não seja o objetivo. Existem diversos materiais na internet que falam sobre esses assuntos, por esse motivo, decidi não escrever sobre eles nesse artigo.

Conclusão

Escrever código reutilizável é um dos desafios de um desenvolvedor, com prática, essa tarefa se torna mais fácil. Nesse artigo apresentei uma maneira de escrever códigos reutilizáveis sem que isso dificulte a manutenção e escalabilidade da aplicação. Com isso, espero que tenha ajudado você a escrever melhores códigos reutilizáveis. Até a próxima!

Links:

--

--