In this blogpost I continue my series of design patterns for AL.
This time I write about a simple pattern which could make the readability of your code much better. I’m talking about the “Template method pattern”. The pattern defines the skeleton of a process without implenting it. The real implemenation is handelt in another codeunit.
The big advantage of this pattern is that it helps us to solve similar problems with a similar solution
In AL you need at least 3 objects to implement the pattern:
- A template codeunit
- An Interface which provides the needed procedures
- And an implementation for the Template
The template codeunit
The template codeunit defines the skeleton of a solution without implementation. In the following example I’m implementing a data export
codeunit 50000 ExportTemplate
{
procedure ExportData(export: Interface IDataExport)
begin
if not export.CheckData() then
exit;
if export.GetLinesToExport() then begin
repeat
export.ExportLine();
until not export.NextLine();
end;
export.finish();
end;
}
The interface
Now that we have the skeleton we need the interface which is used in the codeunit above
interface IDataExport
{
procedure CheckData(): Boolean;
procedure GetLinesToExport(): Boolean;
procedure ExportLine();
procedure NextLine(): Boolean;
procedure Finish();
}
That’s the whole and simple pattern, just to have a complet sample I add one implentation for the pattern
Implementation Example
Here is the implementation of the interface
codeunit 50001 SalesHeaderExport implements IDataExport
{
procedure SetSalesHeader(DocType: Enum "Sales Document Type"; No: Code[10])
begin
SalesHeader.Get(DocType, No);
end;
procedure CheckData(): Boolean
begin
SalesHeader.TestField(Status, Enum::"Sales Document Status"::Released);
end;
procedure GetLinesToExport(): Boolean
begin
SalesLines.SetRange("Document Type", SalesHeader."Document Type");
SalesLines.SetRange("Document No.", SalesHeader."No.");
exit(SalesLines.FindSet());
end;
procedure ExportLine()
begin
//Generate Exportdata here
end;
procedure NextLine(): Boolean
begin
exit(SalesLines.Next() > 0);
end;
procedure Finish()
begin
// Send or Save data here
end;
var
SalesHeader: Record "Sales Header";
SalesLines: Record "Sales Line";
}
And here is the usage
codeunit 50002 ExportOrders
{
procedure ExportOrder(DocType: Enum "Sales Document Type"; No: Code[10])
var
export: Codeunit ExportTemplate;
exportImpl: Codeunit SalesHeaderExport;
exportInt: Interface IDataExport;
begin
exportImpl.SetSalesHeader(DocType, No);
exportInt := exportImpl;
export.ExportData(exportInt);
end;
}