Namespaces in AL

Microsoft Learn: Namespaces in AL

The purpose of this article is to show you how Namespaces can help you organize your code and make it more readable and more maintainable.

Naming Namespaces and Nested Namespaces

Syntax

Put the following line as the first line in all your AL files in your project.

namespace MyNamespace.MyNestedNamespace;

I use my company name FinnPedersenFrance as the Namespace.

Deciding on which Nested Namespaces you need is a bit more complicated. It really depends on your specific situation.

First of all, it is not mandatory to have a Nested Namespace, but I think most cases call for one or two levels. Erik Hougaard suggests having a group level at first: Like Apps or Tools, which is also what I have done in the following examples.

Without the group level

namespace FinnPedersenFrance.BasicSubscriptionManagement;
using FinnPedersenFrance.Library;

With the group level App and Tools nested Namespaces.

namespace FinnPedersenFrance.App.BasicSubscriptionManagement;
using FinnPedersenFrance.Tools.Library;

I can also recommend to watch this video on YouTube Finally we got namespaces in AL by Erik Hougaard. Erik also gives his advice on how to name the Namespace and NestedNamespaces.

Code Readability

To illustrate this, I will use a small app for selling subscriptions in Business Central. The app is an extension to Items and Blanket Sales Order.

Notice how the using directive tells the developer where we are in the standard application.

namespace FinnPedersenFrance.App.BasicSubscriptionManagement;
using Microsoft.Inventory.Item;

tableextension 50140 "Subscription Item" extends Item
namespace FinnPedersenFrance.App.BasicSubscriptionManagement;
using Microsoft.Inventory.Item;
using Microsoft.Sales.Document;
using FinnPedersenFrance.Tools.Library;

codeunit 50144 "Test Subscription App"

The fully qualified name

When should you use the using directive and when should you use the fully qualified name?

In the Codeunit "Subscription Management" below, I declare using Microsoft.Sales.Document and using Microsoft.Inventory.Item, but I choose to fully qualify the variable Codeunit System.Automation."Approvals Mgmt.";. Why? Because the ApprovalsMgmt variable is only used locally in the MakeOrderYN function. Where the theme of the Codeunit is Sales Document and the Inventory Item. I hope it makes sense.

You basically don’t need to know in the top of the Codeunit that I am calling a function from the System.Automation once.

namespace FinnPedersenFrance.App.BasicSubscriptionManagement;

using Microsoft.Sales.Document;
using Microsoft.Inventory.Item;

codeunit 50140 "Subscription Management"

    procedure MakeOrderYN(SalesHeader: Record "Sales Header")
    var
        ApprovalsMgmt: Codeunit System.Automation."Approvals Mgmt.";
    begin
        if ApprovalsMgmt.PrePostApprovalCheckSales(SalesHeader) then
            Codeunit.Run(Codeunit::"Blnkt Sales Ord. to Ord. (Y/N)", SalesHeader);
    end;

In the above code, the following variable declaration uses the fully qualified name Codeunit System.Automation."Approvals Mgmt.".

    var
        ApprovalsMgmt: Codeunit System.Automation."Approvals Mgmt.";

Where the Record "Sales Header" is not fully qualified, because we have already declared using the Microsoft.Sales.Document namespace which includes the Record definition.

procedure MakeOrderYN(SalesHeader: Record "Sales Header")

You have to find the right balance and your guide is the readability of the code. Does it make the code easier to read? I think the above example illustrates this quite well.

In this example, you could question if the .App is needed in the Namespace declaration, but it depends on the context.

How does Microsoft use Namespaces?

I started by saying that Namespaces is to make the code more readable. So let us take a look at how Microsoft is using Namespaces.

Below is the first lines of Table 18 Customer.

I have two observations to this.

  • First of all, it is not really more readable because Microsoft declares the using directive everywhere. This is the easy way of implementing Namespaces. No thinking needed.
  • Second. However, Microsoft has made an effort in choosing good names for the Namespaces and Nested Namespaces and we can use this as a source of inspiration.

First level

  • Microsoft
  • System

It is a bit confusing. Why not just one? Microsoft

How will you choose where to look for a utility?

using Microsoft.Utilities;
using System.Utilities;

I recommend using the first level to name the owner of the code.

Second level

The second level is typically split into application areas or tools.

Application Area or Product

  • Bank
  • Finance
  • Sales

Tools

  • Foundation
  • Utilities

or none

  • using System;

Not having a second level here, seems inconsistent. What function would qualify for being at a top level?

Third and Fourth level

The third level is an area and the fourth level is a feature. You could discuss whether a fourth level is needed, but maybe the size of the feature justifies the need for the extra level.

using Microsoft.Finance.Currency;
using Microsoft.Finance.Dimension;
using Microsoft.Finance.GeneralLedger.Journal;
using Microsoft.Finance.GeneralLedger.Setup;

Table 18 Customer

As it looked in version 23.

I recommend that you avoid having such a long using declaration. Find the right balance. Consider what is the theme of your object and then use fully qualified variable declarations where it makes sense.

namespace Microsoft.Sales.Customer;

using Microsoft.Bank.BankAccount;
using Microsoft.Bank.DirectDebit;
using Microsoft.CRM.BusinessRelation;
using Microsoft.CRM.Campaign;
using Microsoft.CRM.Contact;
using Microsoft.CRM.Outlook;
using Microsoft.CRM.Setup;
using Microsoft.CRM.Team;
using Microsoft.EServices.OnlineMap;
using Microsoft.Finance.Currency;
using Microsoft.Finance.Dimension;
using Microsoft.Finance.GeneralLedger.Journal;
using Microsoft.Finance.GeneralLedger.Setup;
using Microsoft.Finance.ReceivablesPayables;
using Microsoft.Finance.SalesTax;
using Microsoft.Finance.VAT.Registration;
using Microsoft.Finance.VAT.Setup;
using Microsoft.Foundation.Address;
using Microsoft.Foundation.Calendar;
using Microsoft.Foundation.Comment;
using Microsoft.Foundation.Enums;
using Microsoft.Foundation.NoSeries;
using Microsoft.Foundation.PaymentTerms;
using Microsoft.Foundation.Period;
using Microsoft.Foundation.Reporting;
using Microsoft.Foundation.Shipping;
using Microsoft.Integration.Dataverse;
using Microsoft.Integration.Graph;
using Microsoft.Intercompany.Partner;
using Microsoft.Inventory.Intrastat;
using Microsoft.Inventory.Item.Catalog;
using Microsoft.Inventory.Location;
using Microsoft.Inventory.Tracking;
using Microsoft.Pricing.Calculation;
using Microsoft.Pricing.PriceList;
using Microsoft.Pricing.Source;
using Microsoft.Projects.Project.Job;
using Microsoft.Purchases.Vendor;
using Microsoft.Sales.Archive;
using Microsoft.Sales.Document;
using Microsoft.Sales.FinanceCharge;
using Microsoft.Sales.History;
using Microsoft.Sales.Pricing;
using Microsoft.Sales.Receivables;
using Microsoft.Sales.Reminder;
using Microsoft.Sales.Setup;
using Microsoft.Service.Contract;
using Microsoft.Service.Document;
using Microsoft.Service.Item;
using Microsoft.Service.Ledger;
using Microsoft.Service.Setup;
using Microsoft.Utilities;
using System;
using System.Automation;
using System.Email;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Security.User;
using System.Utilities;

table 18 Customer

Clean AL Code Initiative