# Padrões de código

# Índice

### **Resumo**

O livro "Padrões de Código", contém todas as informações referentes à padronização e boas práticas utilizadas na implementação e desenvolvimento dos sistemas SS. Organizado por capítulos e sempre atualizado, este livro é de suma importância para a equipe de desenvolvimento, pois apresenta as diretrizes à serem seguidas durante a manutenção do código. Logo abaixo, serão apresentados os capítulos e uma breve descrição do que é tratado em suas respectivas páginas.

### **Sumário**

#### [**Delphi**](https://wiki.supersoft.com.br/books/padroes-de-codigo/chapter/delphi)

[**Nomenclatura Geral**](https://wiki.supersoft.com.br/books/padroes-de-codigo/page/nomenclatura-geral)

Padrão de nomenclaturas para componentes, variáveis, constantes, métodos, units e classes com exemplos ilustrativos e explicações.

**[Espaçamento](https://wiki.supersoft.com.br/books/padroes-de-codigo/page/espacamento)**

Padronização de espaçamento para declaração de variáveis, atribuições, declaração de métodos, matrizes, operadores binários, operadores unários, subrotinas e uses.

[**Palavras reservadas**](https://wiki.supersoft.com.br/books/padroes-de-codigo/page/palavras-reservadas)

#### [**SQL**](https://wiki.supersoft.com.br/books/padroes-de-codigo/chapter/sql)

[**Considerações Iniciais**](https://wiki.supersoft.com.br/books/padroes-de-codigo/page/consideracoes-iniciais)

Definição do padrão para indentação de cláusulas SQL, palavras reservadas , tabelas, campos e parâmetros.

[**Exemplo: UPDATE**](https://wiki.supersoft.com.br/books/padroes-de-codigo/page/exemplo-update)

Exemplo de cláusula de UPDATE.

[**Exemplo: DELETE**](https://wiki.supersoft.com.br/books/padroes-de-codigo/page/exemplo-delete)

Exemplo de cláusula de DELETE.

[**Exemplo: CASE**](https://wiki.supersoft.com.br/books/padroes-de-codigo/page/exemplo-case)

Exemplos de cláusulas com CASE, tanto com expressão quanto sem expressão no CASE.

[**Palavras reservadas**](https://wiki.supersoft.com.br/books/padroes-de-codigo/page/palavras-reservadas-e2c)

#### [**Boas Práticas**](https://wiki.supersoft.com.br/books/padroes-de-codigo/chapter/boas-praticas)

**[Versionamento](https://wiki.supersoft.com.br/books/padroes-de-codigo/page/versionamento)**

Definição das diretrizes para mensagens de versionamento. Mensagem modelo e exemplo de mensagem em criação de branch, commit de alterações e atualização de branch.

[**Documentação Interna**](https://wiki.supersoft.com.br/books/padroes-de-codigo/page/documentacao-interna)

Exemplos de comentários e como devem ser utilizados.

[**Código Limpo**](https://wiki.supersoft.com.br/books/padroes-de-codigo/page/codigo-limpo)

Definição de código limpo e *bad smells.* Exemplos de *bad smells* comuns e possíveis correções.

# Delphi

Capítulo destinado aos padrões como nomenclatura, indentação entre outros, usados em Delphi.

# Nomenclatura Geral

### **Nomenclatura**

##### **Componentes**

<span style="font-weight: 400;">Os componentes possuem seus prefixos utilizando letras que remetem ao nome completo da classe do componente. </span><span style="font-weight: 400;">Componentes herdados dos componentes listados e sem conexão ao banco de dados devem possuir o mesmo prefixo do componente principal, com exceção dos componentes visuais com conexão ao banco de dados, que utilizam o prefixo “DB“ seguido do padrão identificado logo abaixo. Exemplo: DBED\_Nome é um componente da classe TDBEdit, responsável pela representação de um nome.</span>

<span style="font-weight: 400;">Seguem alguns exemplos de prefixos padrões utilizados:</span>

<table border="1" id="bkmrk-ed_%3A-tedit%3B%E2%A0-ts_%3A-tta" style="border-collapse: collapse; width: 53.7037%; height: 476.75px;"><tbody><tr style="height: 29.7969px;"><td style="width: 27.1031%; height: 29.7969px;"><span style="font-weight: 400;">ED\_: TEdit; </span></td><td style="width: 26.6006%; height: 29.7969px;"><span style="font-weight: 400;">TS\_: TTabSheet;</span></td></tr><tr style="height: 29.7969px;"><td style="width: 27.1031%; height: 29.7969px;"><span style="font-weight: 400;">PN\_: TPanel;</span></td><td style="width: 26.6006%; height: 29.7969px;"><span style="font-weight: 400;">RB\_: TRadioButton;</span></td></tr><tr style="height: 29.7969px;"><td style="width: 27.1031%; height: 29.7969px;"><span style="font-weight: 400;">GB\_: TGroupBox;</span></td><td style="width: 26.6006%; height: 29.7969px;"><span style="font-weight: 400;">OD\_: TOpenDialog;</span></td></tr><tr style="height: 29.7969px;"><td style="width: 27.1031%; height: 29.7969px;"><span style="font-weight: 400;">LB\_: TLabel;</span></td><td style="width: 26.6006%; height: 29.7969px;"><span style="font-weight: 400;">SD\_: TSaveDialog;</span></td></tr><tr style="height: 29.7969px;"><td style="width: 27.1031%; height: 29.7969px;"><span style="font-weight: 400;">MM\_: TMemo;</span></td><td style="width: 26.6006%; height: 29.7969px;"><span style="font-weight: 400;">Q\_: TQuery, TFDQuery;</span></td></tr><tr style="height: 29.7969px;"><td style="width: 27.1031%; height: 29.7969px;"><span style="font-weight: 400;">BT\_: TButton (Botões num geral);</span></td><td style="width: 26.6006%; height: 29.7969px;"><span style="font-weight: 400;">DS\_: TDataSource;</span></td></tr><tr style="height: 29.7969px;"><td style="width: 27.1031%; height: 29.7969px;"><span style="font-weight: 400;">CK\_: TCheckBox;</span></td><td style="width: 26.6006%; height: 29.7969px;"><span style="font-weight: 400;">CDS\_: TClientDataSet;</span></td></tr><tr style="height: 29.7969px;"><td style="width: 27.1031%; height: 29.7969px;"><span style="font-weight: 400;">CB\_: TComboBox;</span></td><td style="width: 26.6006%; height: 29.7969px;"><span style="font-weight: 400;">DSP\_: TDataSetProvider;</span></td></tr><tr style="height: 29.7969px;"><td style="width: 27.1031%; height: 29.7969px;"><span style="font-weight: 400;">LT\_: TListBox;</span></td><td style="width: 26.6006%; height: 29.7969px;"><span style="font-weight: 400;">T\_: TTable;</span></td></tr><tr style="height: 29.7969px;"><td style="width: 27.1031%; height: 29.7969px;"><span style="font-weight: 400;">RG\_: TRadioGroup;</span></td><td style="width: 26.6006%; height: 29.7969px;"><span style="font-weight: 400;">FR\_: TFrxReport;</span></td></tr><tr style="height: 29.7969px;"><td style="width: 27.1031%; height: 29.7969px;"><span style="font-weight: 400;">PC\_: TPageControl;</span></td><td style="width: 26.6006%; height: 29.7969px;"><span style="font-weight: 400;">FDS\_: TFrxDBDataSet;</span></td></tr><tr style="height: 29.7969px;"><td style="width: 27.1031%; height: 29.7969px;"><span style="font-weight: 400;">TB\_: TToolBar;</span></td><td style="width: 26.6006%; height: 29.7969px;"><span style="font-weight: 400;">RV\_: TRvProject;</span></td></tr><tr style="height: 29.7969px;"><td style="width: 27.1031%; height: 29.7969px;"><span style="font-weight: 400;">GD\_: TGrid;</span></td><td style="width: 26.6006%; height: 29.7969px;"><span style="font-weight: 400;">DSC\_: TRvDataSetConnection;</span></td></tr><tr style="height: 29.7969px;"><td style="width: 27.1031%; height: 29.7969px;"><span style="font-weight: 400;">MI\_: TMenuItem;</span></td><td style="width: 26.6006%; height: 29.7969px;"><span style="font-weight: 400;">SH\_: TShape</span></td></tr><tr style="height: 29.7969px;"><td style="width: 27.1031%; height: 29.7969px;"><span style="font-weight: 400;">IM\_: TImage</span></td><td style="width: 26.6006%; height: 29.7969px;"><span style="font-weight: 400;">TM\_: TTimer </span></td></tr><tr style="height: 29.7969px;"><td style="width: 27.1031%; height: 29.7969px;"><span style="font-weight: 400;">NB\_: TNotebook</span></td><td style="width: 26.6006%; height: 29.7969px;"><span style="font-weight: 400;">Page: TPage</span></td></tr></tbody></table>

<span style="font-weight: 400;">Exemplo de componentes visuais com conexão ao banco de dados:  
</span>

<table border="1" id="bkmrk-dbed_%3A-tdbedit%3B-dbgd" style="border-collapse: collapse; width: 39.5062%; height: 58px;"><tbody><tr style="height: 29px;"><td style="width: 19.5062%; height: 29px;"><span style="font-weight: 400;">DBED\_: TDBEdit;</span></td><td style="width: 20%; height: 29px;"><span style="font-weight: 400;">DBGD\_: TDBGrid;</span></td></tr><tr style="height: 29px;"><td style="width: 19.5062%; height: 29px;"><span style="font-weight: 400;">DBCK\_: TDBCheckBox;</span></td><td style="width: 20%; height: 29px;"><span style="font-weight: 400;">DBRG\_: TDRadioGroup;</span></td></tr></tbody></table>

##### **Variáveis**

O nome da variável deve descrever de maneira clara e sem abreviações a função da variável. Utilizar a notação PascalCase para o nome da variável.  
As variáveis podem ter ainda um prefixo para adicionar mais informações sobre sua origem.  
Para **variáveis locais** utiliza-se o prefixo **‘L’**, para **argumentos (Parâmetros) de métodos** utiliza-se o **'A’**. Para **atributos (Field)** de classes utiliza-se o **‘F’**.

```PASCAL
type
  TPessoa = class
    protected
      FNome: String; // Campo nome da classe Pessoa. Prefixo F
    public
      constructor Create(ANome: String); // Argumento do método. Prefixo A.
  end;
  
implementation

constructor TPessoa.Create(ANome: String);
var
  LNome: String; // Variável local. Prefixo L
begin

end;
```

##### **Constantes** 

Para nomes de constantes, o padrão utilizado é:

```PASCAL
const
  NOME_DA_CONSTANTE_1 = 0;
  NOME_DA_CONSTANTE_2 = False;
  NOME_DA_CONSTANTE_3 = ‘Teste’;
```

O tipo da constante é deduzido através do valor dessa constante no momento da declaração. Porém, é possível declarar explicitamente um tipo para as constantes, e em alguns casos, como o de arrays, é necessário que esse tipo seja declarado.

```PASCAL
const
  NOME_DA_CONSTANTE_4: Double = 10;
  NOME_DA_CONSTANTE_5: array [1..2] of String = (‘a’, ‘b’);
```

##### **Métodos** 

Assim como o nome das variáveis, o nome do método deve seguir o mesmo modelo, com nomes que descrevem a função do método, utilizando também a notação PascalCase.  
Ao editar um método, é importante manter sua função original, caso sua funcionalidade seja alterada, deve-se refatorar o seu nome para que permaneça fiel ao seu comportamento.

**Exemplo 1: Criar um método que faça a confirmação de um rotina de gravação. Sem retorno e sem argumentos.**

```PASCAL
procedure ConfirmarGravacao();
```

**Exemplo 2: Criar um método que faça o cálculo da área de um retângulo. Seu retorno será um inteiro, esse método terá ainda dois argumentos, altura e largura.**

```PASCAL
function CalcularArea(AAltura, ALargura: Integer): Integer;
```

##### **Units**

As units padrões utilizadas anteriormente para as entidades eram nomeadas acrescentando 1, 2, 3 ou 4. Para facilitar o entendimento na leitura do nome da unit, elas passam a ser utilizadas no singular, seguido do nome de sua funcionalidade. Por exemplo, a entidade “Empresa” passa a ser utilizada como:  
● Empresas1: Empresa.Manutencao;  
● Empresas2: Empresa.Cadastro;  
● Empresas3: Empresa.Pesquisa;  
● Empresas4: Empresa.DataModule;  
Para units que tenham outra função que não se enquadrem nessas descritas anteriormente, o padrão é utilizar o nome da entidade seguido da descrição de sua função.  
Exemplo: Empresa.Copiar.

##### **Classes**

O padrão Delphi para nome de classes aconselha que ela inicie com o prefixo T (*Type*). É aconselhável que o nome dessas classes sejam descritivos quanto à sua entidade, função e/ou tipo. Por exemplo, uma classe que define a entidade produtos poderia ter o nome *TProdutoModelo*, enquanto o formulário para importação desses produtos poderia ser *TProdutoImportacaoFormulario.*

# Espaçamento

##### **Regras para Formatação Horizontal** 

**Tabulação**: Utilizar 2 caracteres (espaços) ao invés da tabulação.

Para manter a estrutura do código de modo que sua leitura seja fácil, o número máximo de caracteres por linha é **130**. Caso a expressão ultrapasse esse comprimento, a linha deve ser quebrada segundo essas regras:

1. A linha tem comparações? `('a = b', 'a <> b', 'a <= b', 'a >= b', 'a < b' ou 'a > b')`
    1. Envolver cada comparação com parênteses.
2. A linha contem negação? `('not')`
    1. Envolver cada negação com um parênteses.
3. A linha contém operadores lógicos? `('and' e 'or')`
    1. Envolver cada sequência de `'and'` com um parênteses;
    2. Envolver cada sequência de `'or'` com um parênteses.
4. A linha é uma atribuição? `(':=')`
    1. Adicionar uma quebra de linha após o sinal de atribuição `(':=')`, alinhar a nova linha com a linha original e indentar em um nível (2 espaços);
    2. Caso o código resultante não tenha ultrapassado a linha das 130 colunas, processo pode ser interrompido;
    3. Caso a atribuição seja uma String, ela pode ser quebrada em uma ou mais concatenações. Essas podem ser quebradas e alinhadas com a linha original, adicionando um nível de indentação;
    4. Caso a atribuição seja uma comparação (Não considerar comparações dentro de métodos aninhados), adicionar uma quebra de linha após o sinal de comparação `('=', '<>', '<=', '>=', '<' ou '>')`, e alinhar a nova linha com o primeiro operando.
5. A linha tem um 'if'? 
    1. Caso a condição do if não tenha um parênteses envolvendo a condição inteira, envolvê-la com um;
    2. Adicionar uma quebra de linha após cada operador `'and'` ou `'or'`;
    3. Após cada quebra de linha, alinhar a nova linha com o parênteses onde ela está contida e adicionar um espaço;
    4. Caso o código resultante não tenha ultrapassado a linha das 1 colunas, processo pode ser interrompido;
    5. Caso alguma das condições do if tenha uma comparação (Não considerar comparações dentro de métodos aninhados), adicionar uma quebra de linha após o sinal de comparação `('=', '<>', '<=', '>=', '<'` ou `'>')`, e alinhar a nova linha com o primeiro operando.
    6. Caso o código resultante não tenha ultrapassado a linha das 130 colunas, processo pode ser interrompido.
6. A linha contém métodos aninhados? 
    1. Aplicar essa regra do métodos mais externo para o mais interno;
    2. Adicionar uma quebra de linha exatamente antes do início do método aninhado;
    3. Alinhar a nova linha com o método onde ela está contida (Caso o método tenha uma negação (not), alinhar com o início dessa negação), adicionar ainda um nível de indentação (2 espaços);
    4. Caso o código resultante não tenha ultrapassado a linha das 130 colunas, processo pode ser interrompido.
7. A linha contém parâmetros? 
    1. Ao realizar a quebra de linha de um parâmetro, ele deve estar indentado um nível (2 espaços) em relação ao nível do método proprietário do parâmetro (caso o método proprietário tenha uma negação (not), alinhar com o início dessa negação);
    2. Caso o código resultante não tenha ultrapassado a linha das 130 colunas, processo pode ser interrompido.
8. Após todas essas etapas a linha ainda ultrapassa a marca de 130 colunas? 
    1. Caso ainda assim, a linha ultrapasse a marca de 130 colunas então deve-se verificar a existência de pontos na expressão (“.”), sendo que, ao realizar esse tipo de quebra de linha, o ponto deve ficar com a expressão na linha inferior, indentado em um nível em relação ao início da expressão.

Observação: Algumas vezes, quando uma linha ultrapassa as 130 colunas, é um sinal de que esse trecho pode ser refatorado. O programador pode então refatorar, se julgar que é necessário ou melhor.

##### **Declaração de variáveis** 

<p class="callout success">**Correto**</p>

```PASCAL
var
  LTeste: Integer;
```

<p class="callout danger">**Incorreto**</p>

```PASCAL
var
  LTeste : Integer;
  LTeste :Integer;
```

##### **Atribuições**

<p class="callout success">**Correto**</p>

```PASCAL
LTeste := 15;
```

<p class="callout danger">**Incorreto**</p>

```PASCAL
LTeste:=15; 
LTeste:= 15; 
LTeste :=15; 
```

##### **Métodos**

<p class="callout success">**Correto**</p>

```PASCAL
procedure Ex(AParametro: Integer); 
procedure Ex(AParametro1, AParametro2: Integer); 
procedure Ex(AParametro: Integer; AParametro2: String); 
```

<p class="callout danger">**Incorreto**</p>

```PASCAL
procedure Ex (AParametro1: Integer); 
procedure Ex( AParametro: Integer); 
procedure Ex(AParametro: Integer ); 
procedure Ex(AParametro1,AParametro2: Integer); 
procedure Ex(AParametro1 , AParametro2: Integer); 
procedure Ex(AParametro: Integer;AParametro2: String); 
procedure Ex(AParametro: Integer ; AParametro2: String); 
```

##### **Matrizes**

<p class="callout success">**Correto**</p>

```PASCAL
LTeste := LMatriz[0];
```

<p class="callout danger">**Incorreto**</p>

```PASCAL
LTeste := LMatriz[ 0]; 
LTeste := LMatriz[0 ]; 
LTeste := LMatriz[ 0 ];
```

##### **Operadores binários**

<p class="callout success">**Correto**</p>

```PASCAL
LTeste := 1 + 1;
```

<p class="callout danger">**Incorreto**</p>

```PASCAL
LTeste := 1+1; 
LTeste := 1 +1; 
LTeste := 1+ 1; 
```

##### **Operadores unários**

<p class="callout success">**Correto**</p>

```PASCAL
LTeste := -1;
```

<p class="callout danger">**Incorreto**</p>

```PASCAL
LTeste := - 1; 
LTeste :=-1; 
```

##### **Subrotinas**

<p class="callout success">**Correto**</p>

```PASCAL
function MeuMetodo: String;

    procedure SubMetodo;
    begin
      //Código SubMetodo
    end;
    
begin
  //Código MeuMetodo
end;
```

<p class="callout danger">Incorreto</p>

```PASCAL
function MeuMetodo: String;

procedure SubMetodo;
begin
  //Código SubMetodo
end;
begin
  //Código MeuMetodo
end;
```

```PASCAL
function MeuMetodo: String;

  procedure SubMetodo;
  begin
    //Código SubMetodo
  end;
  
begin
  //Código MeuMetodo
end;
```

##### **Uses**

<p class="callout info">**Dica:** Para identificar se uma unit deve ser declarada na uses superior ou inferior, realize o seguinte teste: Copie a unit para a uses inferior e compile o programa, caso o processo de compilação não apresente erros, a unit deve permanecer na uses inferior. Caso contrário, mova a unit para a uses superior.</p>

**<span style="font-weight: 400;">No primeiro “uses“ (logo abaixo de “interface”) declarar as units no .dfm e nas assinaturas dos métodos.</span>**

```Pascal
interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs;
```

<span style="font-weight: 400;">No segundo “uses“ (logo abaixo de “implementation”) declarar as units usadas na implementação do código.</span>

```Pascal
implementation

uses
  uExisteTabela,
  uProcuraRegistro,
  uGravaSistema;
```

<span style="font-weight: 400;">A fim de evitar conflito em Merge devido a alterações em mesma linha, cada Unit deve ser declarada em linha diferente. Esse erro costuma acontecer principalmente quando há refatoração ou exclusão de algum componente visual.</span>

<p class="callout success"><span style="font-weight: 400;">Correto</span></p>

```Pascal
implementation

uses
  uExisteTabela,
  uProcuraRegistro,
  uGravaSistema;
```

<p class="callout danger">Incorreto</p>

```Pascal
implementation

uses
  uExisteTabela, uProcuraRegistro, uGravaSistema;
```

##### **Arrays** 

Ao indentar elementos de um array, eles devem seguir a lógica de ordenação de parênteses. Por não estarem em níveis diferentes de indentação, devem ser indentados da seguinte forma

<p class="callout success">Correto</p>

```Pascal
TClasse.Metodo(
  Parametro1,
  Parametro2,
  [Item1, Item2, Item3
   Item4, Item5, Item6]);
```

<p class="callout danger">Incorreto</p>

```Pascal
TClasse.Metodo(
  Parametro1,
  Parametro2,
  [Item1, Item2, Item3
     Item4, Item5, Item6]);
```

```
TClasse.Metodo(
  Parametro1,
  Parametro2,
  [Item1, Item2, Item3
  Item4, Item5, Item6]);
```

##### **IN em tratamento de condições**

<p class="callout success">Correto</p>

```PASCAL
Result :=
  (Self in 
     [cdfIncidenciadecisaojudicial,
      cdfIncidenciaDecisaoJudicial13Sal,
      cdfIncidenciaDecisaoJudicialAvisoPrevioIndenizado]);
```

<p class="callout danger">Incorreto</p>

```PASCAL
Result :=
  Self in [cdfIncidenciadecisaojudicial,
           cdfIncidenciaDecisaoJudicial13Sal,
           cdfIncidenciaDecisaoJudicialAvisoPrevioIndenizado];
```

```PASCAL
Result := (Self in [cdfIncidenciadecisaojudicial,
                    cdfIncidenciaDecisaoJudicial13Sal,
                    cdfIncidenciaDecisaoJudicialAvisoPrevioIndenizado]);
```

# Palavras reservadas

As palavras reservadas da linguagem Delphi devem ser escritas com todas as letras minúsculas, a única exceção é a palavra String, pois segue o padrão dos tipos, os quais iniciam com letra maiúscula. As palavras reservadas do Delphi são:

<table border="1" class="align-left" id="bkmrk-%E2%A0-%E2%A0-%E2%A0-%E2%A0-%E2%A0-%E2%A0-%E2%A0-%E2%A0-%E2%A0-%E2%A0-%E2%A0-%E2%A0-%E2%A0-%E2%A0-%E2%A0-%E2%A0-%E2%A0-%E2%A0-%E2%A0-%E2%A0-" style="height: 945px; width: 60.1043%; border-collapse: collapse;"><tbody><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">absolute</td><td class="align-center" style="width: 33.3333%; height: 29px;">forward</td><td class="align-center" style="width: 33.3333%; height: 29px;">public</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">abstract</td><td class="align-center" style="width: 33.3333%; height: 29px;">function</td><td class="align-center" style="width: 33.3333%; height: 29px;">published</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">and</td><td class="align-center" style="width: 33.3333%; height: 29px;">goto</td><td class="align-center" style="width: 33.3333%; height: 29px;">raise</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">array</td><td class="align-center" style="width: 33.3333%; height: 29px;">if</td><td class="align-center" style="width: 33.3333%; height: 29px;">read</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">as</td><td class="align-center" style="width: 33.3333%; height: 29px;">implementation</td><td class="align-center" style="width: 33.3333%; height: 29px;">readonly</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">asm</td><td class="align-center" style="width: 33.3333%; height: 29px;">in</td><td class="align-center" style="width: 33.3333%; height: 29px;">record</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">assembler</td><td class="align-center" style="width: 33.3333%; height: 29px;">index</td><td class="align-center" style="width: 33.3333%; height: 29px;">register</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">automated</td><td class="align-center" style="width: 33.3333%; height: 29px;">inherited</td><td class="align-center" style="width: 33.3333%; height: 29px;">reintroduce</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">begin</td><td class="align-center" style="width: 33.3333%; height: 29px;">initialization</td><td class="align-center" style="width: 33.3333%; height: 29px;">repeat</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">case</td><td class="align-center" style="width: 33.3333%; height: 29px;">inline</td><td class="align-center" style="width: 33.3333%; height: 29px;">resourcestring</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">cdecl</td><td class="align-center" style="width: 33.3333%; height: 29px;">interface</td><td class="align-center" style="width: 33.3333%; height: 29px;">safecall</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">class</td><td class="align-center" style="width: 33.3333%; height: 29px;">is</td><td class="align-center" style="width: 33.3333%; height: 29px;">set</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">const</td><td class="align-center" style="width: 33.3333%; height: 29px;">label</td><td class="align-center" style="width: 33.3333%; height: 29px;">shl</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">constructor</td><td class="align-center" style="width: 33.3333%; height: 29px;">library</td><td class="align-center" style="width: 33.3333%; height: 29px;">shr</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">contains</td><td class="align-center" style="width: 33.3333%; height: 29px;">message</td><td class="align-center" style="width: 33.3333%; height: 29px;">stdcall</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">default</td><td class="align-center" style="width: 33.3333%; height: 29px;">mod</td><td class="align-center" style="width: 33.3333%; height: 29px;">stored</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">destructor</td><td class="align-center" style="width: 33.3333%; height: 29px;">name</td><td class="align-center" style="width: 33.3333%; height: 29px;">string</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">dispid</td><td class="align-center" style="width: 33.3333%; height: 29px;">near</td><td class="align-center" style="width: 33.3333%; height: 29px;">then</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">dispinterface</td><td class="align-center" style="width: 33.3333%; height: 29px;">nil</td><td class="align-center" style="width: 33.3333%; height: 29px;">threadvar</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">div</td><td class="align-center" style="width: 33.3333%; height: 29px;">not</td><td class="align-center" style="width: 33.3333%; height: 29px;">to</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">do</td><td class="align-center" style="width: 33.3333%; height: 29px;">object</td><td class="align-center" style="width: 33.3333%; height: 29px;">try</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">downto</td><td class="align-center" style="width: 33.3333%; height: 29px;">of</td><td class="align-center" style="width: 33.3333%; height: 29px;">type</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">dynamic</td><td class="align-center" style="width: 33.3333%; height: 29px;">operator</td><td class="align-center" style="width: 33.3333%; height: 29px;">unit</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">else</td><td class="align-center" style="width: 33.3333%; height: 29px;">or</td><td class="align-center" style="width: 33.3333%; height: 29px;">until</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">end</td><td class="align-center" style="width: 33.3333%; height: 29px;">out</td><td class="align-center" style="width: 33.3333%; height: 29px;">uses</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">except</td><td class="align-center" style="width: 33.3333%; height: 29px;">overload</td><td class="align-center" style="width: 33.3333%; height: 29px;">var</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">export</td><td class="align-center" style="width: 33.3333%; height: 29px;">override</td><td class="align-center" style="width: 33.3333%; height: 29px;">virtual</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">exports</td><td class="align-center" style="width: 33.3333%; height: 29px;">package</td><td class="align-center" style="width: 33.3333%; height: 29px;">while</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">external</td><td class="align-center" style="width: 33.3333%; height: 29px;">pascal</td><td class="align-center" style="width: 33.3333%; height: 29px;">write</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">far</td><td class="align-center" style="width: 33.3333%; height: 29px;">private</td><td class="align-center" style="width: 33.3333%; height: 29px;">writeonly</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">file</td><td class="align-center" style="width: 33.3333%; height: 29px;">procedure</td><td class="align-center" style="width: 33.3333%; height: 29px;">xor</td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">finally</td><td class="align-center" style="width: 33.3333%; height: 29px;">program</td><td class="align-center" style="width: 33.3333%; height: 29px;"> </td></tr><tr style="height: 29px;"><td class="align-center" style="width: 33.3333%; height: 29px;">for</td><td class="align-center" style="width: 33.3333%; height: 29px;">property</td><td class="align-center" style="width: 33.3333%; height: 29px;"> </td></tr></tbody></table>

# Alteração da Estrutura de Banco de Dados

## Regra para Inativação de Campos ou Tabelas

Quando um campo ou tabela deixar de ser utilizado, ele **não** deve ser removido da unit de criação e **não** deve ser executado nenhum comando SQL de exclusão (`DROP`).

A estrutura deve permanecer intacta no banco de dados, mesmo sem utilização pelo sistema.

---

## Definição de Escopo e Escolha da Unit

A unit utilizada para a criação de uma tabela é definida pelo seu escopo de uso:

- **`CriaTabEsp.pas`:** Utilizada para tabelas específicas de um único módulo.
- **`CriaTab.pas`:** Utilizada para tabelas compartilhadas entre dois ou mais módulos do sistema.

---

## Vínculo da Tabela ao Módulo (`DDL.Classes.pas`)

Ao criar uma nova tabela, também é obrigatório registrá-la na unit `DDL.Classes.pas`.

A tabela deve ser adicionada na procedure `CriaMatrizSistemas__` correspondente ao módulo ao qual ela pertence, utilizando o método `AddTabela`.

- **Exemplo Prático (Módulo de Compras - CC):** Para uma tabela pertencente ao módulo de Compras, adicione o registro na procedure `CriaMatrizSistemasCC`.

```pascal
class procedure CriaMatrizSistemasCC(var AMatriz: TMatrizSistema); static;

AddTabela(AMatriz, 'PROPNR', 'Prop. dos itens das Notificações de Recebimento');
AddTabela(AMatriz, 'PROPNRM', 'Prop. dos itens das Notificações de Recebimento no Arquivo Morto', 'NULO', True, False, True);
```

Esse registro é utilizado pelo sistema para identificar a quais módulos a tabela pertence, sendo também a referência utilizada para determinar quais units `uMatrizAlt__.pas` devem ser atualizadas quando houver alterações em tabelas compartilhadas.

---

## Mapeamento de Chaves Estrangeiras e Integridade

Sempre que uma nova tabela possuir chave estrangeira ou depender de outra tabela do sistema, também é obrigatório registrar essa relação de integridade referencial na unit `DDL.Classes.pas`.

O relacionamento deve ser adicionado na procedure `CriaMatrizIntegRef__` correspondente ao módulo ao qual a tabela pertence, utilizando o método `AddIntegRef`.

- **Exemplo Prático (Módulo de Compras - CC):** Para uma tabela pertencente ao módulo de Compras, adicione o relacionamento na procedure `CriaMatrizIntegRefCC`.

```pascal
class procedure CriaMatrizIntegRefCC(var AMatriz: TMatrizIntegRef); static;

AddIntegRef(
	AMatriz, 'ITENSNR', 'Abrev;Numero;NumeroFor;Serie;NumeroCli;Item', 'PROPNR',
	'Abrev;Numero;NumeroFor;Serie;NumeroCli;Item', tcCascade);

AddIntegRef(
	AMatriz, 'ITENSNRM', 'Abrev;Numero;NumeroFor;Serie;NumeroCli;Item', 'PROPNRM',
	'Abrev;Numero;NumeroFor;Serie;NumeroCli;Item', tcCascade);
```

Esse registro define os relacionamentos entre as tabelas do sistema, permitindo que as regras de integridade referencial, como exclusão ou atualização em cascata, sejam aplicadas corretamente.

---

## Versionamento de Alterações na Base de Dados

#### Cenário A: Tabelas Exclusivas de Módulo (`CriaTabEsp.pas`)

Ao criar ou modificar uma tabela de módulo único, é obrigatório registrar a alteração na unit `uMatrizAlt__.pas` correspondente ao módulo modificado, chamando o método de atualização com o número da versão do módulo.

- **Exemplo Prático (Módulo de Compras - CC):** Se uma nova coluna for adicionada a uma tabela exclusiva de Compras, você deve acessar a unit `uMatrizAltCC.pas` e incluir a chamada:

```pascal
AddMatrizAlt('PLANFISC', '5.194');
```

#### Cenário B: Tabelas Compartilhadas (`CriaTab.pas`)

Quando uma tabela compartilhada for criada ou modificada, o desenvolvedor deve identificar todos os módulos afetados e replicar a chamada de atualização em **todas** as units `uMatrizAlt__.pas` desses respectivos módulos.

##### Como identificar os módulos afetados:

1. Acesse a unit `DDL.Classes.pas`.
2. Verifique, dentro das procedures `CriaMatrizSistemas__`, quais delas fazem uso dessa tabela. Você encontrará uma estrutura semelhante a esta:

```pascal
AddTabela(AMatriz, 'PLANFISC', 'Plano Fiscal');
```

3. Para cada módulo identificado, adicione a chamada `AddMatrizAlt` com o número da versão do módulo na sua respectiva unit de alteração.

- **Exemplo Prático:** Você adicionou um novo campo na tabela `PLANFISC` (alterando a `CriaTab.pas`). Ao buscar por `PLANFISC` na unit `DDL.Classes.pas`, você identificou que ela é utilizada pelas seguintes procedures: 
    - `CriaMatrizSistemasCC` (Módulo CC)
    - `CriaMatrizSistemasEX` (Módulo EX)
    - `CriaMatrizSistemasVD` (Módulo VD)
    
    Portanto, você deverá abrir as units `uMatrizAltCC.pas`, `uMatrizAltEX.pas` e `uMatrizAltVD.pas` e adicionar a chamada de atualização em cada uma delas:
    
    ```pascal
    AddMatrizAlt('PLANFISC', '5.194');
    ```
    
    <p class="callout warning">**Atenção:** Cada módulo possui um número de versão diferente. Caso tenha dúvidas, consulte o guia de [como identificar o número da versão de cada módulo](https://wiki.supersoft.com.br/books/padroes-de-codigo/page/como-identificar-o-numero-da-versao-de-um-modulo).</p>

# Alteração de Registros em Massa na Atualização

Sempre que houver a necessidade de realizar alterações em massa nos registros de uma tabela durante o processo de atualização do sistema, utilizamos as rotinas de atualização controladas por versão.

Cada módulo do sistema possui uma unit específica para essa finalidade, nomeada como `uAtualizaCampoNulo__.pas` (onde o sufixo corresponde à sigla do módulo, ex: `uAtualizaCampoNuloCC.pas`).

---

## Estrutura de Versionamento

As atualizações são encapsuladas dentro de condicionais que validam a versão atual do banco de dados (`AVersaoDasTabelas`). Isso garante que a rotina seja executada **apenas uma vez**, exatamente no momento em que o cliente atinge a versão estipulada.

##### Exemplo de Estrutura:

```pascal
if (AVersaoDasTabelas < 5.185) then
begin
  // Executa o método padrão de atualização de campos
  TAtualizaCampoNulo.Atualizar('PARAMCC', 'BloqueiaNumOC', 'S', 'N');
  
  // Executa uma procedure customizada para ajustes complexos
  CorrigirCodClasse();
end;
```

Neste exemplo, ao atualizar o sistema para a versão **5.185**:

- O método `TAtualizaCampoNulo.Atualizar` será disparado para alterar os registros do campo `BloqueiaNumOC` na tabela `PARAMCC`, substituindo os valores `'S'` por `'N'`.
- A procedure customizada `CorrigirCodClasse()` será chamada para executar comandos SQL adicionais.

<p class="callout info">[Como Identificar o Número da Versão de um Módulo](https://wiki.supersoft.com.br/books/padroes-de-codigo/page/como-identificar-o-numero-da-versao-de-um-modulo "Como Identificar o Número da Versão de um Módulo")</p>

---

## Implementação de Procedures Customizadas

Para cenários onde o método `TAtualizaCampoNulo.Atualizar` não é suficiente (como atualizações que exigem regras de negócio mais complexas ou manipulação de strings), deve-se criar uma procedure interna isolada utilizando `TFDQuery`.

##### Exemplo de Procedure Customizada:

```pascal
procedure CorrigirCodClasse();
var
  LQAux: TFDQuery;
begin
  LQAux := CriarFDQuery(nil);
  try
    LQAux.SQL.Clear();
    LQAux.SQL.Add('UPDATE NFReceb');
    LQAux.SQL.Add('   SET CodClasse = LPAD(CodClasse, 2, "0")');
    LQAux.SQL.Add(' WHERE CodClasse <> ""');
    LQAux.ExecutarSQL();
  finally
    FreeAndNil(LQAux);
  end;
end;
```

# Como Identificar o Número da Versão de um Módulo

## 1. Identificar o Número do Caso via GitHub Desktop

O primeiro passo é identificar a branch da versão que está sendo trabalhada. Caso não saiba qual é, verifique as informações no grupo de desenvolvimento do **Rocket.Chat**.

Ao identificar o número da branch, faça a busca no **GitHub Desktop** para localizar o número do caso associado à versão.

- **Exemplo de Branch:** `173-Caso-0054066`
- **O que extrair:** O número após a palavra "Caso" (`0054066`) é o identificador que usaremos para consultar as versões.

---

## 2. Consultar as Relações no Mantis

Com o número do caso em mãos, siga o procedimento abaixo:

1. Acesse o **Mantis** e busque pelo número do caso localizado na branch (ex: `0054066`).
2. Navegue até o tópico de **Relações** do chamado.
3. Nesta seção, estarão relacionados todos os sistemas e casos que compõem essa entrega, detalhando a versão exata de cada um.

##### Exemplo de Vínculo Encontrado:

> **SSCompras Versão 5.195 - COMPRAS**

Desse modo, quando houver a necessidade de aplicar scripts de estrutura de tabelas ou manutenção de registros em massa, o número `5.195` será o valor utilizado exclusivamente para o módulo de **Compras (CC)**.

---

<p class="callout warning">**Atenção / Vale Ressaltar:** Cada módulo possui um número de versão diferente! Nunca assumam que a versão de um sistema se aplica ao outro. A branch `173` pode atualizar Compras para `5.195`, mas conter o módulo de Estoque (CE) na versão `5.170`. Sempre confira a lista de relações para cada sigla envolvida na sua alteração.</p>

# SQL

Neste capítulo se encontram os padrões de código adotados para SQL e alguns exemplos ilustrativos, caso mesmo com os exemplos descritos, ainda restem dúvidas, não hesite em perguntar

# Considerações Iniciais

### **Introdução**

Para rotinas em SQL, deve-se observar as seguintes considerações:

1. **Palavras reservadas** devem ser escritas **integralmente em letras maiúsculas**.
2. Nomes de **tabelas e campos** devem utilizar a notação **PascalCase**, mantendo **siglas em letras maiúsculas**.
3. Os **aliases de tabelas** devem ser escritos **integralmente em letras maiúsculas** e utilizar abreviações **curtas e significativas** da tabela de origem.
4. **Parâmetros** devem possuir o **prefixo "P"** e utilizar a notação **PascalCase**.
5. Para facilitar a implementação e a leitura das cláusulas, as **palavras reservadas devem ser alinhadas de forma que exista uma coluna contínua separando-as dos campos e tabelas**, conforme o exemplo abaixo:

```SQL
    SELECT SUM(NF.ValorNF) AS ValorNF,
           CTE.CodigoCTE
      FROM NotaFiscal AS NF
INNER JOIN ConhecimentoCTE AS CTE
        ON CTE.CodigoNF = NF.CodigoNF
     WHERE NF.EmpresaID = :PNotaFiscalEmpresaID
       AND CTE.EmpresaID = :PConhecimentoCTEEmpresaID
  GROUP BY CTE.CodigoCTE
 UNION ALL
    SELECT (SELECT CodigoXML
              FROM ArquivoXML) AS CodigoXML,
           RELCTE.CodigoCTE
      FROM DocumentoXML AS DOCXML
INNER JOIN (SELECT CodigoCTE
              FROM RelacaoCTE) AS RELCTE
        ON RELCTE.CodigoCTE = DOCXML.CodigoCTE
     WHERE DOCXML.EmpresaID = :PDocumentoXMLEmpresaID
  ORDER BY 1
```

Perceba que, na cláusula do exemplo acima, as linhas 4 e 14 possuem as **maiores palavras reservadas/expressões**. Dessa forma, **as demais palavras reservadas recebem a adição de espaços em branco à esquerda**, para que **todas as expressões terminem na mesma coluna**. Assim, forma-se uma **coluna contínua ao longo de toda a cláusula**, separando as palavras reservadas à esquerda dos campos e tabelas à direita.

# Exemplo: CASE

### **Sem expressão no CASE**

```SQL
SELECT T1.Campo1, T1.Campo2
  FROM Tabela1 T1
 WHERE T1.Campo2 = :PInformacao1
   AND T1.Campo3 = :PInformacao2
   AND CASE
         WHEN
           T1.Campo4 IS NOT NULL
         THEN
           T1.Campo4 = :PInformacao3
         ELSE
           T1.Campo5 = :PInformacao3
       END
```

### **Com expressão no CASE**

```SQL
SELECT T1.Campo1, T1.Campo2
  FROM Tabela1 T1
 WHERE T1.Campo2 = :PInformacao1
   AND T1.Campo3 = :PInformacao2
   AND CASE COALESCE(T1.Campo4, "")
         WHEN
           ""
         THEN
           T1.Campo5 ||
           SUBSTRING(T1.Campo6 FROM 1 FOR 1) ||
           SUBSTRING(T1.Campo6 FROM 3 FOR 5)
         ELSE
           T1.Campo7
       END ApelidoDoCampo
```

### **Com CASE no SELECT**

```SQL
SELECT
  CASE
    WHEN
      EXISTS (SELECT 1
		        FROM Tabela1
               WHERE Campo1 = :PCampo1
                 AND Campo2 = :PCampo2)
      AND EXISTS (SELECT 1 
                    FROM Tabela1
                   WHERE Campo1 = :PCampo1
                     AND Campo2 = :PCampo2)
    THEN 
	  "True"
    ELSE 
	  "False"
  END AS Resultado
  FROM RDB$DATABASE;
```

# Exemplo: DELETE

```SQL
DELETE
  FROM TabelaExemplo
 WHERE Abrev = :PAbrev
   AND Tipo = :PTipo
   AND Categoria = :PCategoria

```

<p class="callout info">As comparações realizadas nas linhas 3-5 poderiam ter seus operadores alinhados na mesma coluna, entretanto essa não é uma prática recomendada para cláusulas mais extensas.</p>

# Exemplo: Modificador DISTINCT

```SQL
SELECT DISTINCT T.Campo1, T.Campo2, T.Campo3
                T.Campo4, T.Campo5, T.Campo6
           FROM Tabela T
     INNER JOIN OutraTabela O
             ON O.Campo1 = T.Campo7
          WHERE T.Campo1 = :Param1
            AND T.Campo8 = :Param2
```

# Exemplo: UPDATE

```SQL
UPDATE TabelaExemplo
   SET Numero = :PNumero,
       Nome = :PNome
 WHERE Categoria = :PCategoria
   AND Tipo = :PTipo

```

<p class="callout info">As comparações realizadas nas linhas 2-5 poderiam ter seus operadores alinhados na mesma coluna, entretanto essa não é uma prática recomendada para cláusulas mais extensas</p>

# Palavras Reservadas

As palavras reservadas em SQL devem ser escritas com todas as letras maiúsculas:

<table border="1" id="bkmrk-active-double-numeri" style="border-collapse: collapse; width: 73.5782%; height: 1334px;"><tbody><tr style="height: 29px;"><td class="align-left" style="width: 33.3333%; height: 29px;">ACTIVE</td><td class="align-left" style="width: 33.3333%; height: 29px;">DOUBLE</td><td class="align-left" style="width: 32.4692%; height: 29px;">NUMERIC</td></tr><tr style="height: 29px;"><td class="align-left" style="width: 33.3333%; height: 29px;">ADD</td><td class="align-left" style="width: 33.3333%; height: 29px;">DROP</td><td class="align-left" style="width: 32.4692%; height: 29px;">OF</td></tr><tr style="height: 29px;"><td class="align-left" style="width: 33.3333%; height: 29px;">AND</td><td class="align-left" style="width: 33.3333%; height: 29px;">EDIT</td><td class="align-left" style="width: 32.4692%; height: 29px;">ON</td></tr><tr style="height: 29px;"><td class="align-left" style="width: 33.3333%; height: 29px;">ALL</td><td class="align-left" style="width: 33.3333%; height: 29px;">ELSE</td><td class="align-left" style="width: 32.4692%; height: 29px;">ONLY</td></tr><tr style="height: 29px;"><td class="align-left" style="width: 33.3333%; height: 29px;">ALTER</td><td class="align-left" style="width: 33.3333%; height: 29px;">END</td><td class="align-left" style="width: 32.4692%; height: 29px;">OPEN</td></tr><tr style="height: 29px;"><td class="align-left" style="width: 33.3333%; height: 29px;">ANY</td><td class="align-left" style="width: 33.3333%; height: 29px;">EXECUTE</td><td class="align-left" style="width: 32.4692%; height: 29px;">OR</td></tr><tr style="height: 29px;"><td class="align-left" style="width: 33.3333%; height: 29px;">AS</td><td class="align-left" style="width: 33.3333%; height: 29px;">EXISTS</td><td class="align-left" style="width: 32.4692%; height: 29px;">ORDER</td></tr><tr style="height: 29px;"><td class="align-left" style="width: 33.3333%; height: 29px;">ASC</td><td class="align-left" style="width: 33.3333%; height: 29px;">FILTER</td><td class="align-left" style="width: 32.4692%; height: 29px;">OUTER</td></tr><tr style="height: 29px;"><td class="align-left" style="width: 33.3333%; height: 29px;">ASCENDING</td><td class="align-left" style="width: 33.3333%; height: 29px;">FIRST</td><td class="align-left" style="width: 32.4692%; height: 29px;">PERCENT</td></tr><tr style="height: 29px;"><td class="align-left" style="width: 33.3333%; height: 29px;">AT</td><td class="align-left" style="width: 33.3333%; height: 29px;">FLOAT</td><td class="align-left" style="width: 32.4692%; height: 29px;">PLAN</td></tr><tr style="height: 29px;"><td class="align-left" style="width: 33.3333%; height: 29px;">AVG</td><td class="align-left" style="width: 33.3333%; height: 29px;">FOR</td><td class="align-left" style="width: 32.4692%; height: 29px;">POSITION</td></tr><tr style="height: 29px;"><td class="align-left" style="width: 33.3333%; height: 29px;">BEFORE</td><td class="align-left" style="width: 33.3333%; height: 29px;">FOREIGN</td><td class="align-left" style="width: 32.4692%; height: 29px;">PRECISION</td></tr><tr style="height: 29px;"><td class="align-left" style="width: 33.3333%; height: 29px;">BEGIN</td><td class="align-left" style="width: 33.3333%; height: 29px;">FROM</td><td class="align-left" style="width: 32.4692%; height: 29px;">PREPARE</td></tr><tr style="height: 29px;"><td class="align-left" style="width: 33.3333%; height: 29px;">BETWEEN</td><td class="align-left" style="width: 33.3333%; height: 29px;">FULL</td><td class="align-left" style="width: 32.4692%; height: 29px;">PRIMARY</td></tr><tr style="height: 29px;"><td class="align-left" style="width: 33.3333%; height: 29px;">BLOB</td><td class="align-left" style="width: 33.3333%; height: 29px;">FUNCTION</td><td class="align-left" style="width: 32.4692%; height: 29px;">PROCEDURE</td></tr><tr><td class="align-left" style="width: 33.3333%;">BY</td><td class="align-left" style="width: 33.3333%;">GENERATOR</td><td class="align-left" style="width: 32.4692%;">PUBLIC</td></tr><tr><td class="align-left" style="width: 33.3333%;">CASE</td><td class="align-left" style="width: 33.3333%;">GEN\_ID</td><td class="align-left" style="width: 32.4692%;">REAL</td></tr><tr><td class="align-left" style="width: 33.3333%;">CAST</td><td class="align-left" style="width: 33.3333%;">GROUP</td><td class="align-left" style="width: 32.4692%;">RIGHT</td></tr><tr><td class="align-left" style="width: 33.3333%;">CHAR</td><td class="align-left" style="width: 33.3333%;">HAVING</td><td class="align-left" style="width: 32.4692%;">ROWS</td></tr><tr><td class="align-left" style="width: 33.3333%;">COALESCE</td><td class="align-left" style="width: 33.3333%;">HOUR</td><td class="align-left" style="width: 32.4692%;">SELECT</td></tr><tr><td class="align-left" style="width: 33.3333%;">COLLATE</td><td class="align-left" style="width: 33.3333%;">IF</td><td class="align-left" style="width: 32.4692%;">SET</td></tr><tr><td class="align-left" style="width: 33.3333%;">COLUMN</td><td class="align-left" style="width: 33.3333%;">IN</td><td class="align-left" style="width: 32.4692%;">SIZE</td></tr><tr><td class="align-left" style="width: 33.3333%;">COMMIT</td><td class="align-left" style="width: 33.3333%;">INACTIVE</td><td class="align-left" style="width: 32.4692%;">SOME</td></tr><tr><td class="align-left" style="width: 33.3333%;">CONTINUE</td><td class="align-left" style="width: 33.3333%;">INDEX</td><td class="align-left" style="width: 32.4692%;">SQL</td></tr><tr><td class="align-left" style="width: 33.3333%;">COUNT</td><td class="align-left" style="width: 33.3333%;">INNER</td><td class="align-left" style="width: 32.4692%;">SUM</td></tr><tr><td class="align-left" style="width: 33.3333%;">CREATE</td><td class="align-left" style="width: 33.3333%;">INSERT</td><td class="align-left" style="width: 32.4692%;">TABLE</td></tr><tr><td class="align-left" style="width: 33.3333%;">CURRENT</td><td class="align-left" style="width: 33.3333%;">INTEGER</td><td class="align-left" style="width: 32.4692%;">THEN</td></tr><tr><td class="align-left" style="width: 33.3333%;">CURRENT\_DATE</td><td class="align-left" style="width: 33.3333%;">INTO</td><td class="align-left" style="width: 32.4692%;">TRIGGER</td></tr><tr><td class="align-left" style="width: 33.3333%;">CURRENT\_ROLE</td><td class="align-left" style="width: 33.3333%;">IS</td><td class="align-left" style="width: 32.4692%;">TRUNCATE</td></tr><tr><td class="align-left" style="width: 33.3333%;">CURRENT\_TIME</td><td class="align-left" style="width: 33.3333%;">JOIN</td><td class="align-left" style="width: 32.4692%;">TYPE</td></tr><tr><td class="align-left" style="width: 33.3333%;">CURRENT\_TIMESTAMP</td><td class="align-left" style="width: 33.3333%;">KEY</td><td class="align-left" style="width: 32.4692%;">UNION</td></tr><tr><td class="align-left" style="width: 33.3333%;">CURRENT\_TRANSACTION</td><td class="align-left" style="width: 33.3333%;">LAST</td><td class="align-left" style="width: 32.4692%;">UPDATE</td></tr><tr><td class="align-left" style="width: 33.3333%;">CURRENT\_USER</td><td class="align-left" style="width: 33.3333%;">LEFT</td><td class="align-left" style="width: 32.4692%;">UPDATING</td></tr><tr><td class="align-left" style="width: 33.3333%;">CURSOR</td><td class="align-left" style="width: 33.3333%;">LENGTH</td><td class="align-left" style="width: 32.4692%;">USE</td></tr><tr><td class="align-left" style="width: 33.3333%;">DATABASE</td><td class="align-left" style="width: 33.3333%;">LIKE</td><td class="align-left" style="width: 32.4692%;">USER</td></tr><tr><td class="align-left" style="width: 33.3333%;">DATE</td><td class="align-left" style="width: 33.3333%;">LONG</td><td class="align-left" style="width: 32.4692%;">USING</td></tr><tr><td class="align-left" style="width: 33.3333%;">DAY</td><td class="align-left" style="width: 33.3333%;">MAX</td><td class="align-left" style="width: 32.4692%;">VALUE</td></tr><tr><td class="align-left" style="width: 33.3333%;">DEC</td><td class="align-left" style="width: 33.3333%;">MERGE</td><td class="align-left" style="width: 32.4692%;">VALUES</td></tr><tr><td class="align-left" style="width: 33.3333%;">DECIMAL</td><td class="align-left" style="width: 33.3333%;">MIN</td><td class="align-left" style="width: 32.4692%;">VIEW</td></tr><tr><td class="align-left" style="width: 33.3333%;">DECLARE</td><td class="align-left" style="width: 33.3333%;">MINUTE</td><td class="align-left" style="width: 32.4692%;">WHEN</td></tr><tr><td class="align-left" style="width: 33.3333%;">DEFAULT</td><td class="align-left" style="width: 33.3333%;">MONTH</td><td class="align-left" style="width: 32.4692%;">WHERE</td></tr><tr><td class="align-left" style="width: 33.3333%;">DELETE</td><td class="align-left" style="width: 33.3333%;">NAMES</td><td class="align-left" style="width: 32.4692%;">WHILE</td></tr><tr><td class="align-left" style="width: 33.3333%;">DESC</td><td class="align-left" style="width: 33.3333%;">NO</td><td class="align-left" style="width: 32.4692%;">WITH</td></tr><tr><td class="align-left" style="width: 33.3333%;">DESCENDING</td><td class="align-left" style="width: 33.3333%;">NOT</td><td class="align-left" style="width: 32.4692%;">YEAR</td></tr><tr><td class="align-left" style="width: 33.3333%;">DISTINCT</td><td class="align-left" style="width: 33.3333%;">NULL</td><td class="align-left" style="width: 32.4692%;">YEARDAY</td></tr><tr><td class="align-left" style="width: 33.3333%;">DO</td><td class="align-left" style="width: 33.3333%;">NULLIF</td><td class="align-left" style="width: 32.4692%;"> </td></tr></tbody></table>

# Dúvidas Frequentes

Espaço dedicado para a inclusão de dúvidas comuns durante o desenvolvimento em SQL. Caso sua dúvida não esteja aqui, talvez seja interessante adicioná-la.

---

##### Quando utilizar parâmetros, QuotedStr ou aspas duplas?

**Parâmetros:**

Utilizar principalmente para as condições da cláusula

```SQL
SELECT *
  FROM Tabela
 WHERE Campo1 = :PParametro1
   AND Campo2 = :PParametro2
   AND Campo3 = :PParametro3   
```

**QuotedStr:**

Utilizar quando for preciso concatenar uma variável string na consulta

```SQL
SELECT Campo1, Campo2, Campo3
	   CASE
	     WHEN 
('	       Campo4 = QuotedStr(LVariavel)');
	     THEN
	       Campo4
	     ELSE
	       Campo5
	   END ApelidoDoCampo
  FROM Tabela
 WHERE Campo1 IS NOT NULL
```

**Aspas duplas:**

Utilizar quando uma string fixa for inserida na cláusula

```SQL
SELECT Campo1, Campo2, Campo3
  FROM Tabela
 WHERE Campo1 = "NFE"
```

---

##### A utilização da palavra reservada "AS" é obrigatória para apelidar campos ou tabelas?

##### Qual a diferença entre a utilização de um UNION e UNION ALL?

##### Qual JOIN devo utilizar na cláusula?

# Exemplo: INSERT

## **INSERT com SELECT**  


```SQL
INSERT INTO Tabela(Abrev, Nome, Numero)
     SELECT Abrev, Nome, Numero
       FROM TabelaExemplo
   GROUP BY 1, 2, 3
```

## **INSERT**

```SQL
INSERT INTO Tabela(Abrev, Nome, Numero)
     VALUES (:PAbrev, :PNome, :PNumero)
```

# Boas práticas

Parte decisiva em manter um código limpo e de fácil manutenção, as boas práticas são essenciais para trabalhar em equipe em qualquer projeto. Neste capítulo, se encontram sugestões e práticas adotadas para a manutenção do código e uso das ferramentas utilizadas durante todo o processo de desenvolvimento.

# Versionamento

### **Mensagens de Versionamento**

Ao realizar qualquer alteração que seja necessário realizar um commit, é importantíssimo adicionar uma mensagem que possa informar do que se trata aquela alteração. Essa mensagem deve ser breve e descritiva, explicando em poucas palavras o que foi alterado, de forma que, caso outro desenvolvedor necessite realizar uma busca pelo log de alterações, as mensagens possam servir de "filtro" para identificar o que é relevante para a sua consulta.

<p class="callout warning">Deve-se evitar ao máximo realizar commits sem mensagem, principalmente em versões e no trunk.</p>

#### **Exemplos**

---

##### **Modelo de Mensagem**

<table border="1" id="bkmrk-caso-xxxxx%3A-descri%E3%A7%E3%A3" style="border-collapse: collapse; width: 100%;"><tbody><tr><td style="width: 100%;">Caso XXXXX: Descrição do caso de acordo com o Mantis/Trello.

\- Mensagem descritiva e em poucas palavras do que foi alterado  
  
(Opcional) Desenvolvedor

</td></tr></tbody></table>

---

##### **Criação de branch**

<p class="callout info">Ao criar um branch, deve-se informar o número do caso e a sua descrição de acordo com o Mantis/Trello.</p>

<table border="1" id="bkmrk-caso-xxxxx%3A-descri%E3%A7%E3%A3-0" style="border-collapse: collapse; width: 100%;"><tbody><tr><td style="width: 100%;">Caso XXXXX: Descrição do caso de acordo com o Mantis/Trello.

\- Criação do branch  
  
(Opcional) Desenvolvedor

</td></tr></tbody></table>

##### **Alterações** 

<p class="callout info">Ao realizar o commit de alterações, além do cabeçalho indicando o número do caso e a descrição, deve-se adicionar por tópico as alterações feitas naquele commit.</p>

<table border="1" id="bkmrk-caso-xxxxx%3A-descri%E3%A7%E3%A3-1" style="border-collapse: collapse; width: 100%;"><tbody><tr><td style="width: 100%;">Caso XXXXX: Descrição do caso de acordo com o Mantis/Trello.

\- Alterações na lógica da rotina CalcularSaldo.

\- Correções no padrão de código aplicado.  
\- Criação da classe TGerador  
  
(Opcional) Desenvolvedor

</td></tr></tbody></table>

##### **Atualização de Branch**

<p class="callout info">Ao realizar a atualização de um branch(Merge com Trunk) , deve-se adicionar a "tag" \[Atualização do Branch\] no início do cabeçalho, para que ao consultar o log de alterações, o desenvolvedor identifique prontamente quais revisões são referentes à atualizações do branch e quais não são.</p>

<table border="1" id="bkmrk-%5Batualiza%E3%A7%E3%A3o-do-bran" style="border-collapse: collapse; width: 100%;"><tbody><tr><td style="width: 100%;">\[Atualização do Branch\] Caso XXXXX: Descrição do caso de acordo com o Mantis/Trello.

  
(Opcional) Desenvolvedor

</td></tr></tbody></table>

# Documentação Interna

#### **Comentários** 

Segundo Robert C. Martin em Código Limpo: Habilidades Práticas do Agile Software,

> “O uso adequado de comentários é compensar nosso fracasso em nos expressar no código.”

Dessa maneira, o **uso de comentários no código deve ser evitado**, visto que, conforme o código passar por manutenção, a tendência é que o comentário fique desatualizado e não condizente com o trecho de código à que se refere.

#### **Comentários que podem ser adicionados:**

##### **Comentários descritivos:**

```PASCAL
// INSS
if (DM_GERACAO.EventosSendoGerados.IndexOf('e301') <> -1) then
begin
	Código Referente ao INSS
end;
```

<p class="callout success">Comentários que complementam o entendimento de uma rotina, mas que não tentam explicar o que está sendo feito no trecho.</p>

---

#### **Comentários que devem ser evitados/removidos:**

##### **Comentários no cabeçalho:**

```PASCAL
{****************************************************************
* Módulo : ArqTeste 											*
* Finalidade : Realizar a exportação de Notas Fiscais 			*
* de Serviços para Prefeitura de São Paulo 						*
* Data : 21/02/2000 											*
* Programador : Fulano da Silva Santos 							*
****************************************************************}
```

<p class="callout danger">Comentários utilizados como cabeçalho que descrevem o que a unit faz, a data de implementação e o programador responsável pela implementação apesar de serem descritivos, muitas vezes não são atualizados conforme o código passa por mudanças. Essas informações podem e devem ser encontradas nas mensagens de versionamento.</p>

---

##### **Comentários referentes à processos passados:**

```PASCAL
// MIGRACAO
// Caso a classe uClass.NumDocs seja utilizada em alguma unit
// a diretiva referente ao arquivo uClass.NumDocs.inc deverá ser acrescentada.
// Ex: Ver units FormPri e Backup, antes do nome da unit;
// No arquivo uClass.NumDocs.inc deverá ser adicionada a diretiva referente ao
// sistema ao qual a classe NumDocs foi adicionada.
```

<p class="callout danger">Comentários como esses não acrescentam informações no entendimento do código e acabam criando uma poluição visual na unit, de modo que, com o passar do tempo a tendência é que esse tipo de comentário seja automaticamente ignorado pelos desenvolvedores. </p>

---

##### **Código comentado:**

```PASCAL
// if ((QMANUT.FieldByName('DiasDireito').AsFloat = 0) or 
//	   (SameText(Trim(QMANUT.FieldByName('DiasDireito').AsString), ''))) and
//     (MessageDialog.Show('Não foi informado os dias de Direito. Deseja Continuar?', 
//		  mtConfirmation, [mbYes, mbNo], 0) = mrNo) then
// begin
// 	 QMANUT.FieldByName('DiasDireito').FocusControl;
// 	 Abort;
// end;
```

<p class="callout danger">Códigos comentados geram confusões no código, além de poluir desnecessariamente a unit, dessa maneira códigos não devem ser comentados e sim removidos. Caso necessário, pode-se visitar o histórico de revisões para acompanhar as alterações do trecho.</p>

# Código Limpo

#### **Definição de Clean Code**

<span style="font-weight: 400;">A apresentação de um código claro e organizado não consiste apenas na convenção nomes, constantes, classes, variáveis, espaçamento etc.. Um código limpo (</span>*<span style="font-weight: 400;">clean code</span>*<span style="font-weight: 400;">) deve ser:</span>

- <span style="font-weight: 400;">Simples: fácil entendimento;</span>
- <span style="font-weight: 400;">Eficiente: realizar tudo o que foi proposto;</span>
- <span style="font-weight: 400;">Único: não realizar algo que outro trecho de código já faz;</span>
- <span style="font-weight: 400;">Direto: não dar voltas para chegar no resultado;</span>
- <span style="font-weight: 400;">Feito com atenção: o código deve ser sempre feito com preocupação e revisto depois de pronto;</span>

#### ***Bad Smells***

Em contra partida, também existem as *<span style="font-weight: 400;">Bad Smells</span>*<span style="font-weight: 400;">, que como sua tradução já sugere, é algo com cheiro ruim, e representa o código com práticas que não devem ser utilizadas. Essas práticas se devem aos códigos que fogem das características de um código limpo. Abaixo são demonstrados alguns exemplos de </span>*<span style="font-weight: 400;">bad smells</span>*<span style="font-weight: 400;">.</span>

##### **Encadeamento de If's**

```PASCAL
if (Q_Manut.FieldByName('DiasDireito').AsFloat = 0) then
begin
  if (AnsiSameText(Trim(Q_Manut.FieldByName('DiasDireito').AsString), ''))) then
  begin
    if (MessageDialog.Show('Não foi informado os dias de Direito. Deseja' +
          'Continuar?', mtConfirmation, [mbYes, mbNo], 0) = mrNo) then
    begin
      Q_Manut.FieldByName('DiasDireito').FocusControl;
      Abort;
    end;
  end;
end;
```

<p class="callout info">Esse tipo de encadeamento pode ser facilmente substituído pela palavra reservada "and".</p>

```PASCAL
if (Q_Manut.FieldByName('DiasDireito').AsFloat = 0) and
   (AnsiSameText(Trim(Q_Manut.FieldByName('DiasDireito').AsString), ''))) and
   (MessageDialog.Show('Não foi informado os dias de Direito. Deseja' +
      'Continuar?', mtConfirmation, [mbYes, mbNo], 0) = mrNo) then
begin
  Q_Manut.FieldByName('DiasDireito').FocusControl;
  Abort;
end;
```

---

##### **Excesso de if-else**

```PASCAL
if (Q_Manut.FieldByName('DiasDireito').AsFloat = 0) then
  LTipo := 1
else if (Q_Manut.FieldByName('DiasDireito').AsFloat = 1) then
  LTipo := 2
else if (Q_Manut.FieldByName('DiasDireito').AsFloat = 2) then
  LTipo := 3
else if (Q_Manut.FieldByName('DiasDireito').AsFloat = 3) then
  LTipo := 5
else
  LTipo := 9;
```

<p class="callout info">O trecho acima pode ter sua estrutura facilitada com a utilização de um "case".</p>

```PASCAL
case Q_Manut.FieldByName('DiasDireito').AsFloat of 
  0: LTipo := 1;
  1: LTipo := 2;
  2: LTipo := 3;
  3: LTipo := 5;
  else
    LTipo := 9;
end;
```

---

##### **Atribuição Indireta**

<p class="callout danger">Situações com atribuições indiretas aparecem constantemente no código</p>

```PASCAL
if (Q_Manut.FieldByName('DiasDireito').AsFloat = 0) then
  LDeveIncrementar := False
else 
  LDeveIncrementar := True;
```

```PASCAL
if (RG_TipoCliente.ItemIndex = 0) then
  LTipo := 0
else (RG_TipoCliente.ItemIndex = 1) then
  LTipo := 1;
```

<p class="callout success">Basta uma pequena análise por parte do desenvolvedor para perceber que podem ser simplificadas</p>

```PASCAL
 LDeveIncrementar := (Q_Manut.FieldByName('DiasDireito').AsFloat <> 0);
```

```PASCAL
LTipo := RG_TipoCliente.ItemIndex;
```