Namespaces in AL (Business Central)
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
- Part 1: Rulesets in Business Central
- Part 2: Namespaces in AL
- Part 3: VS Code Extensions for AL
- Part 4: Automated Tests in AL
- Part 5: Advanced CodeCop Analyzer and Custom Rulesets
- Part 6: How to make a code review
- Part 7: Preconditions and TryFunctions in AL