111 lines
No EOL
3.6 KiB
Markdown
111 lines
No EOL
3.6 KiB
Markdown
---
|
|
title: "if not then exit"
|
|
tags: ["AL"]
|
|
categories: ["Best Practice"]
|
|
---
|
|
|
|
_Created by sirhc101, Described by sirhc101_
|
|
|
|
## Description
|
|
|
|
In general when we are working with tables we want to make sure, the filtered dataset includes records and does not result in a runtime error, so we use `if` to handle the result of `Find()`, `FindSet()`, `Get()`, etc.
|
|
This automatically causes on indent in source code and often the source code does not just contain one but two or more tables involved which leads to multi-level indentation.
|
|
|
|
Basically this is a result of bad coding structure but maybe sometimes necessary. On the other hand this causes multiple `end;` usages and leads to the usage of colorization and other helpers to see which `begin` belongs to which `end;`.
|
|
|
|
Instead of using `if (Record.FindSet()) then` to fetch records from a database it's good practice to use `if (not Record.FindSet()) then` following by an `exit();` to not further process the source code and make it clear for other developers where they can stop reading in certain cases.
|
|
|
|
Furthermore, this more or less automatically leads to smaller and better structured procedures and reduces the complexity of the source code.
|
|
|
|
## Bad code
|
|
|
|
```al
|
|
SalesHeader.Reset();
|
|
SalesHeader.SetRange("Document Type", SalesHeader."Document Type"::Order);
|
|
SalesHeader.SetRange(Status, SalesHeader.Status::Open);
|
|
if (SalesHeader.FindSet(false)) then begin
|
|
repeat
|
|
SalesLine.Reset();
|
|
SalesLine.SetRange("Document Type", SalesHeader."Document Type"::Order);
|
|
SalesLine.SetRange("Document No.", SalesHeader."No.");
|
|
if (SalesLine.FindSet(true)) then begin
|
|
repeat
|
|
DoSomething();
|
|
until SalesLine.Next() = 0;
|
|
end;
|
|
until SalesHeader.Next() = 0;
|
|
|
|
DoSomethingElse();
|
|
end;
|
|
```
|
|
|
|
or
|
|
|
|
```al
|
|
SalesLine.Reset();
|
|
SalesLine.SetRange("Document Type", SalesHeader."Document Type"::Order);
|
|
if (SalesLine.FindSet(true)) then begin
|
|
repeat
|
|
case SalesLine."Type" of
|
|
SalesLine."Type"::Item:
|
|
DoSomethingItem();
|
|
SalesLine."Type"::Resource:
|
|
DoSomethingResource();
|
|
end;
|
|
until SalesLine.Next() = 0;
|
|
end;
|
|
```
|
|
|
|
## Good code
|
|
|
|
```al
|
|
procedure DoSomethingSalesOrder()
|
|
var
|
|
SalesHeader: Record "Sales Header";
|
|
begin
|
|
SalesHeader.Reset();
|
|
SalesHeader.SetRange("Document Type", SalesHeader."Document Type"::Order);
|
|
SalesHeader.SetRange(Status, SalesHeader.Status::Open);
|
|
if (not SalesHeader.FindSet(false)) then
|
|
exit;
|
|
|
|
repeat
|
|
DoSomethingSalesLine(SalesHeader);
|
|
until SalesHeader.Next() = 0;
|
|
|
|
DoSomethingElse();
|
|
end;
|
|
|
|
procedure DoSomethingSalesLine(var SalesHeader: Record "Sales Header")
|
|
var
|
|
SalesLine: Record "Sales Line";
|
|
begin
|
|
SalesLine.Reset();
|
|
SalesLine.SetRange("Document Type", SalesHeader."Document Type"::Order);
|
|
SalesLine.SetRange("Document No.", SalesHeader."No.");
|
|
if (not SalesLine.FindSet(true)) then
|
|
exit;
|
|
|
|
repeat
|
|
DoSomething();
|
|
until SalesLine.Next() = 0;
|
|
end;
|
|
```
|
|
|
|
or
|
|
|
|
```al
|
|
SalesLine.Reset();
|
|
SalesLine.SetRange("Document Type", SalesHeader."Document Type"::Order);
|
|
if (not SalesLine.FindSet(true)) then
|
|
exit;
|
|
|
|
repeat
|
|
case SalesLine."Type" of
|
|
SalesLine."Type"::Item:
|
|
DoSomethingItem();
|
|
SalesLine."Type"::Resource:
|
|
DoSomethingResource();
|
|
end;
|
|
until SalesLine.Next() = 0;
|
|
``` |