Bem vindo ao repositório do time de Front-end da Talentify!
Este guia de desenvolvimento tem o objetivo de melhorar significativamente a qualidade do código do projeto.
https://github.com/ryanmcdermott/clean-code-javascript
Uma boa convenção permite com que tanto a escrita quanto a leitura do código possa ser previsível, reduzindo tempo de raciocínio.
Integrar regras do guia em linters como Eslint e Prettier para automatizar a correção para que estas regras se tornem uma vantagem, e não um atraso.
Por fins de padronização, deve-se utilizar sempre espaçamento com 2 espaços para todo tipo de linguagem. Nunca utilize tabs ou espaços simples para identar o código.
Isso se aplica para JS, CSS, HTML, JSON etc.
.example {
color: blue;
}
<ul>
<li>Fantastic</li>
<li>Great</li>
</ul>
- Nome de componentes
- Nome de classes;
- Nome de tipos;
- Variáveis;
const isVisible = true;
- Funções;
function sayHello() {}
- Elementos BEM;
- Modificadores BEM;
- Atributos de elementos;
- Constantes globais;
Pode ser o nome do componente ou o bloco da estrutura.
Deve ser escrito em PascalCase.
<div class="Feed">...</div>
<nav class="FooterMenu">...</nav>
Deve ser escrito em camelCase.
<div class="Feed__wrapper">...</div>
<div class="Feed__list">...</div>
<div class="Feed__item">...</div>
Deve ser escrito em camelCase.
<div class="MenuItem MenuItem--isLast">...</div>
<div class="Menu__item Menu__item--isLast">...</div>
Blocos e elementos devem ser sempre independentes de seus parentes, isso serve para simplificar a manutenção e permitir uma herança. Por ex, um elemento __container
ou __wrapper
deve ser independente de um __list
ou __item
.
// bad
const userName;
- Quando retornar boolean, sempre utilizar a forma interrogativa para compor nomes.
// bad
let visible: boolean = true;
get visible(): boolean {
// ...
}
get headerExists(): boolean {
// ...
}
// good
let isVisible: boolean = true;
get isVisible(): boolean {
// ...
}
get hasHeader(): boolean {
// ...
}
Escrita sempre deve ser em forma imperativa.
// bad
function isHeaderVisible(): boolean {
// ...
}
function userName(user: User): boolean {
// ...
}
// good
function verifyIfHeaderIsVisible(): boolean {
// ...
}
function getUserName(user: User): boolean {
// ...
}
Quando for necessário adicionar algum valor personalizado, sempre criar constantes globais especificando o nome e tipo do valor. Evitando “valores mágicos”.
O ideal é que estas constantes sempre fiquem no topo do arquivo, após as importações.
Esse tipo de abordagem é ideal para adicionar configurações, como IDs de
// bad
setTimeout(() => {}, 300000);
// good
const FIVE_MINUTES_IN_MILLISECONDS: number = 300000;
setTimeout(() => {}, FIVE_MINUTES_IN_MILLISECONDS);
- Sempre adicionar elementos de texto dentro de um
<span>
;
<!-- errado -->
<button>{{ buttonText }}</button>
<!-- correto -->
<button>
<span>{{ buttonText }}</span>
</button>
-
Para Vue 2, utilizar abordagem do
vue-class-component
utilizando a dependêncianuxt-class-decorators
; -
Utilizar SCSS para styles;
-
Para classes dinamicas, criar getters para elementos que retornam a listagem de classes necessárias.
Por que? Adicionar classes dinamicas diretamente no template pode tornar o template confuso, retornar isso como uma computed deixa o código mais limpo e compreensível.
<!-- bad -->
<template>
<button
:class="{
isFalse: false,
isTrue: true,
}"
>
<span>Foo</span>
</button>
</template>
<!-- good -->
<template>
...
<button :class="buttonClassObject">
<span>Foo</span>
</button>
...
</template>
<script>
...
get buttonClassObject(): Record<string, boolean> {
return {
'isFalse': false,
'isTrue': true,
}
}
...
</script>
Os atributos de elementos e componentes devem ser distribuídos em ordem alfabética e agrupados na seguinte ordem:
- Definições:
v-is
; - Listagem:
v-for
; - Condicional:
v-if
,v-else
; - Modificadores de renderização:
v-once
,v-pre
; - Global:
id
; - Identificadores:
ref
,key
; - Slot:
v-slot
,slot
; - Modelo:
v-model
; - Diretivas:
v-other-directive
; - Outros atributos;
- Eventos:
@click
,v-on
; - Conteúdo:
v-text
,v-html
;
Utilizar a regra
vue/attributes-order
no Eslint para automatizar a ordenação;
Por convenção, sempre utilizar o prefixo on
em handlers para tratar eventos. É importante sempre criar um handler para tratar cada evento em elementos ou componentes (v-on
ou @
) ao invés de fazer a chamada da função principal diretamente no atributo de evento. A composição do nome do handler deve ser a seguinte: on<nome do elemento><nome do evento>
.
Em um cenário onde existe um elemento chamado RegisterUserButton e com um evento de click, o nome do handler fica da seguinte forma: onRegisterUserButtonClick
.
Por que? Enquanto componentes se tornam mais complexos, fica difícil dar manutenção em todos os locais do componente onde alguma função é chamada. Por isso, é sempre melhor ter handlers dedicados para eventos que vão chamar essa função.
<!-- bad -->
<button class="RegisterUserButton" @click="registerUser" />
<!-- good -->
<button class="RegisterUserButton" @click="onRegisterUserButtonClick" />
Exemplo de handler:
onRegisterUserButtonClick() {
this.registerUser();
}
registerUser() {
// ...
}
- Caso utilize declaração
@apply
do Tailwind, separar por tipo (ex: flex, grid, layout, texto, transição etc) ao invés de deixar todos estilos em uma só linha;
.selector {
@apply flex justify-center;
@apply absolute w-full;
}
- Sempre priorize a utilização unidades relativas, como
REM
,%
,vh
, vw, etc. PriorizarREM
ao invés deEM
para manter a consistência dos componentes. Utilize unidades absolutas apenas para situações pontuais estéticas que não alterem a acessibilidade ou responsividade;
// errado
.selector {
border-radius: 100px;
font-size: 16px;
height: 96px;
width: 600px;
}
// correto
.selector {
border-radius: 100px;
font-size: 1rem;
height: 6rem;
width: 100%;
}
- Sempre utilize cores em hexadecimal, utilizando os 6 dígitos e em lower case;
// errado
.selector {
background-color: #fafafa;
color: #eee;
}
// correto
.selector {
background-color: #fafafa;
color: #eeeeee;
}
Para ter mais consistência, é altamente recomendado manter ordem alfabética nas propriedades, pois previne duplicidade, melhora a organização e torna mais simples a visibilidade das propriedades pois facilita encontrar onde vão estar as propriedade. Para facilitar esse processo, é recomendado utilizar extensões do VS Code ou o próprio Prettier.
Para estilo de componentes, sempre utilizar o nome do componente no topo do documento:
.Feed {
&__wrapper {
//...
}
&__list {
//...
}
&__item {
//...
}
}
NUNCA utilize mais que 3 níveis aninhados! Se chegar nesse nível, provavelmente você deveria repensar a estrutura de classes, pois muitos níveis pode criar uma dependência muito forte com o HTML.
.Page {
.content {
.profile {
// PARE!
}
}
}
- Separar com espaço os blocos com mais de uma linha.
Por que? Para facilitar a leitura de templates.
<!-- errado -->
<div class="CodeBlock">
<p>Great</p>
</div>
<div class="CodeBlock">
<p>Fantastic</p>
<p>
<a href="#">Magic</a>
</p>
</div>
<!-- correto -->
<div class="CodeBlock">
<p>Fantastic</p>
</div>
<div class="CodeBlock">
<p>Fantastic</p>
<p>
<a href="#">Magic</a>
</p>
</div>
Os componentes de UI, que não possuem regras de negócios, devem ficar em /components
juntamente com sua respectiva story.
Exemplo:
├── components
│ ├── Button.vue
│ ├── Button.stories.js
Aqui ficarão os componentes com regra de negócio, aqueles que usarão os componentes de UI criados anteriormente. Features não precisam de story.
├── features
│ ├── InputJobSearch
│ │ ├── InputJobSearch.vue
│ │ ├── AnotherNecessaryFile.vue
https://github.com/ryanmcdermott/clean-code-javascript