Frontend Mobile

Tecnologias Utilizadas

O frontend mobile tem como base os seguintes frameworks JavaScript:

  • React Native, como alicerce da arquitetura

  • React Navigation, para navegação entre telas

  • Cloudsupport for React Native, que oferece componentes estruturais

  • Cloudsupport Storage for React Native, opcional, que oferece uma solução simplificada para banco de dados local

Os apps de frontend mobile utilizam como dependência as bibliotecas Node react-native-cloudsupport e react-native-cloudsupport-storage, que incluem módulos e componentes para aumentar produtividade dos desenvolvedores bem como auxiliar o cumprimento dos padrões e convenções de código definidos ao longo deste manual. Dessa forma o código-fonte dos projetos fica enxuto e o desenvolvedor poderá focar naquilo que lhe é útil: construir a interface gráfica.

Considere o exemplo cloudsupport-archetype-frontmobile como ponto de partida para novos projetos bem como para acompanhar a leitura deste manual e melhor assimilar os conceitos.

O aplicativo móvel Showcase (repositório cloudsupport-showcase-app) demonstra e documenta todos os componentes do Cloudsupport for React Native e Cloudsupport Storage for React Native. Utilize esse projeto como forma de aprendizado.

Funcionalidades da Arquitetura

São funcionalidades oferecidas pela biblioteca Cloudsupport for React Native:

  • Suite de mais de 50 componentes de UI, com supporte a tema customizável e funcionalidades para validações de formulário.

  • Módulo Events: barramento simples de eventos, em memória, que permite desacoplamento entre camadas da aplicação.

  • Módulo Networking: cliente REST com suporte a timeout e injetação de configurações padrões no fetch.

  • Módulo Async: métodos utéis para tratamento de Promises.

  • Módulo Lang: métodos utéis para tratamento de objetos, como cópia recursiva de propriedades.

Tem-se ainda a biblioteca Cloudsupport Storage for React Native, que oferece:

  • Uma API de armazenamento simples e de uso geral para persistir objetos JavaScript no formato JSON.

  • Suporte ao motor de banco SQLite (recomendado), até 5x mais rápido que SQLite Bridge.

  • Suporte (legado) ao motor de banco SQLite Bridge (nativo do dispositivo), porém Android limita em 4 MB por tupla.

  • Suporte (legado) ao motor de banco Realm (distribuição oficial do MongoDB), porém não recomendado, vez que o Mongo ocupa a thread de UI a cada operação.

Estrutura de Camadas

Os apps de frontend mobile possuem as seguintes camadas:

  • Camada de Apresentação (Screens), engloba os componentes que representam as telas.

  • Camada de Integração (Remotes), módulos que fazem a comunicação com serviços externos, i.e., que consome os webservices dos microsserviços de backend.

  • Camada de Negócio (Services), composta por funcionalidades de negócio providas no próprio frontend mobile.

A camada de negócio em aplicações de frontend mobile tende a ser pequena ou mesmo inexistir, pois as regras de negócio são providas tipicamente pelo backend. Ela existe, por exemplo, em aplicações que precisam oferecer funcionalidades de maneira offline utilizando o banco de dados local do dispositivo. Ressalta-se que as regras de negócio implementadas no frontend são passíveis de violação, ainda que envolva esforço técnico razoável. É importante que todas as regras sejam sempre validadas quando enviadas para o backend.

Estrutura de Arquivos

Os apps de frontend mobile possuem a seguinte estrutura de pastas e arquivos:

package.json
app.json
android/
ios/
app/

O arquivo package.json é o descritor Node do projeto. Nele é configurado o uso da biblioteca react-native-cloudsupport, opcionalmente react-native-cloudsupport-storage e frameworks associados, como o React Navigation.

O app.json contém configurações básicas, essencialmente “productionMode”, que indicará se a aplicação será executada em modo de teste ou modo de produção e “version”, que contém a versão comercial.

As configurações dos profiles de teste e de produção são definidas no arquivo app/globals/config.js.

As pastas android e ios contêm código-fonte e configurações nativos, que inclui ícones, versão para as lojas da Google e Apple e permissões.

A pasta app contém o código-fonte de aplicação, em JavaScript e React Native. A estrutura sugerida para esta pasta é:

Item Descrição
screens Camada de apresentanção; Contém os componentes de tela.
remotes Camada de funcionalidades remotas; Contém os módulos para comunicação com os microsserviços de backend.
services Camada de negócio; Contém os componentes que implementam regras de negócio, se for o caso.
components Contém componentes compartilhados para uso em telas.
navigation Contém a configuração do React Navigation.
util Contém módulos com funções estáticas utilitárias.
assets Contém resources, como figuras.

Neste manual, o termo “componente” usualmente faz referência a componente React. O termo “módulo” faz referência a qualquer módulo JavaScript, que pode exportar constantes, objetos, funções e componentes. Cabe destacar que um componente React é também uma função, porém destinada a uso na interface gráfica, conforme ciclo de vida do React.

Diretrizes Gerais

  • Utilizar preferencialmente JavaScript puro, em conformidade com ECMAScript 6 (ES6), podendo, se for necessidade do projeto, considerar TypeScript. Este manual incluirá diretrizes e exemplos sempre baseados em JavaScript.

  • Declarar componentes React na forma de componentes funcionais por meio da construção de funções JavaScript e uso dos Hooks. O React não recomenda a utilização de classes e orientação a objetos.

  • Preferir que funções e códigos assíncronos sejam implementados por meio de Promises em lugar da sintaxe async/await.

  • Evitar os operadores padrões de (des)igualdade == e != devido à complexidade da semântica IsLooselyEqual do JavaScript/TypeScript. Considerar os operadores estritos === ou !== e verificar explicitamente pelo undefined e pelo null sempre que for o caso.

    Os operadores padrões são desencorajados devido às suas “ambiguidades” lógicas, como esta exemplificada a seguir:

      a = ""
      b = null
    
      a == true  // retorna false
      b == true  // retorna false
      b == a     // retorna false
    

    Sobre loose equality: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#loose_equality_using

  • Evitar usar o operador || para efeito de “coalesce” ou valor padrão. Considerar ??, que é o verdadeiro Nullish coalescing operator.

    Exemplos:

      // retorna "default" se var1 for qualquer valor Falsy (exemplo: a="" ou a=0)
      var1 || "default" 
    
      // retorna "default" se e somente se var1 for null ou undefined
      var1 ?? "default" 
    
  • Evitar implicit coercion.

    Em vez de:

      if (a) {
          // ...
      }
    

    fazer:

      if (a !== null && a !== undefined) {
          // ...
      }
    
  • Atenção aos valores Falsy no JavaScript (convertidos para false em contextos Boolean): false, 0, -0, 0n, "", null, undefine e NaN.

    Evitar implicit coercion e os operadores ==, != e || (para fins de valor padrão) mitiga substancialmente os problemas causados pelos valores Falsy no JavaScript.

  • Não utilizar a sintaxe antiga de módulos do Node.js, o sistema CommonJS, a citar o comando require() e a variável global module.exports. Considere o padrão atual, com as diretivas import e export.

  • Identar o código preferencialmente com 4 espaços e evitar o caractere de tabulação \t.

Convenções de Nomes

São convenções de nomes recomendadas:

Elemento Regra
Pasta CamelCase iniciando em minúsculo.
Arquivo CamelCase iniciando em minúsculo.
Variáveis JavaScript CamelCase iniciando em minúsculo.
Constantes JavaScript Em maiúsculo, com termos separados por _.
Componentes React CamelCase iniciando em maiúsculo.
Funções JavaScript (excetuando Componentes React) CamelCase iniciando em minúsculo.

Próximos Passos

As seções Apresentação, Integração e Negócio detalham as camadas da aplicação. A seção Documentação da API contém a referência completa de todos os módulos e componentes da arquitetura.