Restructure for Docsy theme

This commit is contained in:
Jeremy Vyska 2022-02-20 13:18:49 +01:00
parent f4a1ebc077
commit cceb0c945e
376 changed files with 963 additions and 186 deletions

View file

@ -0,0 +1,11 @@
+++
title = "Readability"
weight = 980
+++
## C/AL Coding Guidelines
## **Readability**
Generally, all readability rules are Microsoft style choices only. You can use them to keep consistency with the existing code.
Find the C/AL guidelines by expanding the menu in the left.

View file

@ -0,0 +1,22 @@
+++
title = "Begin as an 'After Word'"
weight = 230
+++
When BEGIN follows THEN, ELSE, DO, it should be on the same line, preceded by one space character.
Bad code
```al
IF ICPartnerRefType = ICPartnerRefType::"Common Item No." THEN
BEGIN
...
END;
```
Good code
```
IF ICPartnerRefType = ICPartnerRefType::"Common Item No." THEN BEGIN
...
END;
```

View file

@ -0,0 +1,69 @@
+++
title = "Begin-End - Compound Only"
weight = 240
+++
Only use BEGIN..END to enclose compound statements.
Bad code
```al
IF FINDSET THEN BEGIN
REPEAT
...
UNTIL NEXT = 0;
END;
```
Good code
```al
IF FINDSET THEN
REPEAT
...
UNTIL NEXT = 0;
```
Bad code
```al
IF IsAssemblyOutputLine THEN BEGIN
TESTFIELD("Order Line No.",0);
END;
```
Good code
```al
IF IsAssemblyOutputLine THEN
TESTFIELD("Order Line No.",0);
```
Bad code
```al
IF FINDSET THEN
REPEAT
BEGIN
...
END;
UNTIL NEXT = 0;
```
Good code
```al
IF FINDSET THEN
REPEAT
...
UNTIL NEXT = 0;
```
Exception
```al
// Except for this case
IF X THEN BEGIN
IF Y THEN
DO SOMETHING;
END ELSE (not X)
```

View file

@ -0,0 +1,21 @@
+++
title = "Binary Operator to Start Line"
weight = 250
+++
Do not start a line with a binary operator.
Bad code
```al
"Quantity to Ship" :=
Quantity
- "Quantity Shipped"
```
Good code
```al
"Quantity to Ship" :=
Quantity -
"Quantity Shipped"
```

View file

@ -0,0 +1,44 @@
+++
title = "Blank Lines"
weight = 260
+++
Do not use blank lines at the beginning or end of any functions, after BEGIN, before END, or inside multiline expressions.
Bad code
```al
PROCEDURE MATRIX_OnDrillDown@1133(MATRIX_ColumnOrdinal : Integer);
BEGIN
SetupDrillDownCol(MATRIX_ColumnOrdinal);
DrillDown(FALSE,ValueType);
END;
```
Good code
```al
PROCEDURE MATRIX_OnDrillDown@1133(MATRIX_ColumnOrdinal : Integer);
BEGIN
SetupDrillDownCol(MATRIX_ColumnOrdinal);
DrillDown(FALSE,ValueType);
END;
```
Bad code
```al
IF NameIsValid AND
Name2IsValid
THEN
```
Good code
```al
IF NameIsValid AND
Name2IsValid
THEN
```

View file

@ -0,0 +1,23 @@
+++
title = "CASE Action"
weight = 310
+++
A CASE action should start on a line after the possibility.
Bad code
```al
CASE Letter OF
'A': Letter2 := '10';
'B': Letter2 := '11';
```
Good code
```al
CASE Letter OF
'A':
Letter2 := '10';
'B':
Letter2 := '11';
```

View file

@ -0,0 +1,21 @@
+++
title = "Colon usage in CASE"
weight = 340
+++
The last possibility on a CASE statement must be immediately followed by a colon.
Bad code
```al
CASE DimOption OF
DimOption::"Global Dimension 1" :
DimValue."Dimension Code" := GLSetup."Global Dimension 1 Code";
```
Good code
```al
CASE DimOption OF
DimOption::"Global Dimension 1":
DimValue."Dimension Code" := GLSetup."Global Dimension 1 Code";
```

View file

@ -0,0 +1,46 @@
+++
title = "Comments inside Curly Brackets"
weight = 350
+++
Never use curly bracket comments. During development, the "Block comment" functionality can be used instead. However, in production code, block comments are not recommended.
Bad code
```al
PeriodTxt: {Period}
```
Good code
```al
PeriodTxt: // Period
```
Bad code
```al
PROCEDURE MATRIX_OnAfterGetRecord@10(MATRIX_ColumnOrdinal : Integer);
BEGIN
{
IF ShowColumnName THEN
MatrixHeader := MatrixRecords[MATRIX_ColumnOrdinal].Name
ELSE
MatrixHeader := MatrixRecords[MATRIX_ColumnOrdinal].Code;
}
MatrixRecord := MatrixRecords[MATRIX_ColumnOrdinal];
AnalysisValue := CalcAmt(ValueType,TRUE);
MATRIX_CellData[MATRIX_ColumnOrdinal] := AnalysisValue;
END;
```
Good code
```al
PROCEDURE MATRIX_OnAfterGetRecord@10(MATRIX_ColumnOrdinal : Integer);
BEGIN
MatrixRecord := MatrixRecords[MATRIX_ColumnOrdinal];
AnalysisValue := CalcAmt(ValueType,TRUE);
MATRIX_CellData[MATRIX_ColumnOrdinal] := AnalysisValue;
END;
```

View file

@ -0,0 +1,18 @@
+++
title = "Comment Spacing"
weight = 360
+++
Always start comments with // followed by one space character.
Bad code
```al
RowNo += 1000; //Move way below the budget
```
Good code
```al
RowNo += 1000; // Move way below the budget
```

View file

@ -0,0 +1,26 @@
+++
title = "END ELSE Pair"
weight = 540
+++
The END ELSE pair should always appear on the same line.
Bad code
```al
IF OppEntry.FIND('-') THEN
IF SalesCycleStage.FIND('-') THEN BEGIN
...
END
ELSE
...
```
Good code
```al
IF OppEntry.FIND('-') THEN
IF SalesCycleStage.FIND('-') THEN BEGIN
...
END ELSE
...
```

View file

@ -0,0 +1,112 @@
+++
title = "Indentation"
weight = 650
+++
In general, use an indentation of two space characters. Logical expressions in the IF, WHILE, and UNTIL parts are indented at least 3, 6, and 6 spaces respectively.
Bad code
```al
IF GLSetup."Unrealized VAT" OR
(GLSetup."Prepayment Unrealized VAT" AND NewCVLedgEntryBuf.Prepayment)
```
Good code
```al
IF GLSetup."Unrealized VAT" OR
(GLSetup."Prepayment Unrealized VAT" AND NewCVLedgEntryBuf.Prepayment)
```
Bad code
```al
IF GenJnlLine."Account No." <> ICPartner.Code THEN
ICPartner.GET("Account No.");
IF GenJnlLine.Amount \> 0 THEN BEGIN
...
```
Good code
```al
IF GenJnlLine."Account No." <> ICPartner.Code THEN
ICPartner.GET("Account No.");
IF GenJnlLine.Amount > 0 THEN BEGIN
...
```
Bad code
```al
Dialog.OPEN(WindowTxt +
'@1@@@@@@@@@@@@@@@@@@@@@@@');
```
Good code
```al
Dialog.OPEN(
WindowTxt +
'@1@@@@@@@@@@@@@@@@@@@@@@@');
```
Bad code
```al
TempOldCustLedgEntry.DELETE;
// Find the next old entry for application of the new entry
```
Good code
```al
TempOldCustLedgEntry.DELETE;
// Find the next old entry for application of the new entry
```
Bad code
```al
IF NOT ("Applies-to Doc. Type" IN
["Applies-to Doc. Type"::Receipt,
"Applies-to Doc. Type"::"Return Shipment"])
```
Good code
```al
IF NOT ("Applies-to Doc. Type" IN
["Applies-to Doc. Type"::Receipt,
"Applies-to Doc. Type"::"Return Shipment"])
```
Bad code
```al
WHILE (RemAmt > 0) OR
(RemAmtLCY > 0)
DO
```
Good code
```al
WHILE (RemAmt > 0) OR
(RemAmtLCY > 0)
DO
```
Bad code
```al
UNTIL (RemAmt > 0) AND
(RemAmtLCY > 0);
```
Good code
```al
UNTIL (RemAmt > 0) AND
(RemAmtLCY > 0)
```

View file

@ -0,0 +1,20 @@
+++
title = "Keyword Pairs - Indentation"
weight = 730
+++
The IF..THEN pair, WHILE..DO pair, and FOR..DO pair must appear on the same line or the same level of indentation.
Bad code
```al
IF (x = y) AND
(a = b) THEN
```
Good code
```al
IF (x = y) AND
(a = b)
THEN
```

View file

@ -0,0 +1,26 @@
+++
title = "Line Start Keywords"
weight = 740
+++
The END, IF, REPEAT, FOR, WHILE, ELSE and CASE statement should always start a line.
Bad code
```al
IF IsContactName THEN ValidateContactName
ELSE IF IsSalespersonCode THEN ValidateSalespersonCode
ELSE IF IsSalesCycleCode THEN ValidatSalesCycleCode;
```
Good code
```al
IF IsContactName THEN
ValidateContactName
ELSE
IF IsSalespersonCode THEN
ValidateSalespersonCode
ELSE
IF IsSalesCycleCode THEN
ValidatSalesCycleCode;
```

View file

@ -0,0 +1,20 @@
+++
title = "Lonely Repeat"
weight = 760
+++
The REPEAT statement should always be alone on a line.
Bad code
```al
IF ReservEntry.FINDSET THEN REPEAT
```
Good code
```al
IF ReservEntry.FINDSET THEN
REPEAT
```

View file

@ -0,0 +1,18 @@
+++
title = "Named Invocations"
weight = 830
+++
When calling an object statically use the name, not the number
Bad code
```al
PAGE.RUNMODAL(525,SalesShptLine)
```
Good code
```al
PAGE.RUNMODAL(PAGE::"Posted Sales Shipment Lines",SalesShptLine)
```

View file

@ -0,0 +1,26 @@
+++
title = "Nested WITHs"
weight = 850
+++
Do not nest WITHs that reference different types of objects.
Bad code
```al
WITH PostedWhseShptLine DO BEGIN
...
WITH ItemLedgEntry DO
InsertBufferRec(...,"Serial No.","Lot No.",...);
...
END;
```
Good code
```al
WITH PostedWhseShptLine DO BEGIN
...
InsertBufferRec(...,ItemLedgEntry."Serial No.",ItemLedgEntry."Lot No.",...);
...
END;
```

View file

@ -0,0 +1,36 @@
+++
title = "One Statement Per Line"
weight = 910
+++
A line of code should not have more than one statement.
Bad code
```al
IF OppEntry.FIND('-') THEN EXIT
```
Good code
```al
IF OppEntry.FIND('-') THEN
EXIT
```
Bad code
```al
TotalCost += Cost; TotalAmt += Amt;
```
Good code
```al
TotalCost += Cost;
TotalAmt += Amt;
```

View file

@ -0,0 +1,23 @@
+++
title = "Separate IF and ELSE"
weight = 1050
+++
IF and ELSE statements should be on separate lines.
Bad code
```al
IF Atom[i+1] = '>' THEN HasLogicalOperator := TRUE ELSE BEGIN
...
END;
```
Good code
```al
IF Atom[i+1] = '>' THEN
HasLogicalOperator := TRUE
ELSE BEGIN
...
END;
```

View file

@ -0,0 +1,46 @@
+++
title = "Spacing Binary Operators"
weight = 1120
+++
There must be exactly one space character on each side of a binary operator such as = + - AND OR =. The parameter comma operator however, should have no spaces.
Bad code
```al
"Line Discount %" := "Line Discount Amount"/"Line Value"*100
```
Good code
```al
"Line Discount %" := "Line Discount Amount" / "Line Value" * 100;
```
Bad code
```al
StartDate := CALCDATE('<+'+FORMAT(Days + i)+'D>', StartDate);
```
Good code
```al
StartDate := CALCDATE('<+' + FORMAT(Days + i) + 'D>',StartDate);
```
Bad code
```al
StartDate := 0D; // Initialize
```
Good code
```al
StartDate := 0D; // Initialize
```

View file

@ -0,0 +1,46 @@
+++
title = "Spacing Brackets and ::"
weight = 1130
+++
There must be no spaces characters before and after [] dimension brackets symbols or :: option symbols.
Bad code
```al
A[i] [j] := Amt;
```
Good code
```al
A[i][j] := Amt;
```
Bad code
```al
"Currency Exchange Rate"."Fix Exchange Rate Amount" :: Currency:
```
Good code
```al
"Currency Exchange Rate"."Fix Exchange Rate Amount"::Currency:
```
Bad code
```al
IF FIND (Which) THEN
```
Good code
```al
IF FIND(Which) THEN
```

View file

@ -0,0 +1,32 @@
+++
title = "Spacing Unary Operators"
weight = 1140
+++
There must be no space between a unary operator and its argument (except for the NOT keyword).
Bad code
```al
IF NOT(Type = Type::Item) THEN
```
Good code
```al
IF NOT (Type = Type::Item) THEN
```
Bad code
```al
DiscAmt := - "Discount Amount";
```
Good code
```al
DiscAmt := -"Discount Amount";
```

View file

@ -0,0 +1,31 @@
+++
title = "Temporary Variable Naming"
weight = 1200
+++
The name of a temporary variable must be prefixed with the word Temp and not otherwise.
Bad code
```al
JobWIPBuffer@1002 : TEMPORARY Record 1018;
```
Good code
```al
TempJobWIPBuffer@1002 : TEMPORARY Record 1018;
```
Bad code
```al
TempJobWIPBuffer@1002 : Record 1018;
```
Good code
```al
CopyOfJobWIPBuffer@1002 : Record 1018;
```

View file

@ -0,0 +1,115 @@
+++
title = "TextConst Suffixes"
weight = 1210
+++
TextConst variable names should have a suffix (an approved three-letter suffix: Msg, Tok, Err, Qst, Lbl, Txt) describing usage.
Bad code
```al
CannotDeleteLine@1005 : TextConst 'ENU=You cannot delete this line because one or more rating values exists.';
...
ERROR(CannotDeleteLine,TABLECAPTION);
```
Good code
```al
CannotDeleteLineErr@1005 : TextConst 'ENU=You cannot delete this line because one or more rating values exists.';
...
ERROR(CannotDeleteLineErr,TABLECAPTION);
```
Bad code
```al
Text000@1011 : TextConst 'ENU="has been changed (initial a %1: %2= %3, %4= %5)"';
...
SalesLine.FIELDERROR(Type,STRSUBSTNO(Text000,...);
...
```
Good code
```al
TypeHasBeenChangedErr@1011 : TextConst 'ENU="has been changed (initial a %1: %2= %3, %4= %5)"';
...
SalesLine.FIELDERROR(Type,STRSUBSTNO(TypeHasBeenChangedErr,...);
...
```
Bad code
```al
Text004@1004 : TextConst 'ENU=Indenting the Job Tasks \#1\#\#\#\#\#\#\#\#\#\#.';
...
Window@1007 : Dialog;
...
Window.OPEN(Text004);
```
Good code
```al
IndentingMsg@1004 : TextConst 'ENU=Indenting the Job Tasks \#1\#\#\#\#\#\#\#\#\#\#.';
...
Window@1007 : Dialog;
...
Window.OPEN(IndentingMsg);
```
Bad code
```al
Text002@1005 : TextConst 'ENU=You cannot delete a %1 that is used in one or more setup windows.\\ Do you want to open the G/L Account No. Where-Used List Window?';
...
IF CONFIRM(Text002,TRUE,GLAcc.TABLECAPTION) THEN
```
Good code
```al
OpenWhereUsedWindowQst@1005 : TextConst 'ENU=You cannot delete a %1 that is used in one or more setup windows.\\ Do you want to open the G/L Account No. Where-Used List Window?';
...
IF CONFIRM(OpenWhereUsedWindowQst,TRUE,GLAcc.TABLECAPTION) THEN
```
Bad code
```al
Selection := STRMENU(Text003,2);
...
Text003@1002 : TextConst 'ENU=&Copy dimensions from BOM,&Retrieve dimensions from components';
```
Good code
```al
Selection := STRMENU(CopyFromQst,2);
...
CopyFromQst@1002 : TextConst 'ENU=&Copy dimensions from BOM,&Retrieve dimensions from components';
```
Bad code
```al
DATASET
{
...
{ 1 ;1 ;Column ;Chart_of_AccountsCaption;
SourceExpr=Chart_of_AccountsCaption }
...
Chart_of_AccountsCaption@9647 : TextConst 'ENU=Chart of Accounts';
```
Good code
```al
DATASET
{
...
{ 1 ;1 ;Column ;Chart_of_AccountsCaption;
SourceExpr=ChartOfAccountsLbl }
...
ChartOfAccountsLbl@9647 : TextConst 'ENU=Chart of Accounts';
```

View file

@ -0,0 +1,19 @@
+++
title = "Unary Operator Line End"
weight = 1250
+++
Do not end a line with unary operator.
Bad code
```al
"Quantity Handled (Base)" := -
"Quantity Handled (Base)");
```
Good code
```al
"Quantity Handled (Base)" :=
- "Quantity Handled (Base)");
```

View file

@ -0,0 +1,32 @@
+++
title = "Unnecessary Compound Parenthesis"
weight = 1260
+++
Use parenthesis only to enclose compound expressions inside compound expressions.
Bad code
```al
IF ("Costing Method" = "Costing Method"::Standard) THEN
```
Good code
```al
IF "Costing Method" = "Costing Method"::Standard THEN
```
Bad code
```al
ProfitPct = -(Profit) / CostAmt * 100;
```
Good code
```al
ProfitPct = -Profit / CostAmt * 100;
```

View file

@ -0,0 +1,22 @@
+++
title = "Unnecessary ELSE"
weight = 1270
+++
ELSE should not be used when the last action in the THEN part is an EXIT, BREAK, SKIP, QUIT, ERROR.
Bad code
```al
IF IsAdjmtBinCodeChanged THEN
ERROR(AdjmtBinCodeChangeNotAllowedErr,...)
ELSE
ERROR(BinCodeChangeNotAllowedErr,...);
```
Good code
```al
IF IsAdjmtBinCodeChanged THEN
ERROR(AdjmtBinCodeChangeNotAllowedErr,...)
ERROR(BinCodeChangeNotAllowedErr,...);
```

View file

@ -0,0 +1,32 @@
+++
title = "Unnecessary Function Parenthesis"
weight = 1280
+++
Do not use parenthesis in a function call if the function does not have any parameters.
Bad code
```al
IF ReservMgt.IsPositive() THEN
```
Good code
```al
IF ReservMgt.IsPositive THEN
```
Bad code
```al
IF ChangeStatusForm.RUNMODAL() <> ACTION::Yes THEN
```
Good code
```al
IF ChangeStatusForm.RUNMODAL <> ACTION::Yes THEN
```

View file

@ -0,0 +1,18 @@
+++
title = "Unnecessary Separators"
weight = 1290
+++
There should be no unnecessary separators.
Bad code
```al
IF Customer.FINDFIRST THEN;;
```
Good code
```al
IF Customer.FINDFIRST THEN;
```

View file

@ -0,0 +1,32 @@
+++
title = "Unnecessary TRUE/FALSE"
weight = 1300
+++
Do not use TRUE or FALSE keywords unnecessarily if the expression is already an logical expression.
Bad code
```al
IF IsPositive() = TRUE THEN
```
Good code
```al
IF IsPositive THEN
```
Bad code
```
IF Complete <> TRUE THEN
```
Good code
```al
IF NOT Complete THEN
```

View file

@ -0,0 +1,39 @@
+++
title = "Variable Already Scoped"
weight = 1400
+++
Do not use scope ''.'' qualifier unnecessarily when a variable is already implicitly or explicitly scoped. It keeps the code simpler.
Bad code
```al
ReturnRcptHeader.SETRANGE(ReturnRcptHeader."Return Order No.","Document No.");
```
Good code
```al
ReturnRcptHeader.SETRANGE("Return Order No.","Document No.");
```
Bad code
```al
WITH ChangeLogSetupTable DO BEGIN
...
IF ChangeLogSetupTable.DELETE THEN
...
END;
```
Good code
```al
WITH ChangeLogSetupTable DO BEGIN
...
IF DELETE THEN
...
END;
```

View file

@ -0,0 +1,69 @@
+++
title = "Variable Naming"
weight = 1420
+++
Variables that refer to a C/AL object must contain the objects name, abbreviated where necessary.
A variable must begin with a capital letter.
Blanks, periods, and other characters (such as parentheses) that would make quotation marks around a variable necessary must be omitted.
If a variable is a compound of two or more words or abbreviations, each word or abbreviation should begin with a capital letter.
Bad code
```al
...
WIPBuffer@1002 : Record 1018
...
OBJECT Table Job WIP Buffer
```
Good code
```al
...
JobWIPBuffer@1002 : Record 1018
...
OBJECT Table Job WIP Buffer
```
Bad code
```al
...
Postline@1004 : Codeunit 12;
...
OBJECT Codeunit Gen. Jnl.-Post Line
```
Good code
```al
...
GenJnlPostLine@1004 : Codeunit 12;
...
OBJECT Codeunit Gen. Jnl.-Post Line
```
Bad code
```al
LOCAL PROCEDURE HandleCustDebitCredit@17(...;"Amount (LCY)"@1001 : Decimal;...);
BEGIN
IF ((... ("Amount (LCY)" \> 0)) ...) OR
((... ("Amount (LCY)" < 0)) ...)
THEN BEGIN
...
```
Good code
```al
LOCAL PROCEDURE HandleCustDebitCredit@17(...;AmountLCY@1001 : Decimal;...);
BEGIN
IF ((... (AmountLCY \> 0)) ...) OR
((... (AmountLCY < 0)) ...)
THEN BEGIN
...
```

View file

@ -0,0 +1,19 @@
+++
title = "Variables Declarations Order"
weight = 1430
+++
Variables declarations should be ordered by type. In general, object and complex variable types are listed first followed by simple variables. The order should be the same as the object list in the object designer for C/AL objects. Afterwards come the complex variables like RecordRef, .NET, FieldRef etc. At the end come all the simple data types in no particular order.
Bad code
```al
StartingDateFilter@1002 : Text[30];
Vend@1003 : Record 23;
```
Good code
```al
Vend@1003 : Record 23;
StartingDateFilter@1002 : Text[30];
```