Trabalhar com instruções condicionais
As instruções condicionais são muito usadas em qualquer linguagem de programação, incluindo linguagem de aplicativo (AL). Uma instrução condicional é usada para testar uma condição. Com base na avaliação dessa condição, uma ou mais instruções podem ser executadas.
Instruções if
A instrução condicional mais usada é if.
var
a: Integer;
b: Integer;
c: Integer;
begin
a := 10;
b := 5;
if a > b then
c := a - b;
end;
No exemplo anterior, é atribuído um valor às variáveis a e b. Com a instrução if, a condição que a é maior do que b é testada. Se essa condição for verdadeira, a variável c receberá o valor de a menos b.
Observe a posição do ponto e vírgula. Um ponto e vírgula indica o início de uma nova instrução. Como if ..then é considerado uma instrução, o ponto e vírgula é colocado depois da última instrução, não após a palavra-chave then.
Só é possível colocar uma instrução após a palavra-chave then. Se você desejar executar várias instruções quando a condição for verdadeira, você precisará usar uma instrução composta, conforme mostrado no exemplo a seguir.
var
a: Integer;
b: Integer;
c: Integer;
begin
a := 10;
b := 5;
if a > b then begin
c := a - b;
Message('%1', c);
end;
end;
É importante observar as posições dos diversos pontos e vírgulas após cada instrução na instrução composta e também no final da instrução composta.
A instrução If-then-else
A instrução if é frequentemente combinada com uma instrução else. Se a condição não for avaliada como verdadeira, a(s) instrução(ões) no bloco else será(ão) executada(s).
var
a: Integer;
b: Integer;
c: Integer;
begin
a := 10;
b := 5;
if a > b then
c := a - b
else
c := a + b;
end;
Não é colocado um ponto e vírgula no fim da instrução no bloco then. Ele é colocado apenas no fim da instrução if-then-else completa.
Você também pode usar instruções compostas em uma estrutura if-then-else.
var
a: Integer;
b: Integer;
c: Integer;
begin
a := 10;
b := 5;
if a > b then begin
c := a - b;
Message('%1', c);
end
else begin
c := a + b;
Message('%1', c);
end;
end;
Como uma instrução if-then-else também é uma instrução regular, você pode colocar instruções if em outras instruções if, que criarão instruções nested if.
begin
if Amount <> 0 then
if Amount > 0 then
Sales := Sales + Amount
else
if Reason = Reason::Return then
if ReasonForReturn = ReasonForReturn::Defective then
Refund := Refund + Amount
else
Credits := Credits + Amount
else
Sales := Sales - Amount;
end;
Cuidado com as instruções nested if, pois geralmente são difíceis de ler e podem ser complexas. Analisar as posições dos pontos e vírgulas pode ajudar a facilitar a leitura e a compreensão.
Usar o operador ternário
O operador ternário (? :), conhecido em outras linguagens de programação, simplifica as operações condicionais no código, melhora a legibilidade e reduz o nível de detalhes. É útil para condições simples, promovendo clareza de código e programação concentrada na intenção. Permitindo a inicialização de variáveis na mesma linha, ele garante a atribuição adequada e minimiza o comprimento do código. Nesta versão, o AL dá suporte ao operador ternário.
O operador ternário pode ser usado para atribuir um de dois valores a uma variável, dependendo da condição de uma expressão. Aqui está um exemplo de uso de if-then-else com um operador ternário.
Convenções de programação
Para implementações bem-sucedidas, siga estes princípios:
If e then devem estar na mesma linha; else deve estar em uma linha separada.
Se houver muitas expressões longas, elas deverão estar em uma nova linha e ser alinhadas com expressões if.
Ao escrever expressões if com as partes then e else, escreva-as de forma que o resultado then seja mais provável do que else.
Se a última instrução na parte then de uma instrução if-then-else for uma saída ou um erro, não continue com uma instrução else.
Instrução case
Outra instrução condicional que você pode usar é a instrução case. Dependendo do valor de uma condição, a instrução case executará outras instruções.
O próximo exemplo mostra que, dependendo do valor de Document Type (que é um campo de opção em uma tabela), a instrução case executará algumas instruções. A instrução case pode usar um bloco else que será executado quando nenhum outro bloco for executado. Como só pode executar uma instrução para cada bloco com uma instrução case, você precisa usar instruções compostas para executar mais instruções simultaneamente.
var
a: Integer;
begin
case "Document Type" of
"Document Type"::Quote:
a := 1 + 1;
"Document Type"::Order:
a := 2 + 1;
"Document Type"::Invoice:
begin
// Some statement 1;
// Some statement 2;
// Some statement 3;
a := 3 + 1;
end;
"Document Type"::"Return Order":
if Reason = Reason::Return then begin
// Some statement 1;
// Some statement 2;
// Some statement 3;
a := 4 + 1;
end;
else
a := 5 + 1;
end;
end;
As instruções case também são chamadas de instruções de várias opções e, normalmente, são usadas quando você deve escolher entre mais de duas ações diferentes. O método da declaração case é o seguinte:
A Expressão é avaliada e o primeiro conjunto de valores correspondente executa a instrução associada, se houver.
Se nenhum valor definido corresponder ao valor da expressão e a parte opcional else tiver sido omitida, nenhuma ação será executada. Se a parte opcional else for usada, a instrução associada será executada.
O tipo de dados dos conjuntos de valores deve ser o mesmo que o tipo de dados de Expressão ou, pelo menos, ser conversível para o mesmo tipo de dados.
Na maioria dos casos, o tipo de dados dos conjuntos de valores é convertido no tipo de dados da expressão avaliada. A única exceção é se a expressão avaliada for uma variável Code. Se a expressão avaliada for uma variável Code, os conjuntos de valores não serão convertidos no tipo de dados de Code.
Convenções de programação: instruções case
Ao usar uma instrução case, recue os conjuntos de valores com quatro espaços de caracteres. Se você tiver dois ou mais conjuntos de valores na mesma linha, separe-os por vírgulas sem espaços. O último valor definido em uma linha é imediatamente seguido por dois-pontos sem um espaço precedente. A ação começa na linha após o valor definido e é recuada por quatro espaços de caracteres. Se houver um início, ele deverá ser colocado em uma linha separada, a menos que siga else. Se um begin seguir um else, ele deverá estar na mesma linha que else.
Se houver mais de duas alternativas, use uma instrução case. Caso contrário, use uma instrução if-then-else.
Diretivas do pré-processador em AL
Em AL, assim como em outras linguagens de programação, as diretivas do pré-processador podem ser usadas para tornar o código condicional, suprimir avisos ou habilitar a expansão e o recolhimento no código.
As diretivas do pré-processador podem ser divididas nos grupos a seguir.
- Diretivas condicionais
- Regiões
- Pragmas
Qualquer código pode virar condicional, incluindo os campos de tabela, e ser verificado por uma diretiva condicional. Para verificar o código usando uma diretiva condicional, você deve definir um símbolo para verificar. Um símbolo retorna um valor booliano: verdadeiro ou falso.
É possível definir os símbolos no início de um arquivo de origem e o escopo do símbolo específico é o arquivo no qual ele foi definido. Você também pode definir os símbolos no arquivo app.json e, a partir disso, o escopo torna-se global para a extensão.
As diretivas condicionais do pré-processador a seguir são compatíveis com AL.
#if: especifica o início de uma cláusula condicional. A cláusula #endif a encerra. Compila o código entre as diretivas se o símbolo especificado que está sendo verificado foi definido.
#else: especifica uma cláusula condicional composta. Se nenhuma das cláusulas precedentes for avaliada como verdadeira, o compilador avaliará o código entre #else e #endif.
#elif: combina instruções else e if. Se #elif for verdadeira, o compilador avaliará todo o código entre #elif e a próxima diretiva condicional.
#endif: especifica o fim de uma cláusula condicional que começa com #if.
#define: define um símbolo que pode ser usado para especificar condições para uma compilação. Por exemplo, #define DEBUG. O escopo do símbolo é o arquivo no qual ele foi definido.
#undef: exclui a definição de um símbolo.
Os símbolos podem ser definidos globalmente no arquivo app.json. Um símbolo também pode ser definido usando a diretiva #define no código, mas se os símbolos forem definidos no arquivo app.json, eles poderão ser usados globalmente.
O exemplo a seguir define DEBUG como um símbolo global. Ele pode ser usado com base no código, conforme ilustrado no exemplo de código condicional a seguir. Um símbolo tem um valor booliano, o que significa que ele é avaliado como verdadeiro ou falso.
arquivo app.json
"preprocessorSymbols": [ "DEBUG" ]
símbolo al-code usando DEBUG
#if DEBUG
trigger OnOpenPage()
begin
Message('Only in debug versions');
end;
#endif
Suprimir avisos de AL
Em alguns casos, os avisos do compilador ou do analisador são gerados por causa do uso pretendido do código. Para reduzi-los de forma que os desenvolvedores possam se concentrar apenas nos avisos que devem ser resolvidos, incluímos o suporte para suprimir explicitamente os avisos, seja em toda a extensão ou localmente em uma delimitação de código.
Há duas maneiras de controlar os avisos:
Globalmente (em uma extensão)
Localmente
Lembre-se de que a maioria dos avisos existe por um motivo, e a supressão deles poderá levar a um impacto repentino se os avisos forem alterados para erros (como obsoletos).
Global
Há uma propriedade suppressWarnings no manifesto de app.json para que você possa suprimir uma lista separada por vírgulas de IDs de aviso ao compilar a extensão:
"suppressWarnings": [Warning ID,Warning ID2,...]
Local
As diretivas são uma nova construção em linguagem AL que especifica como o compilador AL processa uma seção delimitada de código. O mesmo conceito é conhecido em outras linguagens. As instruções específicas da diretiva devem ser compatíveis com o compilador. Não é possível criar instruções personalizadas de pré-processamento.
Uma das novas diretivas é um pragma de aviso, que pode ser definido em uma seção de código para suprimir uma lista separada por vírgulas de avisos somente dentro dessa delimitação.
Se não for inserido um pragma de fechamento, será considerado o restante do arquivo. A restauração o reverte a qualquer estado de supressão global existente, conforme descrito acima. Quando nenhum número de aviso é especificado, a desabilitação desabilita todos os avisos e a restauração habilita todos os avisos.
#pragma warning disable warning-list
#pragma warning restore warning-list