Boas práticas para o front-end: Exemplos com o framework Angular - Parte I.

Boas práticas para o front-end: Exemplos com o framework Angular - Parte I.

Não é apenas responsabilidade dos desenvolvedores back-end se preocupar em ter uma arquitetura limpa, classes com responsabilidades únicas e bem definidas, métodos que sejam objetivos, código que seja legível entre outras práticas e princípios importantes (essas são apenas algumas da responsabilidades) para manter o bom estado do Software. Desenvolvedores que cuidam da interface do usuário também tem muito o que se preocupar, afinal o front-end é porta de entrada para seu cliente (usuário) conhecer seu produto. Manter a aplicação do lado do cliente organizada, aumenta a produtividade da equipe e facilita a adição de futuras funcionalidades que serão solicitadas. Vamos abordar, nessa primeira parte do artigo, boas práticas que você pode aplicar em projetos que está atuando. O framework base usado será o Angular, muitas práticas podem ser adaptadas para outros frameworks, outras são exclusivas do Angular.

Organize a estrutura das pastas

A primeira boa prática e que muitos acabam falhando depois de um certo tempo trabalhando no mesmo projeto é com a organização da estrutura de pastas. Parece algo bobo, mas é algo que deve ser levado a sério! Quando você ouve dizer que ter organização pode te poupar tempo, isso realmente é verdade.

Imagine que está procurando em seus arquivos pessoais (arquivos físicos) documentos importantes. Mas a pasta está com vários papeis inúteis e alguns você até joga no lixo, muitos documentos são importantes mas não deveriam estar juntos de outros que não passam de rabiscos. Depois encontra alguns que nem deveriam estar naquela pasta! Tudo está uma bagunça e você leva mais tempo do que imaginou buscando apenas um documento simples. E ao final até se atrasa para o compromisso que tinha hora marcada.

Isso ilustra bem o que pode acontecer com a organização dos seus arquivos e pastas do lado do front-end. Ter uma estrutura clara de pasta e onde está qual componente é importante pois facilita que a equipe trabalhe de maneira ágil. Essa organização também ajuda muito quem está iniciando em um projeto nesse front-end, pois se a pessoa tem experiencia ou não, ao ver algo organizado e com nomes claros (vamos falar sobre nomes) será mais fácil de trabalhar e adicionar novas features. Mas não adianta apenas pensar com cuidado na organização da estrutura das pastas, apenas quando o projeto está no inicio e ir abandonando essa boa pratica ao decorrer dos meses. Vamos fazer uma analogia mais uma vez:

Uma empresa contrata um novo colaborador para ser responsável por organizar e documentar arquivos físicos importantes de toda a empresa. No inicio ela/ele se preocupa muito em separar os arquivos por pastas com nomes (responsabilidades) bem claras. Então documentos do Financeiro, ficam na pasta do Financeiro e assim por diante. Ao passar dos meses novos documentos que devem ser arquivados da Contabilidade, mas a pessoa responsável está com tantas tarefas a cumprir que simplesmente coloca os documentos da contabilidade junto com os da área de tecnologia. Ela/Ele pode pensar; "Depois volto e organizo tudo isso". Que grande erro! O colaborador nunca consegue voltar e essas atitude começam a se tornar mais frequente durante as semanas seguintes. Quando entra um novo colaborador para auxiliar no processo de arquivar, ele começa a olhar as pastas e de primeira vista não tem nada de errado, todas as pastas estão nomeadas segundo sua área. Mas quando ele vai olhar os arquivos dentro dessas pastas vê uma bagunça de semanas ou meses, existem arquivos do RH que estão com do setor Financeiro!

Desenvolvedores responsáveis pelo front-end, também precisam tirar tempo para analisar e entender a melhor forma de organizar as pastas da aplicação em que está trabalhando. Por isso segue abaixo uma sugestão, que você pode se basear, para organizar projetos Angular (isso pode se aplicar a outros frameworks):

|-- app
     |-- modules
       |-- home
           |-- [+] components
           |-- [+] pages/views
           |-- home-routing.module.ts
           |-- home.module.ts
     |-- core
       |-- [+] authentication
       |-- [+] footer
       |-- [+] guards
       |-- [+] http
       |-- [+] interceptors
       |-- [+] mocks
       |-- [+] services
       |-- [+] header
       |-- core.module.ts
       |-- logger.service.ts
     |-- shared
          |-- [+] components
          |-- [+] directives
          |-- [+] pipes
          |-- [+] models
     |-- [+] configs
|-- assets
     |-- scss
          |-- [+] partials
          |-- _base.scss
          |-- styles.scss

Lembrando que é uma sugestão e existem outras formas de organizar. É importante entender que tudo isso pode variar muito dependendo do projeto que está trabalhando e nível de complexidade. Veja que na pasta modules existe apenas um modulo que foi criado, que é identificado pela pasta Home. Mas poderíamos ter outras pastas como Login entre outras. Como já disse, é apenas um exemplo para poder ajudar a ter uma visão melhor.

Evite sempre que possível lógicas no HTML

Esse é um detalhe importante! Mas o que é colocar lógica em nossas templates (no HTML)?

No Angular temos as famosas diretivas, que visam facilitar o desenvolvimento. E uma dessas diretivas que podemos usar é o ngIf. O que essa diretiva nos fornece? Colocar o ngIf em um elemento HTML, cria ou remove esse elemento com base na condição que você fornecer.

O ngIf tem o mesmo comportamento que a condicional If nas linguagens de programação que você já conhece. Veja o exemplo a seguir:

// Template
<p *ngIf="role === 'admin'"> Status: Admin </p>

// component
public ngOnInit (): void {
    this.role = 'admin';
}

O exemplo acima que estamos utilizando é bem simples e apenas para fins didáticos. Como pode observar estamos colocando lógica, uma condição boolean, na template (HTML). Inserir lógica na template não é recomendado, pois ao criar testes unitários terá que testar essa parte do seu código, mas será difícil fazer isso, pois toda a lógica está fixa na template. Veja como podemos corrigir:

// template
<p *ngIf="showStatus"> Status: Admin </p>

// component
public ngOnInit (): void {
    this.role = 'admin';
    this.showStatus = true;
}

Desta maneira fica fácil testar. Mas veja a imagem abaixo com outro exemplo:

Boas-praticas.png

Note que existe nessa template uma multiplicação sendo realizada, total * 100. Nesse caso a responsabilidade de trazer o valor dessa conta está sendo atribuída diretamente para template. Isso deve alertar o desenvolvedor front-end, a legibilidade, manutenção e reutilização do código a medida que a aplicação cresce pode ser prejudica. Os modelos HTML não são feitos para escrever lógica de negócios.

Veja agora esse código aplicando as boas práticas:

Boas-praticas-100.png

Agora temos uma propriedade getter que nomeamos de multiplicarNumeros() e com ele podemos usar como propriedade no modelo HTML. E assim a lógica fica onde deve estar, no componente! Nunca vamos ter que nos preocupar em olhar o HTML procurando por regras.

Veja mais um exemplo clássico de como evitar a poluir a Template com lógica:

111.png

O ngClass contém uma lógica extensa na template, o que pode facilmente levar alguém a cometer um erro. Podemos simplesmente colocar isso em um método:

1112.png

Agora temos apenas um bom modelo e podemos até testar facilmente se nossas validações funcionam corretamente com testes de unidade, sem mergulhar na visualização.

Busque usar em seus componentes seletores de elemento.

No framework Angular, temos dentro do componente um atributo especial que se chama selector. Um seletor é usado para identificar cada componente exclusivamente na árvore de componentes e também define como o componente atual é representado no HTML (DOM). Existem duas formas de se passar o selector, a primeira que não é recomendada está no código abaixo:

Boas-praticas-200.png

E por que não devemos passar ele dentro de colchetes? É porque o framework entende isso como sendo um atributo, veja como fica no HTML:

Boas-praticas-300.png

Estamos declarando uma div e dentro dela nosso componente. E o que nosso componente pode possuir? Muitas coisas, um componente pode fazer referencia a templateUrl e ao styleUrls. Então quando você olha pela primeira vez, pode pensar que appComponent não se trata de todo um componente! Vamos utilizar agora o selector da maneira correta, observe que vamos alterar o nome dele também:

Boas-praticas-400.png

Agora veja o resultado no HTML:

Boas-praticas-500.png

Bem melhor! Sempre que você e outro desenvolvedor analisarem o HTML e notarem um elemento declarado nessa sintaxe, já sabe que se trata de um componente! São detalhes que fazem muita diferença!

Se estiver usando TypeScript, evite o uso de Any

O TypeScript nos ajuda muito a definir objetos e atribuir tipos a variáveis e funções. Usar o Any seria uma maneira muito ruim ao escrever um código pois basicamente desabilita todas as verificações de tipos, o que evita erros na compilação do TypeScript, esses erros que podem surgir nos ajudam a entender se estamos ou não escrevendo nosso código corretamente. Veja mais um exemplo:

getUserAddress() {
    return this.http.get<any>(this.baseUrl + 'account/address');
  }

O método nos ajuda a entender que queremos buscar o endereço do usuário. Mas tem um detalhe. Veja que temos <any>. E qual o problema?

Imagine que você precise saber o que a API vai te retornar nesse endereço. Normalmente temos, CEP, Rua, Bairro, Cidade, Estado. Parece obvio não é mesmo? Mas nem sempre é tão obvio. Imagine se o serviço no response, retorna outros campos como logradouro, numero da residência, tipo de moradia (casa ou apartamento) ou retornar também o País. Por isso é importante definir tipos, além disso, facilita o trabalho de outros desenvolvedores que irão atuar no projeto.

// address.ts
export interface IAddress {
    firstName: string;
    lastName: string;
    street: string;
    city: string;
    state: string;
    zipcode: string;
}
----------------------------
// account.service.ts
getUserAddress() {
    return this.http.get<IAddress>(this.baseUrl + 'account/address');
  }

Agora sabemos exatamente o que esperamos receber.

É importante destacar que em determinados casos vamos precisar usar o any, mas são exceções que podemos comentar em outro artigo.

Cuidado com bibliotecas de terceiros!

Sabemos que existem muitas libs que facilitam e ajudam quando estamos desenvolvendo. Mas é importante escolher bem qual vai utilizar, principalmente se existe uma comunidade disposta em manter tal lib mesmo com as atualizações do framework. Principalmente as mais complexas e que contém dezenas de recursos. Existem comunidades fortes e que constantemente estão atualizando a biblioteca. Mas se o seu projeto tem diversas dependências de pacotes de terceiros é bom começar a ficar atento e rever se realmente precisa de todas. É importante entender que os desenvolvedores que mantém a lib podem abandonar a manutenção por algum motivo. Isso já aconteceu com inúmeras bibliotecas incluindo a famosa Moment.js. Por isso analise bem junto com a equipe de desenvolvimento se realmente vale a pena introduzir uma biblioteca para auxiliar no desenvolvimento de alguma funcionalidade. Pois mais tarde podem ter um retrabalho que poderia ser evitado.

Conclusão

As responsabilidades que os desenvolvedores Front-end tem em mãos também são grandes. Vimos algumas práticas que podem e devem ser utilizadas quando apropriadas. Por isso cabe também ter bom senso em saber que existem situações que impossibilitam colocar os tópicos que abordamos em prática. Mas sempre considere e tente desenvolver sua aplicação da maneira mais organizada e limpa possível. Isso vai facilitar não apenas o seu trabalho mas de toda a equipe! Existem muitos outros conceitos importantes, que estão listados como boas práticas, que podemos aplicar no front-end. No próximo artigo veremos mais!

Fico por aqui neste post. Obrigado por ler. Até! 😄 🚀