From 3661c16c806de9cbc358e9a7a06c7882dc6be143 Mon Sep 17 00:00:00 2001 From: Christoph Krieg Date: Mon, 27 Jun 2022 19:17:15 +0200 Subject: [PATCH] if not then exit --- .../if-not-find-then-exit/index.md | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 content/docs/BestPractices/if-not-find-then-exit/index.md diff --git a/content/docs/BestPractices/if-not-find-then-exit/index.md b/content/docs/BestPractices/if-not-find-then-exit/index.md new file mode 100644 index 00000000..0ca77802 --- /dev/null +++ b/content/docs/BestPractices/if-not-find-then-exit/index.md @@ -0,0 +1,99 @@ +--- +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 + SalesHeader.Reset(); + SalesHeader.SetRange("Document Type", SalesHeader."Document Type"::Order); + SalesHeader.SetRange(Status, SalesHeader.Status::Open); + if (not SalesHeader.FindSet(false)) then + exit; + + 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 (not SalesLine.FindSet(true)) then + exit; + + repeat + case SalesLine."Type" of + SalesLine."Type"::Item: + DoSomethingItem(); + SalesLine."Type"::Resource: + DoSomethingResource(); + end; + until SalesLine.Next() = 0; +``` \ No newline at end of file