Os conceitos e petterns que sigo para minhas aplicações JS em Frontend
Olá! Como vai você?
Eu gostaria de iniciar minha aventura aqui no TabNews da mesma forma que eu inicio qualquer um dos meus projetos: divulgando os conceitos e patterns que eu gostaria de aplicar no desenvolvimento.
Vou tentar explicar brevemente e de forma disruptiva o que é cada um pois podem parecer novidades para alguns, porém, não desejo fazer disso um tutorial, mas talvez um local de discussão dos principios utilizados e receber também o feedback e dicas de vocês!
Bom, vamos começar? :v
Como escolho qual tecnologia utilizar?
Acho que essa é a parte mais importante, hoje como top de mercado no frontend, temos o React, Angular, e Vue... O Svelte tá ganhando mercado agora, mas também da pra aplicar tudo o que for citado aqui nele.
-
O React é o cara faz-tudo, você cria qualquer estrutura com ele, acho que deve ser o mais flexível, mas tem que tomar cuidado que às vezes ele pode virar uma zona!
-
No Angular é o cara que já vem com tudo pronto e de forma bem parruda, quanto mais recursos dele mesmo você utilizar, mais performático seu projeto vai ser e é só tomar cuidado com as subscriptions dele rodando com pipes e dando unsubscribe no destroy do componente que vai ficar supimpa.
-
No VueJS é não é muito diferente do Angular, e o melhor de tudo é que todas as variveis do data, props, computed e etc todas reativas... Isso quer dizer que se mudar o valor de alguma variável, ele já renderiza o componente de novo sem precisar de hooks igual o React ou Observables/RXJS do Angular.
Os 3 chegam no mesmo resultado final, oferecem as mesmas soluções, só que de formas diferentes... Todos tem forma de fazer SSR, SSG, Reactive Forms, e por aí vai.
Eu sempre acabo optando pelo React, e gosto muito de utilizar o NextJS, que oferece um kit de ferramentas incrível para deixar o React tão completo quanto os outros e tudo num só "lugar", sem precisar ficar baixando várias libs.
Mas já trabalhei em empresa onde foi necessário me adaptar ao Angular, e tudo bem! Melhor pra mim, mais experiência com outras tecnologias.
E o melhor de tudo, é tudo JAVASCRIPT.
Então você só precisar ver a documentação do "react way...", "angular way...", "vue way..." e por aí vai.
isso se aplica até mesmo ao quase falecido jQuery 😂
SOLID
O conceito do SOLID, como o Deschamps mesmo já descreveu, é um robô maluco que cada membro faz uma coisa diferente na aplicação, e ele é totalmente modular conforme a necessidade de uso.
Pra mim a base geral mesmo é o próprio SOLID, que é onde vou conseguir criar toda a orientação a objeto do projeto de forma acessível e escalonável, principalmente no CORE do projeto.
Eu não tenho muito o que dizer nessa etapa mesmo, é apenas uma preferência que não sei explicar kkkkkkkkk.
Quer aprender mais sobre SOLID? Segue vídeozinho do Deschamps onde eu realmente consegui aprender esse conceito que explodiu a minha mente para conseguir aplicar em meus projetos!
Assiste aí!
Componentização "extrema"
Não sei bem o nome disso, mas pra mim a coisa mais importante pra organizar o frontend, é criar TUDO em componentes.
O que leva ao Design System abaixo:
Atomic Design / Atomic Components
Esse Pattern pode ser pouco conhecido por alguns, mas pra mim é a melhor opção de para organizarmos nossas pastas de componentes.
Pra quem não sabe como funciona, uma explicação simples é que temos dividido a organização de componentes em até 5 pastas:
- Atoms
- Molecules
- Organisms
- Templates
- Pages
Essa organização tem aver com a coletividade de atomos.
Átomos
Nós temos o elemento mais "cru" da UI dentro da pasta Atoms. Sabe aquele input com o estilo padrão que você cria pra usar em todo formulário do sistema? (e que o UX do seu time provavelmente vai mudar o estilo em cada página que ele prototipar) Pois bem, é lá que você vai colocar ele. Cada menor elemento da UX fica aí!
Moléculas
Um coletivo de atomos forma o que? Uma molécula... Então, sabe aquele mesmo input que eu disse acima, mas com um label com a formatação de texto certinho, ícone do input, e a mensagem de erro que aparece em baixo, já seguindo a validação :is-valid ou :is-invalid ? Pois bem, importa o label, o componente de icone, o input e o componente de erros que você criou nesse cara aí, e exporta ele como um todo, recebendo apenas as propriedades dos componente pai e passando para seus componentes filhos.
Organismos
Agora um coletivo de Moléculas forma o que? Exato, um Organismo!
Então sabe o componente de "form-control" que você criou? está na hora de você usar ele para criar um componente do formulário.
Então é aí que você vai montar todo o formulário, schema de validação, importar o seu service de http client para enviar ele via post, e por aí vai. Todo o funcionamento DAQUELE formulário você faz ali.
Templates
Um coletivo de Organismos forma o que? um corpo humano Um template! Aqui você vai montar o seu TEMPLATE utilizando os componentes de UI que você criou nos Organismos.
É aí que você vai importar o seu header, navbar, breadcrumbs, footer e outros componentes da UI, só esperando para receber via body content o conteúdo da página.
Pages
Agora aqui é aonde junta tudo e joga fora e faz a mágica acontecer, você importa aqui o template desejado e só passa para o content body o componente de organismo de conteúdo que você deseja apresentar na tela.
Ficou confuso?
Segue aqui um tutorial bonitão de como aplicar o conceito criado pela Rocketseat!
Clica aqui!
RESTful
Quando separamos as stacks backend e frontend, nossa aplicação só tem uma forma de se comunicar com o backend... Chamadas de endpoints via http que retornam um model via JSON.
Se precisar armazenar algo temporariamente você pode usar o localstorage para algo permanente e os cookies para algo com validade.
Simples assim.
Segue um bom tutorial da Rocketseat sobre REST e RESTful: É só clicar
Frontend BURRO / Frontend Passivo
Isso aqui eu bato na tecla em quase todo projeto... O Frontend deve ser o cara que só exibe a informação. Qualquer plano de negócio deve ser resolvido no BACKEND, chamando as apis via endpoints.
"Never else", "true vars" e "triple equals".
Esses caras eu também não sei o nome correto, mas eu gosto de chamar eles dessa forma.
Quando vamos criar um if/else, precisamos de uma condição TRUE, correto?
Um programador Jr. normalmente faria:
if(varivel == true) {
console.log('aqui caiu true')
} else {
console.log('aqui caiu false')
}
Esse de cima é fácil, agora imagina um if com diversas condições, exemplo:
if((varivel1 == true && varivel2.includes('texto') == true ) || varivel3 == true) {
console.log('aqui caiu true')
} else {
console.log('aqui caiu false')
}
Cara, vai dar manutenção nesse código 3 meses depois, duvido que você vai saber o que rola ai kkkk
Tudo no JS pode ser "resumido" em uma varivel booleana para criar essas condições.
Então, pq não deixar mais organizado como abaixo?
const var1IsTrue = !!varivel1 // o operador !! faz a variavel retornar uma negação da negação, ou seja... !true = false, !!true = not false (ou true)
const var2IncludesText = varivel2.includes('texto') // Ele já retorna boolean
const var3IsTrue = !!varivel3 // o mesmo do var1IsTrue
const nomeDaCondicaoDoVar1EVar2 = var1IsTrue && var2IncludesText
const nomeDaCondicaoFinal = nomeDaCondicaoDoVar1EVar2 || var3IsTrue
if(nomeDaCondicaoFinal) {
console.log('aqui caiu true')
}
if(!nomeDaCondicaoFinal) {
console.log('aqui caiu false')
}
Explicação bônus:
O operador lógico !var não valida apenas boolean, ele atual dentro das especificações do toBoolean(), onde ele valida: false, 0, undefined, null, "" (string vazia), ou até mesmo {} (objeto vazio).
Exemplo:
const teste1 = ""
const teste1IsTrue = !teste1
console.log(teste1IsTrue) // = false, pois teste1 está vazio
const teste2 = "nao estou vazio"
const teste2IsTrue = !teste2
console.log(teste2IsTrue) // = true, pois teste2 não está vazio
/* No operador !! você está basicamente negando a negação, ou seja, const teste1IsTrue = !!teste1 retorna true ao invés de false, e const teste2IsTrue = !!teste2 retorna false ao invés de true.
Ficou mais verboso né? mas pelos nomes das variaveis você sabe exatamente o que faz todas as partes da sua validação só de bater o olho.
E você não precisa validar (nomeDaCondicaoFinal === true), apenas (nomeDaCondicaoFinal), pois no if ele já precisa que seja true.
E se você utilizar o conceito de never-else, validando (!nomeDaCondicaoFinal), você já está dizendo que "é falso que essa condição é true", e isso retorna em true!
Hoje o JS é minificado, então não tenha medo de declarar variáveis, é até melhor para debugar!
Tá, mas e o triple equals com === ?
No JavaScript por padrão não existe validação de tipagem da varivel, isso força a validação de tipagem, "blindando" cada vez mais o seu projeto.
Exemplo:
const str = ""
console.log(str == false) // retorna true
console.log(str === false) // retorna false
Foreach, map, find, findIndex, reduce, some, every e outras formas de percorrer um array
Hoje "gracias" ao ECMAScript modernizando o JS, temos várias formas de percorrer um array, se eu vejo um trecho de código fazendo um for(let i = 0; i <= 10; i++) {}
o bicho vai pegar vai ter a pull request reprovada SIM! kkkk.
Brincadeiras à parte, esses métodos ajudam muito a reduzir o código e deixar a gente entender com maior facilidade o que cada função está fazendo, o que ela precisa retornar e etc.
Então dê um ligue nesse vídeo aqui do Código Fonte TV que explica os principais métodos: bora ver!
Apenas um nível de identação por médoto
Esse é bem simples, e quanto mais você praticar isso, melhor é para você entender tudo o que é feito dentro das classes de seu código.
Assim como na parte de UI, temos o conceito de "componentize tudo", parte dos services é bom você "metodonizar tudo" (ok, essa tirada foi ruim!)
Esse vídeo do Matt Sokola explica muito bem, porém está em inglês... Mas você pode achar conteúdo sobre isso no livro Clean Code/Código Limpo, de Robert Cecil Martin.
O link do vídeo tá aqui!
Documente seu código da forma correta / JSDoc
Como eu disse anteriormente, o javascript hoje é minificado em produção, então não tem problema nenhum deixar comentado no código os métodos que você cria. Desde que da forma correta! utilizando o JSDoc
Vamos ao código em exemplo:
function calcularFrete(cep1, cep2, hasVoucher) {
..todo o calculo de frete aqui..
return price;
}
Quando for implementar essa função, vai ter que ficar procurando o método sempre pra lembrar quais os parametros e o que ele retorna?
Faz assim ó!
/**
* @description efetua o calculo de frete de acordo com o cupom aplicado
* @param {string} cep1 - cep da transportadora
* @param {string} cep2 - cep do destinatário
* @param {boolean} hasVoucher - boolean se o usuário tem cupom de desconto no frete
* @return {number} price - valor final
*/
function calcularFrete(cep1, cep2, hasVoucher) {
..todo o calculo de frete aqui..
return price;
}
E o legal é que de forma nativa as principais IDEs de mercado já fazem a leitura do JSDocs nas funções e te dão a orientação quando passa o mouse por cima quando você usar um const valorFrete = this.calcularFrete('00000-000', '11111-111', true)
E se você estiver deixando uma função absoleta, você pode usar o @deprecated since version 2.0, please use newCalcularFrete() instead
Que toda vez que você chamar a função que está em processo de substituição, mas ainda sendo mantida para alguma garantia de uso legal, ela ficará tipo: this.calcularFrete() (riscado assim) visualmente, e quando você passar o mouse por cima, você já pode ver que essa versão está desatualizada e tem uma nova implementada.
Você pode achar toda a formatação do JSDocs no site oficial, aqui!
Finalmente finalizando
Galera, existem muitos outros conceitos que eu aplico que eu posso não ter lembrado de aplicar aqui, mas eu garanto que esses são os que eu mais "bato o pé" pra seguirem nos meus projetos, pois assim eu sei que o sucesso é garantido.
Por isso comenta ai o que você achou e possíveis dicas, pois estou pensando em fazer uma parte 2 desse tópico!
Peço desculpas pelos erros de português afinal sou programador e não professor mas mesmo com uma breve revisão posso ter deixado passar algo.
Grato a todos, e vamo que dale TabNews!
Isso aqui vai ser o novo stackoverflow, vai vendo! kkk