Guia de estilo

Para melhorar a legibilidade e a estética dos códigos fontes, deve-se seguir um guia de estilo adequado para cada linguagem de programação utilizada no desenvolvimento da plataforma.

O guia de estilo adotado busca seguir convenções modernas que tenham um racional que favoreça a legibilidade do código fonte. No entanto, deve-se levar em consideração que a plataforma possui uma base de códigos extensa que foi desenvolvida ao longo dos anos com convenções distintas das atuais. Algumas decisões do passado vão de encontro às recomendações dos guias mais recentes. Quando possível, deve-se atualizar o guia de estilo adotado na plataforma para as melhores práticas. No entanto, em alguns casos específicos, optou-se por manter a definição legada por uma questão de consistência, sempre quando ela não gera prejuízos significativos à legibilidade do código.

Preferencialmente, a adequação ao estilo deve ser automatizada por ferramentas como o editorconfig e o prettier. Segue a configuração recomendada do .editorconfig:

root = true

[*]
indent_style = space
insert_final_newline = true
max_line_length = 100
charset = utf-8

[*.{js,css,ts}]
indent_size = 2
continuation_indent_size = 4
trim_trailing_whitespace = true
quote_type = single

[*.{ts}]
quote_type = double

[*.md]
indent_size = 4

JavaScript

São adotadas as convenções sugeridas em Google JavaScript Style Guide, com as seguintes considerações:

  • Strings devem ser preferencialmente iniciadas com aspas simples. O uso de aspas duplas em expressões SQL é uma exceção comum devido ao uso de aspas simples nas strings literais do SQL.
  • Não devem ser utilizadas strings com mais de uma linha. Elas devem ser concatenadas pelo operador “+” ou deve ser utilizado o recurso de template literals quando disponível.
  • Atributos HTML textuais devem utilizar aspas duplas.
  • Em um protótipo ou classe, as propriedades devem ser preferencialmente declaradas antes dos métodos.
  • Parâmetros obrigatórios devem ser definidos antes dos parâmetros opcionais.
  • Não devem ser construídas instâncias de String, Number e Boolean. Sempre devem ser utilizadas as versões primitivas desses objetos.
  • Não devem ser utilizadas chaves literais nos códigos. Elas devem ser declaradas em constantes ou coleções de chaves, preferencialmente no diretório /keys.
  • Por convenção, os nomes dos arquivos devem seguir a mesma convenção de nome adotada para o tipo exportado pelo módulo. Módulos que exportem construtores, classes, singletons, biblioteca de funções ou objeto literal devem adotar o PascalCase. Módulos que exportem funções devem adotar o camelCase.
  • Limite de 120 colunas por linha. Deve-se buscar evitar linhas com mais de 100 colunas com o objetivo de tornar mais produtivas as mesclagens e revisões de códigos.

Typescript

Deve ser adotada a formatação automática do prettier.

SQL

São adotadas as convenções sugeridas em SQL Style Guide, com as seguintes adequações ao modelo de dados do sistema:

  • Datas são gravadas em um campo do tipo DATE sem a sua componente de hora. A hora deve ser gravada em uma coluna separada do tipo varchar(8).
  • Utilize apenas os tipos de dados normalizados pelo Engine em todos os SGBDs suportados.
  • Deve ser utilizada a sintaxe padrão SQL, tendo atenção em utilizar apenas os recursos comuns e suportados por todos os SGBDs compatíveis com o Engine. No manual Banco de dados há uma relação de funcionalidades conhecidas por serem compatíveis com todos os SGBDs. Também há uma relação daquelas que devem ser evitadas, por não serem totalmente suportadas.
  • Os registros das tabelas devem ser modificados pelos métodos Database.prototype.applyUpdates e DataSet.prototype.applyUpdates. Jamais utilize os comandos DELETE, INSERT e UPDATE para modificar os dados do sistema.
  • Nomes de tabelas devem ser no singular.
  • Nomes das colunas são padronizados em camelCase para preservar a consistência com o modelo de dados histórico do sistema.
  • Para evitar colisões de identificadores, os nomes das colunas e tabelas criadas pela plataforma são prefixados com i. Colunas criadas em customizações são prefixadas com z.

Categorias de log

É recomendado que códigos distribuídos em pacotes ou produtos do sistema utilizem a função Logger.getLogger(categoryName) para criar categorias de log hierárquicas que permitam redirecionar ou modificar a prioridade dos logs gerados por um pacote ou produto específico do sistema.

Para esse fim, as bibliotecas da plataforma adotam as seguintes convenções para nomear as categorias de log:

  • Módulos JavaScript: adota-se o padrão “package.ModuleName” em pacotes especializados em uma API ou domínio de negócio, como o “@nginstack/jsunit”. Em pacotes que envolvam APIs ou domínios de negócio distintos, como o “@nginstack/engine”, pode ser opcionalmente indicado o subdomínio na categoria: “package.subdomain.ModuleName”. Esse padrão também se aplicada aos módulos que exportam funções ou configurações. Exemplos: “jsunit.TestRunner”, “engine.http.RealmConfig” e “devops.restartEngineServers”.
  • Scripts de pacotes: scripts JavaScripts de pacotes criados para serem executados via executeScript ou ScriptRunner adotam o mesmo padrão das funções declaradas em módulos. Nesses casos, o nome do script deve ser um identificador JavaScript válido em camelCase. Exemplo: “engine.scheduledSendEmail”.
  • Scripts globais, configurações, processos e relatórios: códigos que não tenham um identificador JavaScript válido associado a eles utilizam apenas o nome do pacote ou produto do sistema como identificador da categoria. Exemplo: “admin”.

Em algumas classes, a identificação das instâncias pode ser útil para a análise dos logs. Nesses casos, utiliza-se como sufixo o identificador da instância. Exemplos: “ngin.dbcache.DatabaseName” e “web-framework.Grid.GridName”.

A convenção adotada pela plataforma não é obrigatória e produtos desenvolvidos sobre ela podem adotar outras regras que façam mais sentido na aplicação desenvolvida.

Observação: os logs gerados pelo executável “engine” adotam o prefixo “ngin” por motivos históricos e para diferenciar esses logs daqueles gerados pelo pacote JavaScript “@nginstack/engine”.

Documentação

JSDoc

Todas as APIs públicas devem ser documentadas no padrão JSDoc. APIs privadas frequentemente utilizadas também devem ser documentadas a fim de gerar informações para o recurso de code completion das IDEs.

O arquivo publicModules.js nos repositórios de código deve incluir todos os arquivos contendo APIs públicas que terão a sua documentação exportada.

A tag @author é utilizada exclusivamente para atribuir a autoria de códigos de terceiros embarcados ou adaptados na plataforma. Ela nunca deve ser utilizada para indicar profissionais da própria equipe de desenvolvimento.

Completion proposal

As APIs públicas precisam ser publicadas na configuração do Completion Proposal da IDE do Engine. A configuração fica localizada em /Configuração/Completion Proposal.

Manuais ou guias

Sempre que possível deve ser utilizado o formato Markdown. Os arquivos devem ser formatados para possuir 120 colunas ou menos, simplificando a revisão da documentação. As exceções são links ou trechos de código fonte, que não podem ser quebrados em várias linhas.

Nos arquivos Markdown, é empregada uma indentação de 4 caracteres para simplificar a criação de blocos.