I did not write on the blog for a long time because I was too busy working on projects and was not in the mood for blogging. But today I want to write about the new concept of abstraction introduced in AL in 2020: D365 Business Central interfaces.
So, first what are interfaces and why use them?
Interfaces are somehow like codeunits, excepting that an interface can only contain method signatures(name, parameters), not also the implementation of these methods. Interfaces are a way to achieve polymorphism. Polymorphism means “to have many forms”, so an interface can be used to call functions from different Codeunits, bearing the same name, but each having different behaviors. Before an interface can be used, one or more Codeunits must implement that interface.
The most simple example: imagine we have a “Cat” and a “Dog” codeunits with same method “MakeSound”, as both animals make a sound, but in a different way. And we have also an Interface “Animal”. When we want to call the “MakeSound” function on any of the codeunits that implement that interface, we could, instead of using the codeunit, use the Interface, thus obtaining polymorphism.
In order for the Interface to know that it needs to call the “MakeSound” method from a specific Codeunit that implements it, we use Enums. Interfaces can also be used as parameters in functions, so this is one reason to use them. Because a function can receive as argument an “Animal” and we can now have one function instead of 2 or more different functions. Without interface, each function would receive as argument a Dog or a Cat or some other animal. By using an Interface, in case we need to add a 3rd animal, there is no need to update functions which use “Animals”.
Ok, enough with the theory and the classic example with Animals used to explain the concept of interfaces and polymorphism in programming. Let’s see how and why we can use this in Business Central.
Real Life Example
Imagine that you need to create Integration between Business Central and the web sites of a company. The company uses Business Central as their ERP and have let’s say 3 different web sites where they sell their BC Items. We want to maintain Items only in BC and synchronize these with the websites when someone changes Item related data in BC.
For this, we create a table “Web Integration Action Log” and every time something changes in BC we create an action in this table. For example “Insert” item, “Modify” item, “Delete” item. By default these actions are not Processed. We can manually process them (one by one or in bulk) or automatically by creating a Job Queue which runs every minute and process new records in this table.
“Process” means that we will make web API call requests to send data to the web sites. We have checkmarks on each item if is “Active For Website 1”, “Active For Website 2” etc. So if an item is “Active for Website 1” and is modified, we create action record for Web Site 1 and so on.
Each Web Site has it’s own API, so when we process the line(s), we need to send all records for website 1 to a codeunit that handles website 1 processing. The records for website 2 to codeunit that handles website 2 processing and so on, no matter how many websites we have now or in future.
In the past, we would probably have a Case statement under the Process buttons, so if Action Type = Website 1, we call proper codeunit. But, if we then need to add more web sites in future, this way we need to change code under Processing actions.
If we use a Business Central Interface instead of Case statement, we write code under Process actions now and we don’t have to update it in future. We will just write another codeunit that implements same interface and the code will ‘magically’ know to use that one.
So, let’s see now how we can do that.
First, we create interface “iWebSiteActionsProcessor” with methods signatures:
This Interface specifies that all codeunits that implement it must contain a method “ProcessAction” with 2 overloads. One for individual line processing and another for bulk processing.
Second, the action Type(“For Website 1”, “For Website 2” etc.) is an Enum type which implements the “iWebSiteActionsProcessor” interface. Each Enum value has an Implementation of the Interface. So this is how we know what codeunit to execute. (in case value is “Website 1”, we use codeunit “Process Website 1 Actions” in below example):
Next step is when we write the code that process action records:
Notice how we use the Business Central Interface variable to call the method and how clean and abstract the code is now (without caring about how many websites there are- we can have 100 if we need- and without need to update a Case statement if new web sites appear).
We can go even further and change the above code to iterate through the Business Central ENUM elements and process the Items Bulk for all websites by doing something like this:
* this code calls ProcessActions method in each processor codeunit that implements the iWebSiteProcessor interface
We also have the processing codeunits which have their own individual logic, but must implement the methods of the interface. For example “Process Website 1 Actions” which is called in case Enum “For Website” has value “Website 1”:
*Codeunits and Enums can implement multiple interfaces and can have default implementation:
This was just a small example. Business Central Interfaces are a great tool and we should use them as often we have the opportunity to write better and easier to maintain code. Most of the times when you can group some things using the relation “Is A” (like for example Car Is A Vehicle, Dog Is An Animal, Process Web site Actions Is A Web site actions processor etc) an interface should be used.
You can find all files of the sample project below (for reference purposes):