BC AL Journey #12

We have gone a long way on our BC AL Journey, and we have looked at a lot of different technologies. For this step we are going to step back and do a deeper dive into procedures. This step won’t be advancing our existing project, but more of a how/why for decisions we will be making in the future, specifically around the concept of Scope. I prefer everything to be hands on, but I don’t want the details of the “why” to be lost in the “how” of application.

Procedures contain code that can be executed from other procedures. We can have a trigger call a procedure; we can have procedures call procedures; we can have Events call procedures. Procedures can exist in nearly any Business Central object, tables, pages, reports, and so on. Procedures even have an object that is designed to contain just procedures, the Code Unit.

When creating a procedure, it is important to consider the purpose of that procedure. A good practice is for tables and pages to have small procedure that act on a single record at a time. If a procedure acts on several records, is used by more than one object, or is large and complex it should live in a Code Unit.

A critical consideration is the Scope of a procedure. A procedure can be Local, Internal, or Global. These scopes define what can use the procedure, where it can be loaded from, and impact your ability update and maintain your code.

Local scope is the most limited where the procedure can only be accessed inside the object that it is created in. If you create a code unit with a local procedure, nothing outside that code unit file will have visibility to that procedure. This is good when the procedure is part of a larger process, such as a procedure supporting another procedure. There is no reason for anyone to use this procedure outside the code unit.

Internal scope is broader, the procedure can only be accessed in the solution it is a part of. This is valuable when you have processes you want to run, but don’t want them available to other people extending your extension.

Global is the most accessible and can be used by anything inside the solution, as well as any other solution that references its containing solution. This is useful if these are tools and processes that you want to make available to someone extending your extension or want it available in other extensions you are creating.

There is a risk to Global procedures; If you publish a solution with a global scoped procedure and you later decide that you don’t need it anymore and want to delete it, it will be considered a breaking change to the solution.

Why would deleting my procedure be a breaking change? Business Central is based on the concept of Extensions extending Extensions. It is assumed that if you have made a procedure Global, some extension is going to utilize that procedure and taking it away would break that extension.

Working with AL methods – Business Central | Microsoft Learn

A common development pattern is that Code Units have very small Internal or Global scoped procedures that utilize many Local scoped procedures. This allows you to redesign the inside of a code unit, while maintaining compatibility through limited global scope procedures.

How about an example. This is a very simple globally scoped procedure that takes a customer record as a parameter and returns back a Text[50] called ReturnValue which is populated with the customer’s name.

procedure MyMethod(CustomerRec: Record Customer) ReturnValue: Text[50]
var 
    NameValue: Text[50];
begin
    NameValue:= CustomerRec.Name;
    //Do something important here with the name
    ReturnValue := NameValue;
end;

Here is another way to do the same thing, in this case we use the exit method to exit the procedure and return the value.

procedure MyMethod(CustomerRec: Record Customer): Text[50]
var 
    NameValue: Text[50];
begin
    NameValue:= CustomerRec.Name;
    //Do something important here with the name
    exit(NameValue);
end;

A more complex code unit might look like this.

namespace AardvarkLabs;
using Microsoft.Sales.Customer;

codeunit 50001 ARDValidateCustomer
{
    procedure ValidateCustomer(CustomerRec: Record Customer): Boolean
    begin
        exit(ValidateCustomerDetails(CustomerRec));
    end;

    local procedure ValidateCustomerDetails(CustomerRec: Record Customer): Boolean
    var
        CustomerValid: Boolean;
        CustomerHasName: Boolean;
        CustomerHasEmail: Boolean;
    begin
        CustomerHasName := StrLen(CustomerRec.Name) > 0;
        CustomerHasEmail := ValidateEmail(CustomerRec."E-Mail");

        CustomerValid := CustomerHasName and CustomerHasEmail;
        exit(CustomerValid);
    end;

    local procedure ValidateEmail(EmailAddress: Text[80]): Boolean
    var
        EmailValid: Boolean;
    begin
        EmailValid := StrPos(EmailAddress, '@') > 1;
        exit(EmailValid);
    end;
}
    

We have a Global procedure called ValidateCustomer that takes in a Customer Record and returns a Boolean value. That Global procedure calls a Local procedure to validate the details, which in turn calls another Local procedure. Once I publish this, I can’t remove the ValidateCustomer procedure, as it is global, but I can change and remove the two local procedures. If I didn’t want anyone outside the extension to be able to use the ValidateCustomer procedure, I could have scoped it Internal.

We will be working with procedure a lot as we move forward into more advanced data handling. It will be important that we are aware of our procedure scope and how it impacts the availability of the procedures we create and the maintenance of those procedures.

This lesson is a bit more abstract, and it will be much clearer as we apply the concepts. As we plan our solutions, where code is written, and the scope of those procedures is important.

One response to “Understanding Business Central AL Procedures: Scope Best Practices”

  1. […] This will prevent anyone from using it to gain access to the isolated storage. Back in BC AL Journey #12 we discussed Scope and how it can restrict access to objects in Business Central AL. In this case, […]

    Like

Leave a comment

Trending