WebComponents de nível empresarial - parte 2

WebComponents de nível empresarial - parte 2

No artigo anterior vimos como uma empresa de grande porte que utilizava bibliotecas e frameworks proprietários e opinativos para criar os seus componentes de UI começou a se transformar a quando introduziu os WebComponents como sua stack principal.

Nessa segunda parte, vamos ver os 3 últimos grandes desafios que foram encontrados e mitigados no decorrer do projeto: como lidar com Breaking Changes, como comunicar e criar uma comunidade de desenvolvedores na empresa (para reportar bugs ou pedir novas funcionalidades) e como manter a qualidade evitando que novas versões quebrem projetos legados.

Uma breve recapitulação:

  • Primeiramente definimos como os repositórios deveriam ser organizados: 1 repositório para cada componente foi o escolhido para não criar nenhuma dependência (o que significa 1 pipeline para cada também).
  • O segundo foi a escolha da tecnologia e, após alguns embates entre LitElement e StencilJS, o StenciJS foi escolhido pois a empresa se identificava mais com a estrutura.
  • E o terceiro ponto e o mais importante para o dia a dia: a criação de um Marketplace que obtivesse a documentação e mostrasse uma Demo de cada componente, tudo online e conectado ao GitHub da empresa.

Os três primeiros desafios identificados foram mitigados e possibilitou criar e entregar os componentes, porém, alguns pontos precisavam ser discutidos, pois para toda tecnologia que você quer incluir em grande escala, algum controle de qualidade você precisaria ter para esses componentes.

Agora começamos a explorar os três últimos (e não menos importantes) pontos:

  • Breaking Changes e updates.
  • Comunicação (mudanças, novos componentes, bugs).
  • Qualidade.

Atualizar, Comunicar e Revisar

Breaking Changes e updates

Criar um componente que encapsula um input text parece algo relativamente simples, não é? Bastaria criar um CSS que deixaria com o estilo da empresa, mas não é tão simples assim. Alguns componentes são muito importantes, pois receberão muitas estilizações com o passar do tempo. Muitas demandas de projetos que precisarão de coisas diferentes para um simples componente.   Se você quer entregar algum ganho para quem for utilizar, o componente começará naturalmente a receber algumas funcionalidades.

Só nessa empresa que uso de exemplo, o componente que encapsulava o input text recebeu as funcionalidades:

  • Capacidade de incluir um ícone no prefixo (lado esquerdo).
  • Capacidade de incluir um ícone no sufixo (lado direito).
  • Aceitar apenas números.
  • Mostrar um texto abaixo para auxílio ou para quando estiver com o estado de inválido.
  • Mostrar ao lado da label um ícone de ajuda, para mais informações sobre o campo.

Essas e muitas outras propriedades que foram sendo desenvolvidas com o passar do tempo, pois encapsular no componente faria mais sentido do que vários projetos implementarem a mesma coisa.

Conforme os pedidos de inclusão de funcionalidade chegavam à preocupação era uma só: não posso quebrar as aplicações que já estão funcionando. Se alguém precisar atualizar a versão do componente para resolver algum bug, o design e a implementação dele não poderia quebrar (e receber novos bugs).

A política que foi criada foi, primeiramente, utilizar Semantic Version (Semver):

Ou seja, apenas em casos raros em que não podemos um novo parâmetro e uma breaking change precisará ser lançada, mudaríamos a versão major de um componente. Enquanto parâmetros puderem ser criados, o componente deve apenas alterar para uma versão Minor ou Patch.

Alterar uma versão Major, significaria ter de comunicar todos os desenvolvedores e documentar o que precisaria ser feita para a migração. Então junto com a regra de se utilizar Semver nos componentes de forma rígida, foi criada a máxima de que: tentar ao máximo evitar a versão 2, sempre ficar na versão 1 de um componente, crie parâmetros.

Comunicação (mudanças, novos componentes, bugs)

Ok, digamos que em determinado momento não vai dar para criar um parâmetro ou que a empresa toda está passando por um redesign e todos os componentes vão necessariamente mudar para uma versão 2. Ou mesmo um bug importante surja e seja necessário informar a todos para atualizar os componentes. E agora, como deveremos agir?

Depois te ter criado o Marketplace, sabia que ainda sim precisava manter a comunidade de desenvolvedores informada e uma organização deveria ser feita para documentar e receber os bugs e pedidos de novas funcionalidades.

Changelog

Como já havia determinado que receberia os pedidos dos desenvolvedores através das issues do Github, também decidi manter um CHANGELOG.md para cada componente. Desta forma, poderia fechar as issues atrelando um commit e manter o histórico de fácil localização das mudanças (escolhi o formato que a equipe do Angular utiliza nos repositórios, pois já era de simples entendimento).

Blog

Nessa empresa também utilizamos o Confluence, como ferramenta de documentação, essa ferramenta já vem com uma funcionalidade de blog:

Criei uma seção para a comunidade de Front-end poder assistir e receber um e-mail sempre que houvesse algo de novo no blog do Confluence. Com isso, a cada componente novo ou funcionalidade importante eu poderia informar a todos como utilizar e como acessar o link no Marketplace.

News

Por último, pedi na empresa que fosse criado um e-mail corporativo para front-end (aqueles que você pode incluir várias pessoas no Outlook, mandando apenas para o grupo).  Fui adicionando ao grupo as pessoas que precisariam receber a informação.

A cada coisa nova, componente, mudança no Marketplace, alteração de Design, nova iniciativa em Front-end ou até para ensinar algo interessante ou apontar links externos para estudo, eu criava um e-mail, que teria um conteúdo refletido do blog (o blog manteria o histórico e o e-mail convidaria para acessar e saber mais). Essa News por e-mail foi a que teve maior sucesso, pois chamava as pessoas para saber o que estava acontecendo e muitas vezes eu recebia algum feedback diretamente por lá. A periodicidade dessa News era de em média 2 por mês.

Apresentações para a comunidade de devs

E por último deixei estabelecido que faria duas apresentações para a comunidade sobre as novidades no Front-end a cada 6 meses.

O intuito era manter a comunidade informada e engajada, com isso promover o uso dos WebComponents de forma que muitos projetos legados quisessem reescrever e projetos novos quisessem usar, quanto mais motivada era a comunidade, mais feedback eu recebia e mais componentes eu descobria que poderiam ser feitos, era como evoluía.

Nessas apresentações também surgiam dúvidas e ideias, que só quem está lá programando nos projetos todos os dias sabem da necessidade. Era uma forma também da minha área se atualizar e mostrar o que havia de novo para quem ainda não havia visto (sempre tem a rotatividade de desenvolvedores e sempre haverá novas pessoas que nem sabem que o Marketplace existe).

Qualidade

Pronto, os componentes estão escritos, demonstrados, sendo utilizados na versão 1 por alguns novos projetos, todos começam a testar e boom, alguém precisa da primeira alteração em um primeiro componente.

Como garantir que nessa primeira alteração eu já não vou quebrar alguma coisa para outro projeto? Eu previ as situações de uso? Parei para pensar sobre isso? Quão fácil está alterar o meu componente? O código está simples ou complexo?

Deixei para o último tópico o que deve ser pensado desde o início do desenvolvimento de um componente.

Quando escrevemos um componente apenas para uma aplicação, já sabemos o que queremos dele, qual o comportamento esperado, não estamos preocupados se vai dar para utilizar em um outro projeto que tem outro propósito. Como posso garantir (ou ao menos chegar perto) de que uma alteração não vai quebrar outros 80 projetos de uma vez só e me causar uma dor de cabeça gigante para falar com todo mundo? =o

A reposta é um conjunto de pontos importantes:

  • Análise Estática.
  • Testes Unitários.
  • Estrutura do Typescript.
  • Estrutura do CSS.

Explico o que fizemos para cada ponto, a partir que você tem esses pontos na cabeça e como regra para criar um componente, sua vida vai ficar 120% melhor.

Análise Estática

A empresa já utilizava um Sonarqube para fazer análise estática, o que já era um ponto positivo, mas quando escolhi o StencilJS também vieram algumas regras específicas para ele.

O que fiz primeiro foi configurar o ESLint nos componentes (mais tarde também criei um gerador com o Yeoman para já criar um componente com todas as configurações necessárias para a gente, inclusive o ESLint e as regras que defini).

Com o ESLint configurado (não é a ideia desse artigo mostrar como configurar o ESLint no StencilJS, google it), instalei também biblioteca para alguns casos específicos que é de propriedade da equipe do Ionic: https://github.com/ionic-team/stencil-eslint.

Uma grande vantagem do ESLint é poder se gerar um arquivo json ao final da análise para mandar o resultado para o Sonar (caso encontre algum Code Smell).

Você só precisa configurar:

  • No seu package.json, criar um script para executar o eslint gerando um arquivo json ao final, por exemplo (no nosso caso os arquivos têm a extensão tsx para o StencilJS):
  • Incluir essa task para ser executada no seu pipeline antes de executar a análise estática do Sonarqube.
  • Na configuração do Sonarqube (cada empresa coloca em algum lugar diferente) é só adicionar a propriedade para enviar o arquivo json gerado, por exemplo:

Obs.: você pode criar um formatter para o ESlint para alterar a severidade das regras se necessário. Não esqueça de instalar o plugin do ESLint para a IDE que você utiliza hein.

Testes Unitários

Esse tópico, para quem já conhece testes unitários ele é autoexplicativo, eu só gostaria de expor o ponto pois esse é um dos mais importantes.  Ao criar uma propriedade, crie os testes unitários necessários para testá-la e tente imaginar cenários diferentes para o uso dessa propriedade combinado com outras já existentes.

Os testes unitários é que te farão enxergar se você não está entregando algo novo e quebrando algo já existente, evitando aqueles 80 projetos te chamando de uma só vez.

Não preciso nem dizer que os testes unitários TÊM que ser executados no pipeline e que o pipeline deve parar caso eles não executem com sucesso né? NÉ?

Estrutura do Typescript e Estrutura do CSS

Para ter um padrão crie uma estrutura para como você vai criar o seu código, aqui por exemplo mantemos os métodos o ciclo de vida do StencilJS primeiro, depois os métodos privados, o método render deve sempre ser o último e assim vai.

Não tem uma regra exata de como você vai fazer isso nesse caso, o importante é que seja definida uma regra e ela seja seguida para os criadores de componente, nesse caso um Code Review ou uma regra personalizada no ESLint ajudam bastante. Já para a estrutura de CSS o que melhor se encaixou aqui foi o BEM (Block, Element, Modifier), por ser simples e utilizarmos o SCSS como ferramenta.

Como você vai ver em WebComponents, muito também será usado de CSS Variables (CSS4) e manter eles organizados e documentados ajuda bastante, já que no build o StencilJS gera a documentação (readme.md) automaticamente a partir do que pega de dentro do componente.

That’s it

Enfim é isso. Muitas lições aprendidas e muito o que compartilhar. Foi um projeto que poderia ser tratado de uma forma simples, mas hoje eu percebo como a aderência é grande e como está sendo bem utilizado. Vi que os meus esforços valeram a pena.

Essa empresa que estou é multinacional e esse projeto virou um case de sucesso aqui na Bélgica. Agora estamos expandindo para as outras filiais em vários outros países, pois a estrutura está toda pronta. Sucesso na sua empreitada e até a próxima \o/.

Álvaro Junqueira - https://github.com/alvarocjunq

💡
As opiniões e comentários expressos neste artigo são de propriedade exclusiva de seu autor e não representam necessariamente o ponto de vista da Revelo.

A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.