formatted nav patterns 2 to 4

This commit is contained in:
christianbraeunlich 2022-02-05 19:44:44 +01:00
parent 2fad891a77
commit f1f4aab1d7
55 changed files with 788 additions and 506 deletions

View file

@ -18,8 +18,6 @@ If the table is empty, it means that either the upgrade has run, or there was no
**Solution:** if using an upgrade table, always validate that the table contains data before doing anything.
****
### Upgrade code, can it be rerun safely?
**Problem**: if the upgrade code is not written in a way that makes it runnable twice ([idempotent][anchor1]), then several failures can happen, including something as critical as data corruption.

View file

@ -8,18 +8,18 @@ Unintentional value changes might propagate. Also, it might lead people to belie
Bad code
LOCAL PROCEDURE ShowMessage@15(VAR Text@1000 : Text\[250\]);
LOCAL PROCEDURE ShowMessage@15(VAR Text@1000 : Text[250]);
BEGIN
Text := GetMessageText;
IF (Text <\> '') AND GenJnlLineInserted THEN
MESSAGE(Text);
Text := GetMessageText;
IF (Text <> '') AND GenJnlLineInserted THEN
MESSAGE(Text);
END;
Good code
LOCAL PROCEDURE ShowMessage@15(Text@1000 : Text\[250\]);
LOCAL PROCEDURE ShowMessage@15(Text@1000 : Text[250]);
BEGIN
Text := GetMessageText;
IF (Text <\> '') AND GenJnlLineInserted THEN
MESSAGE(Text);
Text := GetMessageText;
IF (Text <> '') AND GenJnlLineInserted THEN
MESSAGE(Text);
END;

View file

@ -6,7 +6,7 @@ Do not write functions that have high class coupling. This makes the code hard t
Bad code
Any procedure / trigger that has class coupling of \> 30
Any procedure / trigger that has class coupling of > 30

View file

@ -6,7 +6,7 @@ Do not write functions that have high cyclomatic complexity. This makes the code
Bad code
Any procedure / trigger that has a cyclomatic complexity \> 25, using the CC3 version mentioned in [this article][anchor0].
Any procedure / trigger that has a cyclomatic complexity > 25, using the CC3 version mentioned in [this article][anchor0].

View file

@ -7,23 +7,23 @@ FINDSET, FIND('+') or FIND('-') should only be used when NEXT is used and vice v
Bad code
IF Cust.FIND('-') THEN
ERROR(CustIsBlockErr)
ERROR(CustIsBlockErr)
Good code
IF Cust.FINDFIRST THEN
ERROR(CustIsBlockErr)
ERROR(CustIsBlockErr)
Bad code
IF Cust.FINDFIRST THEN
REPEAT
...
UNTIL Cust.NEXT = 0;
REPEAT
...
UNTIL Cust.NEXT = 0;
Good code
IF Cust.FINDSET THEN
REPEAT
...
UNTIL Cust.NEXT = 0;
REPEAT
...
UNTIL Cust.NEXT = 0;

View file

@ -8,25 +8,25 @@ Bad code
PROCEDURE SetPurchLine@22(VAR CurrentPurchLine@1000 : Record 39);
VAR
Pegging@1001 : Boolean;
Pegging@1001 : Boolean;
BEGIN
IF Pegging THEN
CurrQuantity := CurrentPurchLine."Quantity (Base)"
ELSE
CurrQuantity := CurrentPurchLine."Outstanding Qty. (Base)";
IF Pegging THEN
CurrQuantity := CurrentPurchLine."Quantity (Base)"
ELSE
CurrQuantity := CurrentPurchLine."Outstanding Qty. (Base)";
END;
Good code
PROCEDURE SetPurchLine@22(VAR CurrentPurchLine@1000 : Record 39);
VAR
Pegging@1001 : Boolean;
Pegging@1001 : Boolean;
BEGIN
Pegging := IsPegging(CurrentPurchLine);
IF Pegging THEN
CurrQuantity := CurrentPurchLine."Quantity (Base)"
ELSE
CurrQuantity := CurrentPurchLine."Outstanding Qty. (Base)";
Pegging := IsPegging(CurrentPurchLine);
IF Pegging THEN
CurrQuantity := CurrentPurchLine."Quantity (Base)"
ELSE
CurrQuantity := CurrentPurchLine."Outstanding Qty. (Base)";
END;
Bad code
@ -34,16 +34,16 @@ Bad code
// In the example below, the function will always return FALSE.
PROCEDURE GetItemsToPlan@22() : Boolean;
BEGIN
SETRANGE("Document Type","Document Type"::Order);
...
FINDSET
SETRANGE("Document Type","Document Type"::Order);
...
FINDSET
END;
Good code
PROCEDURE GetItemsToPlan@22() : Boolean;
BEGIN
SETRANGE("Document Type","Document Type"::Order);
...
EXIT(FINDSET)
SETRANGE("Document Type","Document Type"::Order);
...
EXIT(FINDSET)
END;

View file

@ -12,11 +12,11 @@ Bad code
Good code
Any procedure / trigger that has a maintainability index \>= 20\.
Any procedure / trigger that has a maintainability index >= 20\.
The Maintainability Index is computed as a function:
- Lines Of Code (inverse proportional)
- the Halstead Volume
- Cyclomatic Complexity (inverse proportional).
- Lines Of Code (inverse proportional)
- the Halstead Volume
- Cyclomatic Complexity (inverse proportional).
More info
@ -25,7 +25,7 @@ More info
Bad code
Any procedure / trigger that is \> 100 lines of code
Any procedure / trigger that is > 100 lines of code

View file

@ -4,8 +4,6 @@ weight = 920
+++
The number of parameters passed to a string must match the placeholders.
****
Bad code
CannotDeleteLineErr@1005 : TextConst 'ENU=You cannot delete this line because one or more rating values exists.';
@ -18,7 +16,7 @@ Good code
...
ERROR(CannotDeleteLineErr);
###
Bad code

View file

@ -8,14 +8,14 @@ Bad code
LOCAL PROCEDURE Code@1();
VAR
CAJnlPostBatch@1001 : Codeunit 1103;
CAJnlPostBatch@1001 : Codeunit 1103;
BEGIN
CAJnlPostBatch.Run(CostJnlLine);
CAJnlPostBatch.Run(CostJnlLine);
END;
Good code
LOCAL PROCEDURE Code@1();
BEGIN
CODEUNIT.RUN(CODEUNIT::"CA Jnl.-Post Batch",CostJnlLine);
CODEUNIT.RUN(CODEUNIT::"CA Jnl.-Post Batch",CostJnlLine);
END;

View file

@ -8,18 +8,18 @@ It affects code readability and can lead to wrong assumptions.
Bad code
IF Type <\> Type::FIELD THEN BEGIN
...
ERROR(...);
RecRef.CLOSE;
IF Type <> Type::FIELD THEN BEGIN
...
ERROR(...);
RecRef.CLOSE;
END;
Good code
IF Type <\> Type::FIELD THEN BEGIN
...
RecRef.CLOSE;
ERROR(...);
IF Type <> Type::FIELD THEN BEGIN
...
RecRef.CLOSE;
ERROR(...);
END;

View file

@ -6,33 +6,33 @@ The value assigned to a variable must be used. Else the variable is not necessar
Bad code
PROCEDURE AddEntities@1(FilterStr@1000 : Text\[250\]);
PROCEDURE AddEntities@1(FilterStr@1000 : Text[250]);
VAR
Vendor@1001 : Record 23;
Count@1002 : Integer;
Vendor@1001 : Record 23;
Count@1002 : Integer;
BEGIN
Count := 0;
Vendor.SETFILTER("No.",FilterStr);
IF Vendor.FINDSET THEN
REPEAT
"User ID" := USERID;
"Vendor No." := Vendor."No.";
IF INSERT THEN
Count += 1;
UNTIL Vendor.NEXT = 0;
Count := 0;
Vendor.SETFILTER("No.",FilterStr);
IF Vendor.FINDSET THEN
REPEAT
"User ID" := USERID;
"Vendor No." := Vendor."No.";
IF INSERT THEN
Count += 1;
UNTIL Vendor.NEXT = 0;
END;
Good code
PROCEDURE AddEntities@1(FilterStr@1000 : Text\[250\]);
PROCEDURE AddEntities@1(FilterStr@1000 : Text[250]);
VAR
Vendor@1001 : Record 23;
Vendor@1001 : Record 23;
BEGIN
Vendor.SETFILTER("No.",FilterStr);
IF Vendor.FINDSET THEN
REPEAT
"User ID" := USERID;
"Vendor No." := Vendor."No.";
IF INSERT THEN;
UNTIL Vendor.NEXT = 0;
Vendor.SETFILTER("No.",FilterStr);
IF Vendor.FINDSET THEN
REPEAT
"User ID" := USERID;
"Vendor No." := Vendor."No.";
IF INSERT THEN;
UNTIL Vendor.NEXT = 0;
END;

View file

@ -8,37 +8,37 @@ Unused variables affect readability.
Bad code
PROCEDURE CheckPostingDate@23(CaptionEntryNo@1005 : Text\[50\]);
PROCEDURE CheckPostingDate@23(CaptionEntryNo@1005 : Text[50]);
BEGIN
IF GenJnlCheckLine.DateNotAllowed(PostingDate) THEN
ERROR(DateNotAllowedErr,Caption,EntryNo)
IF PostingDate \> MaxPostingDate THEN
MaxPostingDate := PostingDate;
IF GenJnlCheckLine.DateNotAllowed(PostingDate) THEN
ERROR(DateNotAllowedErr,Caption,EntryNo)
IF PostingDate > MaxPostingDate THEN
MaxPostingDate := PostingDate;
END
Good code
PROCEDURE CheckPostingDate@23();
BEGIN
IF GenJnlCheckLine.DateNotAllowed(PostingDate) THEN
ERROR(DateNotAllowedErr,Caption,EntryNo);
IF PostingDate \> MaxPostingDate THEN
MaxPostingDate := PostingDate;
IF GenJnlCheckLine.DateNotAllowed(PostingDate) THEN
ERROR(DateNotAllowedErr,Caption,EntryNo);
IF PostingDate > MaxPostingDate THEN
MaxPostingDate := PostingDate;
END;
Bad code
PROCEDURE IsReturned@14(EntryNo@1002 : Integer) : Decimal;
VAR
ItemEntry@1000 : Record 32;
Quantity@1003 : Integer;
ItemEntry@1000 : Record 32;
Quantity@1003 : Integer;
BEGIN
EXIT(-OutboundApplied(EntryNo,TRUE) - InboundApplied(EntryNo,TRUE));
EXIT(-OutboundApplied(EntryNo,TRUE) - InboundApplied(EntryNo,TRUE));
END;
Good code
PROCEDURE IsReturned@14(EntryNo@1002 : Integer) : Decimal;
BEGIN
EXIT(-OutboundApplied(EntryNo,TRUE) - InboundApplied(EntryNo,TRUE));
EXIT(-OutboundApplied(EntryNo,TRUE) - InboundApplied(EntryNo,TRUE));
END;

View file

@ -8,52 +8,52 @@ It will throw an error at runtime.
Bad code
FileName@1010 : Text\[250\];
FileName@1010 : Text[250];
...
UploadedFileName@1016 : Text\[1024\];
UploadedFileName@1016 : Text[1024];
...
FileName := UploadedFileName;
Good code
FileName@1010 : Text\[1024\];
FileName@1010 : Text[1024];
...
UploadedFileName@1016 : Text\[1024\];
UploadedFileName@1016 : Text[1024];
...
FileName := UploadedFileName;
Bad code
FileName@1010 : Text\[250\];
FileName@1010 : Text[250];
...
UploadedFileName@1016 : Text\[1024\];
UploadedFileName@1016 : Text[1024];
...
FileName := UploadedFileName;
Good code
FileName@1010 : Text\[250\];
FileName@1010 : Text[250];
...
UploadedFileName@1016 : Text\[1024\];
UploadedFileName@1016 : Text[1024];
...
FileName := COPYSTR(UploadedFileName,1,250); // In case only the first 250 chars are needed. Similar for fields
Bad code
VAR
ExceededNumberTxt@001 : 'ENU=Warning: Exceeded number of unsent documents/requests'
Subject@1002 : Text\[50\];
...
ExceededNumberTxt@001 : 'ENU=Warning: Exceeded number of unsent documents/requests'
Subject@1002 : Text[50];
...
BEGIN
...
Subject := ExceededNumberTxt;
...
Subject := ExceededNumberTxt;
Good code
VAR
ExceededNumberTxt@001 : 'ENU=Warning: Exceeded number of unsent documents/requests'
Subject@1002 : Text\[100\];
...
ExceededNumberTxt@001 : 'ENU=Warning: Exceeded number of unsent documents/requests'
Subject@1002 : Text[100];
...
BEGIN
...
Subject := ExceededNumberTxt';
...
Subject := ExceededNumberTxt';

View file

@ -4,17 +4,18 @@ weight = 1450
+++
Do not use the WITH scope when it has a variable whose name is the same as a local variable. This can lead to wrong code assumptions.
**Given that** "Contract Type" is a field on table ServiceContractHeader, then in the following example there is a parameter name clash with the field name. Which one will be used?
**Given that**
"Contract Type" is a field on table ServiceContractHeader, then in the following example there is a parameter name clash with the field name. Which one will be used?
Bad code
PROCEDURE InsertData@1("Contract Type"@1000 : Option...);
...
BEGIN
...
WITH ServiceContractHeader DO BEGIN
...
DimMgt.InsertServContractDim(...,"Contract Type","Contract No.",0,...);
...
WITH ServiceContractHeader DO BEGIN
...
DimMgt.InsertServContractDim(...,"Contract Type","Contract No.",0,...);
END;
Good code
@ -22,8 +23,8 @@ Good code
PROCEDURE InsertData@1(ContractType@1000 : Option...);
...
BEGIN
...
WITH ServiceContractHeader DO BEGIN
...
DimMgt.InsertServContractDim(...,ContractType,"Contract No.",0,...);
...
WITH ServiceContractHeader DO BEGIN
...
DimMgt.InsertServContractDim(...,ContractType,"Contract No.",0,...);
END;

View file

@ -2,15 +2,16 @@
title = "Using Calcdate"
weight = 1370
+++
CALCDATE should only be used with DateFormula variables. Alternatively the string should be enclosed using the <\> symbols.
CALCDATE should only be used with DateFormula variables. Alternatively the string should be enclosed using the <> symbols.
Bad code
IF ReservEntry."Expected Receipt Date" \>
CALCDATE('-' + FORMAT("Dampener (Time)") + FirstDate)
IF ReservEntry."Expected Receipt Date" >
CALCDATE('-' + FORMAT("Dampener (Time)") + FirstDate)
THEN
Good code
IF ReservEntry."Expected Receipt Date" \>
CALCDATE('<-' + FORMAT("Dampener (Time)") + FirstDate + '\>')
IF ReservEntry."Expected Receipt Date" >
CALCDATE('<-' + FORMAT("Dampener (Time)") + FirstDate + '>')
THEN

View file

@ -11,8 +11,12 @@ Reason:
Bad code
IF NOT CONFIRM(UpdateLocationQst,TRUE,FIELDNAME("Location Code"),...)
```al
IF NOT CONFIRM(UpdateLocationQst,TRUE,FIELDNAME("Location Code"),...)
```
Good code
IF NOT CONFIRM(UpdateLocationQst,TRUE,FIELDCAPTION("Location Code"),...)
```al
IF NOT CONFIRM(UpdateLocationQst,TRUE,FIELDCAPTION("Location Code"),...)
```

View file

@ -6,15 +6,19 @@ Declare Text Constant as global variables.
Bad code
PROCEDURE GetRequirementText@6(...) : Text\[50\];
VAR
```al
PROCEDURE GetRequirementText@6(...) : Text\[50\];
VAR
RequirementOptionsTxt@1002 : TextConst 'ENU=Shipment,Receive,Pick,Put-Away';
BEGIN
BEGIN
```
Good code
VAR
```al
VAR
RequirementOptionsTxt@1002 : TextConst 'ENU=Shipment,Receive,Pick,Put-Away';
...
PROCEDURE GetRequirementText@6(...) : Text\[50\];
BEGIN
...
PROCEDURE GetRequirementText@6(...) : Text\[50\];
BEGIN
```

View file

@ -6,32 +6,40 @@ Pass user messages using Text Constants. It makes translation easy.
Bad code
ImportAttachmentQst@1021 : TextConst 'ENU="Import attachment "';
...
IF CONFIRM(ImportAttachmentQst + Caption +'?',TRUE) THEN BEGIN
```al
ImportAttachmentQst@1021 : TextConst 'ENU="Import attachment "';
...
IF CONFIRM(ImportAttachmentQst + Caption +'?',TRUE) THEN BEGIN
```
Good code
ImportAttachmentQst@1021 : TextConst 'ENU="Import attachment %1?"';
...
IF CONFIRM(STRSUBSTNO(ImportAttachmentQst, Caption),TRUE) THEN BEGIN
```al
ImportAttachmentQst@1021 : TextConst 'ENU="Import attachment %1?"';
...
IF CONFIRM(STRSUBSTNO(ImportAttachmentQst, Caption),TRUE) THEN BEGIN
```
Bad code
...
```al
...
IF NOT
CONFIRM(
STRSUBSTNO(
'Difference on Periodic entries: %1 on %2' +
'Do you want to continue?',Balance,Date),
TRUE)
CONFIRM(
STRSUBSTNO(
'Difference on Periodic entries: %1 on %2' +
'Do you want to continue?',Balance,Date),
TRUE)
THEN
ERROR('Program terminated by the user');
ERROR('Program terminated by the user');
```
Good code
DiffOnPeriodEntiesQst@100 : TextConst 'ENU="Difference on Periodic entries: %1 on %2\\ Do you want to continue?"';
ProgramTerminatedErr@200 : TextConst 'ENU="Program terminated by the user"';
...
```al
DiffOnPeriodEntiesQst@100 : TextConst 'ENU="Difference on Periodic entries: %1 on %2\\ Do you want to continue?"';
ProgramTerminatedErr@200 : TextConst 'ENU="Program terminated by the user"';
...
IF NOT CONFIRM(STRSUBSTNO(DiffOnPeriodEntiesQst,Balance,Date),TRUE) THEN
ERROR(ProgramTerminatedErr);
ERROR(ProgramTerminatedErr);
```

View file

@ -2,15 +2,21 @@
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
When BEGIN follows THEN, ELSE, DO, it should be on the same line, preceded by one space character.
IF ICPartnerRefType = ICPartnerRefType::"Common Item No." THEN
Bad code
```al
IF ICPartnerRefType = ICPartnerRefType::"Common Item No." THEN
BEGIN
...
END;
END;
```
Good code
IF ICPartnerRefType = ICPartnerRefType::"Common Item No." THEN BEGIN
```
IF ICPartnerRefType = ICPartnerRefType::"Common Item No." THEN BEGIN
...
END;
END;
```

View file

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

View file

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

View file

@ -2,30 +2,43 @@
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
PROCEDURE MATRIX\_OnDrillDown@1133(MATRIX\_ColumnOrdinal : Integer);
BEGIN
SetupDrillDownCol(MATRIX\_ColumnOrdinal);
DrillDown(FALSE,ValueType);
END;
Good code
PROCEDURE MATRIX\_OnDrillDown@1133(MATRIX\_ColumnOrdinal : Integer);
BEGIN
SetupDrillDownCol(MATRIX\_ColumnOrdinal);
DrillDown(FALSE,ValueType);
END;
Do not use blank lines at the beginning or end of any functions, after BEGIN, before END, or inside multiline expressions.
Bad code
IF NameIsValid AND
Name2IsValid
THEN
```al
PROCEDURE MATRIX_OnDrillDown@1133(MATRIX_ColumnOrdinal : Integer);
BEGIN
SetupDrillDownCol(MATRIX_ColumnOrdinal);
DrillDown(FALSE,ValueType);
END;
```
Good code
IF NameIsValid AND
```al
PROCEDURE MATRIX_OnDrillDown@1133(MATRIX_ColumnOrdinal : Integer);
BEGIN
SetupDrillDownCol(MATRIX_ColumnOrdinal);
DrillDown(FALSE,ValueType);
END;
```
Bad code
```al
IF NameIsValid AND
Name2IsValid
THEN
THEN
```
Good code
```al
IF NameIsValid AND
Name2IsValid
THEN
```

View file

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

View file

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

View file

@ -2,38 +2,45 @@
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
Never use curly bracket comments. During development, the "Block comment" functionality can be used instead. However, in production code, block comments are not recommended.
PeriodTxt: {Period}
Bad code
```al
PeriodTxt: {Period}
```
Good code
PeriodTxt: // Period
```al
PeriodTxt: // Period
```
Bad code
PROCEDURE MATRIX\_OnAfterGetRecord@10(MATRIX\_ColumnOrdinal : Integer);
BEGIN
```al
PROCEDURE MATRIX_OnAfterGetRecord@10(MATRIX_ColumnOrdinal : Integer);
BEGIN
{
IF ShowColumnName THEN
MatrixHeader := MatrixRecords\[MATRIX\_ColumnOrdinal\].Name
MatrixHeader := MatrixRecords[MATRIX_ColumnOrdinal].Name
ELSE
MatrixHeader := MatrixRecords\[MATRIX\_ColumnOrdinal\].Code;
MatrixHeader := MatrixRecords[MATRIX_ColumnOrdinal].Code;
}
MatrixRecord := MatrixRecords\[MATRIX\_ColumnOrdinal\];
MatrixRecord := MatrixRecords[MATRIX_ColumnOrdinal];
AnalysisValue := CalcAmt(ValueType,TRUE);
MATRIX\_CellData\[MATRIX\_ColumnOrdinal\] := AnalysisValue;
END;
MATRIX_CellData[MATRIX_ColumnOrdinal] := AnalysisValue;
END;
```
Good code
PROCEDURE MATRIX\_OnAfterGetRecord@10(MATRIX\_ColumnOrdinal : Integer);
BEGIN
MatrixRecord := MatrixRecords\[MATRIX\_ColumnOrdinal\];
```al
PROCEDURE MATRIX_OnAfterGetRecord@10(MATRIX_ColumnOrdinal : Integer);
BEGIN
MatrixRecord := MatrixRecords[MATRIX_ColumnOrdinal];
AnalysisValue := CalcAmt(ValueType,TRUE);
MATRIX\_CellData\[MATRIX\_ColumnOrdinal\] := AnalysisValue;
END;
MATRIX_CellData[MATRIX_ColumnOrdinal] := AnalysisValue;
END;
```

View file

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

View file

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

View file

@ -3,82 +3,110 @@ 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
IF GLSetup."Unrealized VAT" OR
(GLSetup."Prepayment Unrealized VAT" AND NewCVLedgEntryBuf.Prepayment)
Good code
IF GLSetup."Unrealized VAT" OR
```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
IF GenJnlLine."Account No." <\> ICPartner.Code THEN
ICPartner.GET("Account No.");
IF GenJnlLine.Amount \> 0 THEN BEGIN
```al
IF GenJnlLine."Account No." <> ICPartner.Code THEN
ICPartner.GET("Account No.");
IF GenJnlLine.Amount \> 0 THEN BEGIN
...
```
Good code
IF GenJnlLine."Account No." <\> ICPartner.Code THEN
ICPartner.GET("Account No.");
IF GenJnlLine.Amount \> 0 THEN BEGIN
...
```al
IF GenJnlLine."Account No." <> ICPartner.Code THEN
ICPartner.GET("Account No.");
IF GenJnlLine.Amount > 0 THEN BEGIN
...
```
Bad code
Dialog.OPEN(WindowTxt +
'@1@@@@@@@@@@@@@@@@@@@@@@@');
```al
Dialog.OPEN(WindowTxt +
'@1@@@@@@@@@@@@@@@@@@@@@@@');
```
Good code
Dialog.OPEN(
```al
Dialog.OPEN(
WindowTxt +
'@1@@@@@@@@@@@@@@@@@@@@@@@');
```
Bad code
TempOldCustLedgEntry.DELETE;
// Find the next old entry for application of the new entry
```al
TempOldCustLedgEntry.DELETE;
// Find the next old entry for application of the new entry
```
Good code
TempOldCustLedgEntry.DELETE;
// Find the next old entry for application of the new entry
```al
TempOldCustLedgEntry.DELETE;
// Find the next old entry for application of the new entry
```
Bad code
IF NOT ("Applies-to Doc. Type" IN
\["Applies-to Doc. Type"::Receipt,
"Applies-to Doc. Type"::"Return Shipment"\])
```al
IF NOT ("Applies-to Doc. Type" IN
["Applies-to Doc. Type"::Receipt,
"Applies-to Doc. Type"::"Return Shipment"])
```
Good code
IF NOT ("Applies-to Doc. Type" IN
\["Applies-to Doc. Type"::Receipt,
"Applies-to Doc. Type"::"Return Shipment"\])
```al
IF NOT ("Applies-to Doc. Type" IN
["Applies-to Doc. Type"::Receipt,
"Applies-to Doc. Type"::"Return Shipment"])
```
Bad code
WHILE (RemAmt \> 0) OR
(RemAmtLCY \> 0)
DO
```al
WHILE (RemAmt > 0) OR
(RemAmtLCY > 0)
DO
```
Good code
WHILE (RemAmt \> 0) OR
(RemAmtLCY \> 0)
DO
```al
WHILE (RemAmt > 0) OR
(RemAmtLCY > 0)
DO
```
Bad code
UNTIL (RemAmt \> 0) AND
(RemAmtLCY \> 0);
```al
UNTIL (RemAmt > 0) AND
(RemAmtLCY > 0);
```
Good code
UNTIL (RemAmt \> 0) AND
(RemAmtLCY \> 0)
```al
UNTIL (RemAmt > 0) AND
(RemAmtLCY > 0)
```

View file

@ -2,13 +2,19 @@
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
The IF..THEN pair, WHILE..DO pair, and FOR..DO pair must appear on the same line or the same level of indentation.
IF (x = y) AND
(a = b) THEN
Bad code
```al
IF (x = y) AND
(a = b) THEN
```
Good code
IF (x = y) AND
(a = b)
THEN
```al
IF (x = y) AND
(a = b)
THEN
```

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -3,36 +3,44 @@ 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
"Line Discount %" := "Line Discount Amount"/"Line Value"\*100
```al
"Line Discount %" := "Line Discount Amount"/"Line Value"*100
```
Good code
"Line Discount %" := "Line Discount Amount" / "Line Value" \* 100;
```al
"Line Discount %" := "Line Discount Amount" / "Line Value" * 100;
```
Bad code
StartDate := CALCDATE('<+'+FORMAT(Days + i)+'D\>', StartDate);
```al
StartDate := CALCDATE('<+'+FORMAT(Days + i)+'D>', StartDate);
```
Good code
StartDate := CALCDATE('<+' + FORMAT(Days + i) + 'D\>',StartDate);
```al
StartDate := CALCDATE('<+' + FORMAT(Days + i) + 'D>',StartDate);
```
Bad code
StartDate := 0D; // Initialize
```al
StartDate := 0D; // Initialize
```
Good code
StartDate := 0D; // Initialize
```al
StartDate := 0D; // Initialize
```

View file

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

View file

@ -3,24 +3,30 @@ 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
IF NOT(Type = Type::Item) THEN
```al
IF NOT(Type = Type::Item) THEN
```
Good code
IF NOT (Type = Type::Item) THEN
```al
IF NOT (Type = Type::Item) THEN
```
Bad code
DiscAmt := - "Discount Amount";
```al
DiscAmt := - "Discount Amount";
```
Good code
DiscAmt := -"Discount Amount";
```al
DiscAmt := -"Discount Amount";
```

View file

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

View file

@ -3,88 +3,113 @@ 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
CannotDeleteLine@1005 : TextConst 'ENU=You cannot delete this line because one or more rating values exists.';
...
ERROR(CannotDeleteLine,TABLECAPTION);
```al
CannotDeleteLine@1005 : TextConst 'ENU=You cannot delete this line because one or more rating values exists.';
...
ERROR(CannotDeleteLine,TABLECAPTION);
```
Good code
CannotDeleteLineErr@1005 : TextConst 'ENU=You cannot delete this line because one or more rating values exists.';
...
ERROR(CannotDeleteLineErr,TABLECAPTION);
```al
CannotDeleteLineErr@1005 : TextConst 'ENU=You cannot delete this line because one or more rating values exists.';
...
ERROR(CannotDeleteLineErr,TABLECAPTION);
```
Bad code
Text000@1011 : TextConst 'ENU="has been changed (initial a %1: %2= %3, %4= %5)"';
...
SalesLine.FIELDERROR(Type,STRSUBSTNO(Text000,...);
...
```al
Text000@1011 : TextConst 'ENU="has been changed (initial a %1: %2= %3, %4= %5)"';
...
SalesLine.FIELDERROR(Type,STRSUBSTNO(Text000,...);
...
```
Good code
TypeHasBeenChangedErr@1011 : TextConst 'ENU="has been changed (initial a %1: %2= %3, %4= %5)"';
...
SalesLine.FIELDERROR(Type,STRSUBSTNO(TypeHasBeenChangedErr,...);
...
```al
TypeHasBeenChangedErr@1011 : TextConst 'ENU="has been changed (initial a %1: %2= %3, %4= %5)"';
...
SalesLine.FIELDERROR(Type,STRSUBSTNO(TypeHasBeenChangedErr,...);
...
```
Bad code
Text004@1004 : TextConst 'ENU=Indenting the Job Tasks \#1\#\#\#\#\#\#\#\#\#\#.';
...
Window@1007 : Dialog;
...
```al
Text004@1004 : TextConst 'ENU=Indenting the Job Tasks \#1\#\#\#\#\#\#\#\#\#\#.';
...
Window@1007 : Dialog;
...
Window.OPEN(Text004);
```
Good code
IndentingMsg@1004 : TextConst 'ENU=Indenting the Job Tasks \#1\#\#\#\#\#\#\#\#\#\#.';
...
Window@1007 : Dialog;
...
```al
IndentingMsg@1004 : TextConst 'ENU=Indenting the Job Tasks \#1\#\#\#\#\#\#\#\#\#\#.';
...
Window@1007 : Dialog;
...
Window.OPEN(IndentingMsg);
```
Bad code
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
```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
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
```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
Selection := STRMENU(Text003,2);
...
Text003@1002 : TextConst 'ENU=&Copy dimensions from BOM,&Retrieve dimensions from components';
```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
DATASET
{
...
{ 1 ;1 ;Column ;Chart\_of\_AccountsCaption;
SourceExpr=Chart\_of\_AccountsCaption }
...
Chart\_of\_AccountsCaption@9647 : TextConst 'ENU=Chart of Accounts';
```al
DATASET
{
...
{ 1 ;1 ;Column ;Chart_of_AccountsCaption;
SourceExpr=Chart_of_AccountsCaption }
...
Chart_of_AccountsCaption@9647 : TextConst 'ENU=Chart of Accounts';
```
Good code
DATASET
{
...
{ 1 ;1 ;Column ;Chart\_of\_AccountsCaption;
SourceExpr=ChartOfAccountsLbl }
...
ChartOfAccountsLbl@9647 : TextConst 'ENU=Chart of Accounts';
```al
DATASET
{
...
{ 1 ;1 ;Column ;Chart_of_AccountsCaption;
SourceExpr=ChartOfAccountsLbl }
...
ChartOfAccountsLbl@9647 : TextConst 'ENU=Chart of Accounts';
```

View file

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

View file

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

View file

@ -2,15 +2,21 @@
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
ELSE should not be used when the last action in the THEN part is an EXIT, BREAK, SKIP, QUIT, ERROR.
IF IsAdjmtBinCodeChanged THEN
Bad code
```al
IF IsAdjmtBinCodeChanged THEN
ERROR(AdjmtBinCodeChangeNotAllowedErr,...)
ELSE
ELSE
ERROR(BinCodeChangeNotAllowedErr,...);
```
Good code
IF IsAdjmtBinCodeChanged THEN
```al
IF IsAdjmtBinCodeChanged THEN
ERROR(AdjmtBinCodeChangeNotAllowedErr,...)
ERROR(BinCodeChangeNotAllowedErr,...);
ERROR(BinCodeChangeNotAllowedErr,...);
```

View file

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

View file

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

View file

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

View file

@ -3,30 +3,37 @@ 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
ReturnRcptHeader.SETRANGE(ReturnRcptHeader."Return Order No.","Document No.");
```al
ReturnRcptHeader.SETRANGE(ReturnRcptHeader."Return Order No.","Document No.");
```
Good code
ReturnRcptHeader.SETRANGE("Return Order No.","Document No.");
```al
ReturnRcptHeader.SETRANGE("Return Order No.","Document No.");
```
Bad code
WITH ChangeLogSetupTable DO BEGIN
```al
WITH ChangeLogSetupTable DO BEGIN
...
IF ChangeLogSetupTable.DELETE THEN
...
END;
...
END;
```
Good code
WITH ChangeLogSetupTable DO BEGIN
```al
WITH ChangeLogSetupTable DO BEGIN
...
IF DELETE THEN
...
END;
...
END;
```

View file

@ -9,48 +9,61 @@ 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
...
OBJECT Table Job WIP Buffer
```
Good code
...
```al
...
JobWIPBuffer@1002 : Record 1018
...
OBJECT Table Job WIP Buffer
...
OBJECT Table Job WIP Buffer
```
Bad code
...
```al
...
Postline@1004 : Codeunit 12;
...
OBJECT Codeunit Gen. Jnl.-Post Line
...
OBJECT Codeunit Gen. Jnl.-Post Line
```
Good code
...
```al
...
GenJnlPostLine@1004 : Codeunit 12;
...
OBJECT Codeunit Gen. Jnl.-Post Line
...
OBJECT Codeunit Gen. Jnl.-Post Line
```
Bad code
LOCAL PROCEDURE HandleCustDebitCredit@17(...;"Amount (LCY)"@1001 : Decimal;...);
BEGIN
```al
LOCAL PROCEDURE HandleCustDebitCredit@17(...;"Amount (LCY)"@1001 : Decimal;...);
BEGIN
IF ((... ("Amount (LCY)" \> 0)) ...) OR
((... ("Amount (LCY)" < 0)) ...)
((... ("Amount (LCY)" < 0)) ...)
THEN BEGIN
...
```
Good code
LOCAL PROCEDURE HandleCustDebitCredit@17(...;AmountLCY@1001 : Decimal;...);
BEGIN
```al
LOCAL PROCEDURE HandleCustDebitCredit@17(...;AmountLCY@1001 : Decimal;...);
BEGIN
IF ((... (AmountLCY \> 0)) ...) OR
((... (AmountLCY < 0)) ...)
((... (AmountLCY < 0)) ...)
THEN BEGIN
...
```

View file

@ -2,12 +2,18 @@
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
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.
StartingDateFilter@1002 : Text\[30\];
Vend@1003 : Record 23;
Bad code
```al
StartingDateFilter@1002 : Text[30];
Vend@1003 : Record 23;
```
Good code
Vend@1003 : Record 23;
StartingDateFilter@1002 : Text\[30\];
```al
Vend@1003 : Record 23;
StartingDateFilter@1002 : Text[30];
```

View file

@ -3,15 +3,20 @@ title = "Actions - Images"
weight = 200
+++
All actions must have an image assigned to them.
Bad code
{ 7 ;1 ;Action ;
CaptionML=ENU=Customer - &Balance;
RunObject=Report 121 }
```al
{ 7 ;1 ;Action ;
CaptionML=ENU=Customer - &Balance;
RunObject=Report 121 }
```
Good code
{ 7 ;1 ;Action ;
CaptionML=ENU=Customer - &Balance;
RunObject=Report 121 }
Image=Report }
```al
{ 7 ;1 ;Action ;
CaptionML=ENU=Customer - &Balance;
RunObject=Report 121 }
Image=Report }
```

View file

@ -3,14 +3,19 @@ title = "CONFIRM"
weight = 380
+++
Always end CONFIRM with a question mark.
Bad code
ChangeAllOpenedEntriesQst@1000 : TextConst 'ENU=Do you want to change all open entries for every customer and vendor that are not blocked';
...
IF CONFIRM(ChangeAllOpenedEntriesQst,TRUE) THEN
```al
ChangeAllOpenedEntriesQst@1000 : TextConst 'ENU=Do you want to change all open entries for every customer and vendor that are not blocked';
...
IF CONFIRM(ChangeAllOpenedEntriesQst,TRUE) THEN
```
Good code
ChangeAllOpenedEntriesQst@1000 : TextConst 'ENU=Do you want to change all open entries for every customer and vendor that are not blocked?';
...
IF CONFIRM(ChangeAllOpenedEntriesQst,TRUE) THEN
```al
ChangeAllOpenedEntriesQst@1000 : TextConst 'ENU=Do you want to change all open entries for every customer and vendor that are not blocked?';
...
IF CONFIRM(ChangeAllOpenedEntriesQst,TRUE) THEN
```

View file

@ -3,14 +3,19 @@ title = "FIELDERROR"
weight = 590
+++
Never use FIELDERROR with a period as it is automatically inserted.
Bad code
InvalidValue@1025 : TextConst 'ENU=is invalid.';
...
Cust.FIELDERROR("No.",InvalidValue);
```al
InvalidValue@1025 : TextConst 'ENU=is invalid.';
...
Cust.FIELDERROR("No.",InvalidValue);
```
Good code
InvalidValue@1025 : TextConst 'ENU=is invalid';
...
Cust.FIELDERROR("No.",InvalidValue);
```al
InvalidValue@1025 : TextConst 'ENU=is invalid';
...
Cust.FIELDERROR("No.",InvalidValue);
```

View file

@ -3,14 +3,19 @@ title = "MESSAGE and ERROR"
weight = 790
+++
Always end MESSAGE or ERROR with a period.
Bad code
CustIsBlockedErr@1025 : TextConst 'ENU=You cannot %1 this type of document when Customer %2 is blocked with type %3';
...
ERROR(CustIsBlockedErr,...);
```al
CustIsBlockedErr@1025 : TextConst 'ENU=You cannot %1 this type of document when Customer %2 is blocked with type %3';
...
ERROR(CustIsBlockedErr,...);
```
Good code
CustIsBlockedErr@1025 : TextConst 'ENU=You cannot %1 this type of document when Customer %2 is blocked with type %3.';
...
ERROR(CustIsBlockedErr,...);
```al
CustIsBlockedErr@1025 : TextConst 'ENU=You cannot %1 this type of document when Customer %2 is blocked with type %3.';
...
ERROR(CustIsBlockedErr,...);
```

View file

@ -29,14 +29,14 @@ We are working on creating a set of rules, which would help keeping the content
[anchor0]: /nav/w/designpatterns/74.no-series.aspx "No. Series"
[anchor1]: /nav/w/designpatterns/76.single-record-setup-table.aspx "Setup Table"
[anchor2]: /nav/w/designpatterns/117.hooks-pattern.aspx "Hooks"
[anchor3]: /nav/w/designpatterns/122.implementation-of-surrogate-keys-using-autoincrement-pattern.aspx
[anchor4]: /nav/w/designpatterns/104.easy-update-of-setup-or-supplementary-information.aspx
[anchor5]: /nav/w/designpatterns/155.totals-and-discounts-on-subpages-sales-and-purchases.aspx
[anchor6]: /nav/w/designpatterns/123.using-cal-query-objects-instead-of-nested-loops.aspx
[anchor0]: /navpatterns/1-patterns/no-series/ "No. Series"
[anchor1]: /navpatterns/1-patterns/singleton/singleton-table/setup-table/ "Setup Table"
[anchor2]: /navpatterns/1-patterns/hooks/ "Hooks"
[anchor3]: /navpatterns/1-patterns/implementation-of-surrogate-keys-using-autoincrement-pattern/
[anchor4]: /navpatterns/1-patterns/easy-update-of-setup-or-supplementary-information/
[anchor5]: /navpatterns/1-patterns/totals-and-discounts-on-subpages-sales-and-purchases/
[anchor6]: /navpatterns/1-patterns/queries/use-queries-to-replace-nested-loops/
[anchor7]: /members/bogdana-botez/default.aspx
[anchor8]: /nav/w/designpatterns/107.template-for-writing-nav-design-patterns.aspx
[anchor8]: /navpatterns/4-get-involved/template-for-writing-nav-design-patterns/
[anchor9]: /members/bogdana-botez/default.aspx "Bogdana Botez"
[anchor10]: /nav/w/designpatterns/239.rules-of-conduct.aspx "Find the rules here"
[anchor10]: /navpatterns/4-get-involved/code-of-conduct/ "Find the rules here"

View file

@ -163,5 +163,5 @@ And last but not least, we have collaborated with Plataan who hired Eric Wauters
[anchor0]: /nav/w/designpatterns/106.be-a-nav-pattern-author.aspx
[anchor0]: /navpatterns/4-get-involved/
[anchor1]: /members/bogdana-botez/default.aspx "NAV Design Patterns project administrator"