Aprendizados de 1 ano de projeto em vue.js com escopo ultra caótico
Published: 2021-01-26 17:47:17

_tl;dr: Implemente Design System, componentize, faça componentes base, faça testes unitários / de integração, não ignore o log do terminal. O trabalho dos designers pode facilitar muito a vida do front._

Uma das coisas mais legais de trabalhar na Snowman Labs é que cada hora surge um pepino diferente pra gente resolver. E a gente gosta disso, faz parte da natureza do programador, eu diria. A gente já resolveu cada bucha que daria um artigo por si só. 
O último projeto que participei foi um desafio técnico e tanto, por uma série de fatores. Várias coisas foram reescritas várias vezes, e a gente tinha noção de que isso ia acontecer, então cada tomada de decisão em relação a arquitetura foi feita com bastante cautela, tentando prever o que poderia mudar e o que a gente poderia fazer pra minimizar a quantidade de problemas e a eficácia do reaproveitamento. 

Em determinado momento o sistema foi dividido em dois (repositórios diferentes) e depois mergeado de novo, o que colocou em teste nossas decisões. Felizmente, o merge foi muito menos doloroso do que poderia ter sido. 

Um pouco de estatística de nerd: Tivemos 185 componentes de features (inteligentes e burros) e 47 na pasta core, ou seja, componentes que não pertencem à nenhuma feature específicam, totalizando 232 arquivos .vue na versão que foi entregue ao cliente. Ouso dizer que pelo menos a mesma quantidade de arquivos foi deletado por conta do escopo caótico do projeto (e descansam em paz no nosso git). O que não é necessariamente um problema, Agile é feito justamente pra lidar com esse tipo de problema.
Ao longo de alguns projetos de git que compuseram esse projeto, tivemos 2181 commits, distribuidos em 671 merge requests que foram de fato mergeados. Houve uma média de 2% de merge requests que foram fechados ao invés de serem mergeados na master.
A versão final do projeto possuía pouco mais de 20372 linhas de código na sua pasta de features, e 3004 na pasta core, que, graças a elas, poupamos de escrever muita coisa redundante na pasta de feature.

A componentização pesada ajudou bastante a gente a lidar com os problemas. 
Slots não foram tão usados (foram fundamentais em pontos específicos, como forms e elementos de UI com miolo dinâmico), felizmente a maior parte das vezes conseguimos resolver com parametrizações.

Aqui vou deixar alguns pontos chave que aprendemos ou queremos reenforçar como aprendizado nesse projeto:

# Pontos de valor
## Designers podem ajudar (e muito) no desenvolvimento
O Design System ajuda a padronizar o tema e a componentização do sistema, facilitando a vida do dev front, auxiliando na tomada de decisão independente (fica muito mais fácil pro desenvolvedor). Felizmente, nesse projeto, tivemos designers competentes (vlw Rubens e Stoco) já deixando tudo preparado e sólido pra trabalhar. Às vezes o povo do front tem que colocar um botãozinho, ou um inputzinho. Com um Design System funcional e robusto, o front pode se aventurar em meter a mão na UI para coisas pequenas sem precisar encher o saco do designer pra alterar o protótipo praquela coisinhazinha ali. O que não é a melhor coisa pra se sair fazendo, mas sabe como é, o tempo urge e a sapucaí é grande.

**Uma boa componentização (misturado com Design System) pode transformar criar telas novas em lego**. Quando entrou um dev front na metade do caminho (fala, Puff!), com pouca experiência em vue (mas já em outros frameworks), fazer a parte de UI foi praticamente um drag and drop dos componentes que já existiam. A semântica e a simplicidade de usar os componentes (tanto os base quanto os da feature) permitiram que tudo fosse criado muito rápido, e sem ficar com cara de copicola em código que já tava funcionando. Com uma introdução bem rápida ao projeto, já dá pra tacar o pau. Se tiver tudo em [storybook](https://storybook.js.org/), melhor ainda! Não foi o caso desse projeto kkkkkkkk embora usamos em outro projeto anterior e gostamos bastante. Super recomendamos. 

## O front ama quando o designer faz as coisas já baseada num framework de UI
![Componentes base](https://dev-to-uploads.s3.amazonaws.com/i/1kygo80dz3xue2pfi93d.png)
 
Nesse projeto decidimos trabalhar com o [vuetify](http://vuetifyjs.com/), que é baseado em [material](https://material.io/design), e os designers montaram os componentes todos no vuetify . Sendo assim, quando a gente foi codar os componentes base, a gente praticamente só extendeu e customizou os componentes do framework. Isso poupou muito tempo e deu muito poder aos fronts, agilizando muito o desenvolvimento do look and feel geral do sistema, além de reduzir significantemente a quantidade de código escrito e repetido no sistema.


## Vuetify + Componentes base para não precisar escrever CSS
Isso é uma das coisas mais legais de desenhar sistemas com Design System e componentes base (e designers competentes, claro. Valeu Rubens e Stoquinho). 90% dos componentes de página (sem exagero) possuem 0 CSS escrito. Tudo está como parâmetro de componente, customização ou defaults do vuetify e classes helpers do vuetify

## Feature modules são uma ótima forma de organizar coisas
![Exemplo de feature module](https://dev-to-uploads.s3.amazonaws.com/i/cq45ikkug78616tcyr66.png)
 
Como um teste, decidi propositalmente não usar [feature module](https://ednsquare.com/story/3-tips-for-scaling-large-vue-js-application------5jFiEn) (tip #1, não tem link direto, infelizmente) no sistema para ver em que momento a organização sai do controle. Descobrimos rapidinho que, com 5 ou 6 features no sistema, você já começa a ficar incomodado e quer uma separação melhor. Além de ajudar bastante na orgnanização, ainda torna o namespacing menos verboso por conta da localização dos arquivos no filesystem. 

## Mixins sao poderosos e perigosos
Mixins são poderosos pois permitem lógicas de componentes serem reutilizadas e escritas em um lugar só, porém, nos frameworks de [front](https://css-tricks.com/how-the-vue-composition-api-replaces-vue-mixins/#mixins-are-considered-harmful) [em](https://reactjs.org/blog/2016/07/13/mixins-considered-harmful.html) [geral](https://www.codamit.dev/vuejs-mixins-are-broken), essa feature deixa alguns problemas de DX ao ser utilizada. Pra mim, o mais marcante deles é não ter um namespace claro. Quanto mais mixins você tiver utilizando, mais você não vai ter a menor idéia de onde aquele trecho de código vem. Além de outros, como colisão de nome (princípio parecido com o de não usarmos `prototype` no js), etc.

## Sintaxes alternativas para componentes e typescript
Vue2 não é muito bom pra lidar com typescript de forma vanilla, então o próprio core team e a comunidade criaram soluções pra você ter sintaxes alternativas (nada muito diferente) que suportam os toolings mais modernos e que tiveram maior adoção no decorrer dos últimos anos, como o [vue-class-component](https://class-component.vuejs.org/), [vue-property-decorator](https://github.com/kaorun343/vue-property-decorator) e o [vuex-class](https://github.com/ktsn/vuex-class). 
O caso mais notório de ferramenta que tira proveito disso, com certeza é o typescript. Com essas tecnologias, usar typescript é 100% possível, e usando essas sintaxes alternativas, diria até que o código fica mais enxuto e claro do que o vue sem nada (`@Action` do `vuex-class`, pra mim, tem uma sintaxe mais agradável que `mapActions` do `vuex` cru, por exemplo). 
Começamos o projeto sem, mas o Brunão começou a implementar usando isso e com uma curva bem pequena de aprendizado, aderimos felizes ao novo método de escrever componentes vue2.

## Testes se pagam rapidamente
A comunidade de front só tem dado a devida atenção a testes de uns anos pra cá, sempre foi um inferno testar as coisas, e eu nem sempre fui a melhor pessoa para advogar o uso de testes kkkkkkkkk inclusive, até um tempo atrás, eu era explicitamente contra, com um tom de ironia mas um fundo de verdade. 
Muito dos meus receios em começar a aplicar eram baseados totalmente em ignorância do ferramentário e desgosto em encarar a curva de aprendizado e o tempo extra ao desenvolver as features. Porém, quanto mais eu decidi encarar, mais foi ficando claro que o tempo investido vale a pena, pois traz segurança e te poupa muito tempo em descobrir ONDE alguma coisa não tá mais funcionando. Ainda há muito a estudar e pegar fluidez, mas quanto mais testes você faz, mais rápido fica fazê-los.

## Jest first, depois cypress (eu acho)
Eu comecei usando [cypress](https://www.cypress.io/) pois achava bem mais simples testar se algo estava funcionando simplesmente usando o próprio browser, mas depois de me aventurar com [jest](https://jestjs.io/) (usando [vue-test-utils](https://vue-test-utils.vuejs.org/), percebi que: ele é bem mais rápido, e os testes tem uma função razoavelmente diferente (o cypress não te diz onde algo tá quebrado a nível de código, e sim a nível de "tem alguém usando isso aqui e não tá funcionando"). 
Eu comecei escrevendo testes pro sistema em cypress, mas toda vez que eu ia mexer, era leeeeento. Inclusive tive que pedir pra colocarem mais ram no meu maczinho (imac de 2011, guerreiro) pois eu não tinha ram suficiente pra rodar o cypress e todo o resto do ferramentário (e olha que eu nem usava o VSCode ainda). 
Suspeito que dava pra ter feito tudo que eu fiz em cypress, usando jest, o que teria uma curva de dificuldade um pouco maior, mas o uso dos testes seria extremamente mais rápido e útil. Mas apenas suspeito. O próximo sistema vai ser feito "jest-first", vamos ver o que vem por aí, não dá pra saber ainda.

## Módulo core pra coisas gerais (mas usar com cuidado)
![Parte do módulo core](https://dev-to-uploads.s3.amazonaws.com/i/kv503yizm9pis5yt0mns.png)
 
Devido a uma decisão de arquitetura que tomamos, o sistema todo é cru, e a gente injeta os feature modules num sistema que, em seu estado inicial, só possui a feature de login. Portanto, temos um "módulo core" onde colocamos tudo que não pertence especificamente a módulo nenhum. Isso agiliza muito as coisas, porém tem seus drawbacks. Há de se mexer nesses caras com bastante cuidado, pois não se sabe exatamente quais partes do sistema utilizam ele. Entretanto, o fato de estar em "core" já deixa isso meio implícito.  Há algfuma forma melhor de fazer isso? Não sei, não pensei direito ainda. A idéia de usar os core para extender em componentes de cada feature parece interessante, mas talvez desnecessariamente verbosa, mas é a primeira ideia que me passa em mente.

## Performance e bundle size são pontos relevantes
Rapaz, a bundle final do sistema deu 13mb! Num sistema web! Lógico que isso não pode ficar assim. Imagina, ter que carregar 13mb só pra usar o sistema. Dito isso, fui atrás de [técnicas pra reduzir o bundle](https://medium.com/shard-labs/how-to-drastically-reduce-your-bundle-size-and-load-time-in-vue-js-54370d513fdf) e diminui de 13mb pra 2mb. Ainda dá pra dar uma escovadinha aqui ou ali, porém já temos um excelente ganho. Um dos grandes culpados é o vuetify, que se colocado de qualquer jeito adiciona um tamanho bem significativo ao sistema, mas o próprio vuetify te ensina formas de usar a biblioteca da [forma mais enxuta possível](https://vuetifyjs.com/en/features/treeshaking/#vuetify-loader). A forma que o vue2 foi desenhado [não permite](https://github.com/vuejs/vue-cli/issues/1644#issuecomment-469308280) usar alguns recursos de redução de bundle do webpack, o que é somewhat triste, mas reclamar disso é pedir demais pelo trabalho dos caras. Inclusive, alguns dos problemas que existem nesse quesito, se bem me recordo, vão ser adereçados no vue3, então os caras já estão cientes e trabalhando nisso. 

## Negligenciar os logs do terminal... nem dá nada, até ser tarde demais

![Report do build](https://dev-to-uploads.s3.amazonaws.com/i/4qxsfbrh4sxrfslmw3ju.png)
<figcaption>O build é feito, mas não consigo ver o output por conta dos erros do log</figcaption>
_

 
Eu não sei em que momento do projeto a gente parou de dar bola pros linters. Tem toda uma treta encima do eslint e sua compatibilidade com typescript (tslint foi descontinuado e virou outra lib que, enquanto estávamos desenvolvendo ainda estava bem imatura se bem me lembro) e numa mistura de prettier, eslint, typescript, chegou uma hora que nos embananamos e não deu pra dar conta mais. Isso sem contar com o fato de eu usar o Sublime Text antes (saudades), que no meu ubuntuzinho, não tinha a melhor das integrações com linter (parte porque meu ubuntu sempre vive meio quebrado). Mas tava tudo funcionando, né.

Daí chegou um ponto que começou a atrapalhar. Não conseguíamos ver o output do comando de build, não conseguíamos mais usar o logo como auxílio, regras de typescript quase não faziam sentido mais. Até tentei fazer uns refactors pra ir limpando essas coisas, mas a pressão do projeto me obrigava a avançar mais rápido do que meus refactors davam conta. Só fui sentir a dor de verdade quando fui otimizar a build final: tive que desativar o typescript e os linters pra fazer que o comando rodasse sem erro, e aí sim entendi alguns gargalos que não tinha noção antes (até tinha, mas não passava de "em ambiente de homolog leva muito tempo pra abrir o sistema", seguido por um "as otimizações necessárias ainda precisam ser feitas").
Não deixem chegar a esse ponto, menines.

# Coisas que senti necessidade / Looking forward to:

## Styled components
Tem várias strings gigantes de várias classes que foram repetidas em vários momentos. Com certeza dava pra agregar elas em unidades de classes semânticas (o que seria meio que dar um 360 no conceito de CSS funcional, mas há o debate de que CSS funcional é um 360 encima do style inline... enfim, discussão pra outro momento). O importante é que eu senti falta de aplicar isso no sistema a partir de um determinado momento. Tenho certeza que, com styled components, os templates ficariam significantemente mais enxutos e semânticos.

## Typescript
Finalmente caiu a ficha sobre [typescript](https://www.typescriptlang.org/). Quanto maior o código, maior a chance de você não saber o que tem naquela variável. Além da tipagem, typescript também documenta as coisas, facilita a vida de quem for mexer naquele código depois e não tiver tudo na ponta da língua. Meu uso de typescript nesse projeto deixou a desejar, mas já foi o suficiente pra entender o real valor desse negócio que eu tive tanta resistencia em usar, afinal, "vai demorar mais pra escrever as coisas!"

## Usar mais o vuex...? Talvez?
Eu uso esse fluxograma que tem me servido bem como guia de tomada de decisão:
![](https://res.cloudinary.com/practicaldev/image/fetch/s--8FLfEUjr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/maxpou/maxpou.fr/master/content/posts/2018-12-13-scaling-vue-app/vuex-or-not.png) 
 Porém, às vezes fico pensando se  talvez desse para passar mais lógica de processamento para o vuex. Esse projeto não teve cache de dados, nem uma hierarquia complexa de componentes. Claro, há bastante informação no store, mas quase sempre era nas camadas de estrutura do projeto, e não nas features em si. Sempre quando vou ver outros projetos grandes, eu vejo umas stores ultra boladas, e fico pensando: será que eles tão jogando as coisas no vuex onde não precisa? Será que meu projeto realmente não precisa de vuex? Ou será que eu tô fazendo algo errado? 

# Conclusão 
Espero que tenham tirado algum proveito. O Vue 2 dá pra fazer bastante coisa dahora, e consideravelmente mais simples, rápido e divertido que nos outros frameworks (sou enviesado pra falar por ser o framework que mais usei até agora? Imagiiiina...). 
Muitas necessidades foram surgindo no meio do caminho da timeline do desenvolvimento do framework, e foram sendo adereçadas pela comunidade enquanto a ideia de uma forma mais nativa para se resolver era matutada em background pela galera do desenvolvimento do Vue 3, que já saiu e provavelmente vai ser usado no próximo projeto aqui na Snowman Labs.