Trabajar con instrucciones condicionales

Completado

Las instrucciones condicionales se usan con frecuencia en los lenguajes de programación, incluido el lenguaje de aplicación (AL). Una instrucción condicional se utiliza para probar una condición. Según la evaluación de dicha condición, se podrían ejecutar una o varias instrucciones.

Instrucciones if

La instrucción condicional más utilizada es la instrucción if.

var 
    a: Integer;
    b: Integer;
    c: Integer;
begin
    a := 10;
    b := 5;

    if a > b then
        c := a - b;
end;

En el ejemplo anterior a las variables a y b se les asigna un valor. Con la instrucción if, se prueba si a es mayor que b. Si esta condición es true, a la variable c se le asignará el valor a menos b.

Observe la posición del punto y coma. Un punto y coma indica el inicio de una nueva instrucción. Dado que if .. then se considera una instrucción, el punto y coma se coloca después de la última instrucción, no después de la palabra clave then.

Solo puede introducir una instrucción después de la palabra clave then. Si desea ejecutar varias instrucciones cuando la condición es true, debe usar una instrucción compuesta, tal y como se muestra en el siguiente ejemplo.

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;

Es importante tener en cuenta las posiciones de los diferentes puntos y comas después de cada instrucción dentro de la instrucción compuesta, y también al final de la misma.

Instrucción If-then-else

La instrucción if suele combinarse con una instrucción else. Si la condición no se evalúa como true, se ejecutarán las instrucciones en el bloque else.

var
    a: Integer;
    b: Integer;
    c: Integer;
begin
    a := 10;
    b := 5;

    if a > b then
        c := a - b
    else
        c := a + b;
end;

No se coloca ningún punto y coma al final de la instrucción en el bloque then; solo se coloca uno al final de la instrucción completa if-then-else.

También puede usar instrucciones compuestas en una estructura 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;

Dado que una instrucción if-then-else también es una instrucción normal, puede introducir instrucciones if en otras instrucciones if, creando así instrucciones 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;

Debe usar instrucciones nested if con precaución, ya que son difíciles de leer y pueden resultar complejas. Algo que puede ayudar a comprenderlas es fijarse en la posición de los puntos y coma.

Uso del operador ternario

El operador ternario (? :), de otros lenguajes de programación, simplifica las operaciones condicionales en el código, mejora la legibilidad y contribuye a reducir las expresiones empleadas. Resulta útil para condiciones simples, contribuye a que el código sea fácil de entender y permite programar de un modo centrado en el objetivo. Permite inicializar variables dentro de la misma línea, lo que garantiza una asignación correcta y minimiza la longitud del código. Con esta versión, el operador ternario se puede usar en AL.

Se puede usar el operador ternario para asignar uno de dos valores posibles a una variable, en función de la condición de una expresión. A continuación, puede ver un ejemplo de "if-then-else" con un operador ternario.

Convenciones de programación

Para implementar correctamente, siga estos principios:

  • Las instrucciones if y then deben estar en la misma línea; else debería estar en una línea separada.

  • Si hay muchas expresiones o si las expresiones son largas, deberían estar en una nueva línea y alinearse con las expresiones if.

  • Cuando escriba expresiones if con partes que incluyan then y else, escríbalas de modo que el resultado de then sea más probable que el de else.

  • Si la última instrucción en la parte THEN de una instrucción IF/THEN/ELSE es una salida o un error, no siga con una instrucción ELSE.

Instrucción CASE

Otra instrucción condicional que puede usar es la instrucción case. En función del valor de una condición, la instrucción case ejecutará otras instrucciones.

En el siguiente ejemplo se muestra que, en función del valor de Document Type (que es un campo de opción de una tabla), la instrucción case ejecutará algunas instrucciones. La instrucción case puede usar un bloque else que se ejecutará cuando no se ejecuten otros bloques. Dado que solo puede ejecutar una instrucción para cada bloque con una instrucción case, debe usar instrucciones compuestas para ejecutar más instrucciones de forma simultánea.

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;

Las instrucciones CASE también se denominan instrucciones multiopción, y normalmente se usan cuando debe elegir entre más de dos acciones diferentes. El método de la instrucción CASE es el siguiente:

  • La expresión se evalúa y el primer conjunto de valores coincidentes ejecuta la instrucción asociada, si existe.

  • Si no hay ningún conjunto de valores que coincida con el valor de la expresión y se ha omitido la parte ELSE opcional, no se lleva a cabo ninguna acción. Si se utiliza la parte ELSE opcional, se ejecuta la instrucción asociada.

El tipo de datos de los conjuntos de valores debe ser el mismo que el tipo de datos de la expresión o, al menos, ser convertible al mismo tipo de datos.

En la mayoría de los casos, el tipo de datos de los conjuntos de valores se convierte al tipo de datos de la expresión evaluada. La única excepción es si la expresión evaluada es una variable Code. Si la expresión evaluada es una variable Code, los conjuntos de valores no se convierten al tipo de datos Code.

Convenciones de programación: instrucciones CASE

Cuando utilice una instrucción CASE, aplique una sangría a los conjuntos de valores con espacios de cuatro caracteres. Si tiene dos o más conjuntos de valores en la misma línea, sepárelos con comas sin espacios. El último valor establecido en una línea va seguido inmediatamente por dos puntos, sin un espacio anterior. La acción comienza en la línea después del valor establecido y se sangra con espacios de cuatro caracteres. Si hay un inicio, debe colocarse en una línea separada, a menos que siga a ELSE. Si un inicio viene después de un ELSE, debería estar en la misma línea que ELSE.

Si hay más de dos alternativas, utilice una instrucción CASE. De lo contrario, utilice una instrucción IF/THEN/ELSE

Directivas de preprocesador en AL

En AL, al igual que en otros lenguajes de programación, las directivas de preprocesador se pueden usar para condicionar el código, suprimir advertencias o habilitar la expansión y el colapso del código.

Las directivas de preprocesador se pueden dividir en los siguientes grupos.

  • Directivas condicionales
  • Regiones
  • Pragmas

Cualquier código puede hacerse condicional, incluidos los campos de la tabla, y verificarse mediante una directiva condicional. Para comprobar un código usando una directiva condicional, debe definir un símbolo para comprobar. Un símbolo devuelve un valor booleano; true o false.

Los símbolos se pueden definir al principio de un archivo fuente y el alcance del símbolo específico es el archivo en el que se define. También puede definir símbolos en el archivo app.json y entonces el alcance es global para la extensión.

Las siguientes directivas de preprocesador condicional son compatibles con AL.

  • #if: especifica el comienzo de una cláusula condicional. La cláusula #endif la finaliza. Compila el código entre las directivas si se define el símbolo especificado que se está marcando.

  • #else: especifica una cláusula condicional compuesta. Si ninguna de las cláusulas anteriores se evalúa como true, el compilador evaluará el código entre #else y #endif.

  • #elif: combina instrucciones else e if. Si #elif es true, el compilador evalúa todo el código entre #elif y la siguiente directiva condicional.

  • #endif: especifica el final de una cláusula condicional que comienza con #if.

  • #define: define un símbolo que se puede usar para especificar las condiciones de una compilación. Por ejemplo, #define DEBUG. El alcance del símbolo es el archivo en el que se definió.

  • #undef: anula la definición de un símbolo.

Los símbolos se pueden definir globalmente en el archivo app.json. Un símbolo también se puede definir usando la directiva #define en el código, pero si los símbolos se definen en el archivo app.json, se pueden usar globalmente.

En el siguiente ejemplo se define DEBUG como símbolo global. Esto se puede usar posteriormente desde el código como se ilustra en el ejemplo de código condicional que figura a continuación. Un símbolo tiene un valor booleano, lo que significa que se evalúa como true o false.

app.json file

"preprocessorSymbols": [ "DEBUG" ]

al-code usando el símbolo de DEPURACIÓN

#if DEBUG
    trigger OnOpenPage()
    begin
        Message('Only in debug versions');
    end;
#endif

Suprimir advertencias de AL

En algunos casos, las advertencias del compilador o del analizador se deben al uso previsto del código. Para reducir el desorden de modo que los desarrolladores puedan centrarse en las advertencias que deben atenderse, hemos añadido soporte para suprimir explícitamente las advertencias, tanto para una extensión completa como de forma local en una carcasa de código.

Hay dos maneras de admitir las advertencias:

  • Globalmente (para una extensión)

  • Localmente

Recuerde que la mayoría de las advertencias están ahí por una razón: suprimirlas podría provocar un impacto repentino si se convierten en errores (como las relacionadas con la obsolescencia).

Global

Hay una propiedad suppressWarnings en el manifiesto app.json para suprimir una lista separada por comas de id. de advertencia al compilar la extensión:

"suppressWarnings": [Warning ID,Warning ID2,...]

Local

Directivas es una nueva construcción en el lenguaje AL que especifica la manera en que el compilador AL trata una sección de código adjunta. El mismo concepto se conoce en otros lenguajes. Las instrucciones específicas de la directiva deben ser compatibles con el compilador. No puede crear instrucciones de preprocesamiento personalizadas.

Una de las nuevas directivas es una pragma de advertencia, que puede configurar alrededor de una sección de código para suprimir una lista de advertencias separadas por comas solo en esa carcasa.

Si no se proporciona un cierre pragma, será el resto del archivo. La restauración lo devuelve al estado de supresión global, tal y como se ha descrito anteriormente. Cuando no se especifican números de advertencia, Desactivar deshabilita todas las advertencias y Restaurar habilita todas las advertencias.

#pragma warning disable warning-list
#pragma warning restore warning-list