The community often criticizes Microsoft for adding new platform features only when Microsoft needed them. Well, it has been a bit too harsh – Microsoft did add improvements in other situations, too. But still, if you compare it to other Microsoft’s languages like TypeScript or C#, the AL language isn’t really advancing.
Looking back at C/AL, the AL language has really brought a lot of improvements. We have native JSON types, HTTP API, interfaces, overloads, and a lot more. But still, the overall change of the AL language was minor improvement, rather than a real evolution that transition to VS Code could have allowed.
Here’s the list of top five things I’d absolutely love to see in AL. And I have strong reasons to believe that all of them would be fairly easy to implement for Microsoft. Let’s get started.
A lot of languages have a keyword that refers to the current instance of an object from within the object. C# uses
this. Visual Basic uses
Me. Python uses
self. AL doesn’t have it. Or it does… ish.
In AL, we can already refer to the current record through the
Rec variable. We can already refer to the current page instance through the
CurrPage variable. In reports, we have
CurrReport. They allow to do things with the current instance of wherever we are. For codeunits, we don’t have such a thing. Why?
Codeunits in AL support instances. You can have multiple instances of the same codeunit. Instances are relevant for architecture and design (otherwise, they all be static, or single-instance in AL terminology). But the fact that we can’t refer to the current instance from within the instance itself means that when we need the reference to a running instance, we must control it from the outside.
While this probably was sufficient back in late 1980ies, in 2020 it leaves a lot to be desired. One of the reasons is that with event subscriptions, we may want to have a more granular control of our code (and state) than is supported by default.
Let’s take this example of event subscriptions. You can bind event subscriptions to an instance from outside, but not from within a codeunit. What if I am inside a function of a manually-bound codeunit, and I want – for a short while – to bind *this* instance to events? I’d love to be able to do something like this:
In a lot of situations, I can say that whoever called such a function should first bind subscriptions on the codeunit instance it’s working with. However, sometimes the decision needs to be made from within the codeunit itself. Currently, the only way to do this is to pass the variable from an outer scope that has access to it. Something like this:
However, this doesn’t cover all of the situations. For example, if you are inside a statically-bound non-single-instance codeunit (most of codeunits are this kind, anyway), and you are inside a subscriber, and you need access to current instance (perhaps to pass forward to some other piece of code), you are stuck.
I am pretty sure who wanted to do some scalable, modular architecture with AL, sooner or later wanted to have some kind of an equivalent to the
How difficult would it be for Microsoft to implement this one? I guess not difficult at all.
As you may guess, the
CodeunitRef type would allow us to keep a reference to any codeunit. If you ask why would anyone need such a type, well – we have
RecordRef, and why would anyone want that?
The question was rhetorical – I know very well why we need
RecordRef, and it’s a powerful type. Just the same kind of power it adds to
CodeunitRef would add to
I actually wrote one full-blown article about
CodeunitRef. It was one of the series of articles and a part of my active effort to push for more polymorphism in AL. I have been quite loud about it for years, writing, talking about, pushing and lobbying for codeunit interfaces, and my suggestion to include codeunit interfaces in AL became the most upvoted product suggestion (and it still is!) in less than a day, and Microsoft eventually shipped it. We needed codeunit interfaces that much, and Microsoft listened.
But, interefaces answer only a part of the problem. When we are tightly bound, and control both the caller and the callee, interfaces are not only enough – they are actually much better at doing whatever a hypothetical
CodeunitRef could do in those scenarios. However, when we are as loosely bound as we are in the event-driven world of extensions,
CodeunitRefs would solve all of the remaining situations.
One of the things – for example – that bothers me a lot recently, is the absence of a way to rollback and continue. Yes, the
if Codeunit.Run() construct helps there, but it requires either the hijacking of the OnRun trigger or writing a wrapper codeunit for each codeunit that may want to roll back. This adds a lot of boilerplate code, which is just a fancy name for code duplication and is definitely the best solution we could have.
CodeunitRefs would enable us to reduce this duplication tremendously.
But this is just one of the examples. What if I wanted to instantiate any instance of any codeunit, while not knowing the exact codeunit id at the compile time? I mean, this is precisely what we do with records and
RecordRef. With interfaces, we can do this through a factory pattern, but factory is monolithic and requires advance knowledge of all possible interfaces. Yes, we can defer that knowledge by adding an event publisher to the factory method. This would make the factory extensible, but wouldn’t solve the advance knowledge issue (somebody, somewhere, still needs to know about all the possible interfaces under it’s own domain of control). More advanced patterns (such as any of the inversion of control patterns) are mostly completely unavailable to us in AL.
CodeunitRefs could enable a lot of them.
CodeunitRef type would allow us to cast codeunits to and from it, to check whether the variable contains a specific codeunit by id, and also whether it contains a codeunit that implements a specific interface.
#3: More reference return types
Right now, in AL, function return types can be simple types plus Json types, Xml types, and some select types that I suspect Microsoft needed for their code.
For example, this is fine:
But this is not:
(It’s not at all about RecordId, don’t catch on to that particular type here!)
When Microsoft introduced Json types in AL, they made it possible to return those types from functions. That was an amazingly cool thing, as we could now do this:
Still, when they introduced lists and dictionaries, they didn’t make sure we can do this, for example:
Yet, for some reason, this is fine:
There isn’t much consistency about the return types anymore. AL brought a ton of new auxiliary types to describe things such as data classification, execution context, telemetry, and more – all of which can be used as return types.
HttpHeaders – for example – is a good return type, but
HttpContent are not. Why is that so?
One thing that would be incredibly amazing, would be returning codeunit or interface types from functions. Wouldn’t this be amazing:
A lot of languages allow us to create data structures to represent entities that can be described by more than one attribute. In C# you can do this:
(you can change
class if you want)
Similarly, C# allows us to have anonymous types, like this:
I would just love to be able to do this in AL:
This would allow me to hold arbitrary data structures that are only ever kept in memory. I could do
List of [Person] or
Dictionary of [Guid, Person], and a lot more.
controladdin type, this type would be automatically serializable to and from JSON, so I could declare it on methods and events on
#5: More (and more versatile) collections
When Microsoft introduced
Dictionary types, they were provided to facilitate transition from
DotNet types used earlier. I believe lists and dictionaries were among the most commonly used .NET collections we all used in our AL code.
However, there are two more generic collections that I believe people used from .NET:
Stack. I would be absolutely thrilled to be able to do things like
Queue of [Text] or,
Stack of [Integer], or… god forbid
Queue of [Interface Foo].
Talking about collection versatility, right now we can put some select types into collections. Texts, guids, integers, decimals, they are all fine in lists and dictionaries. We can also have all Json and Xml types there. We can even have collection types, so a
Dictionary of [Guid, List of [Dictionary of [Integer, JsonArray]]] is quite fine.
However, we can’t have collections over more complex AL types, such as codeunits or interfaces.
List of [Interface Foo] or
Dictionary of [Text, Codeunit Bar]] would be amazingly powerful. Now that I am dreaming, the ultimate mother of all collections in AL would be
List of [Object Person]. Yes, keeping a collection of in-memory-only arbitrary objects (check my #4) would just blow my brains off.
Notable mention: Rollback
Yeah, I know. I am boring already about this, but an explicit Rollback is a low-hanging fruit. We do have explicit
Commit, so why not explicit
That’s it. This is my top five. Tell me what your top five are, or if you are just happy enough with what you already have in AL?
This Post Has 7 Comments
Can you create also serialaizable objects?
That’s what I talk about in #4, isn’t it?
I would like variable groups where you could init the group and all the variables in the group would be initialized.
Let the group be single or an array.
Allow a group to contain lists and let the groups be referenced by the group index.
Allow the lists to have good search capabilities and sorting.
Allow the group to be sorted by one or more of its variables if it is an array group or a list group.
I think you can do a rollback like this if you want:
It will roll back and the code continues. Not clean, but it works.
Really? You can? 😉 https://vjeko.com/2020/11/06/how-about-rollback-in-al/ and https://vjeko.com/2014/10/17/cal-rollback-without-error/
And it was in my conf sessions since 2011. Not only it’s not clean – it doesn’t work in AppSource. So – no.
I think AL language is introduced by keeping business in mind. That’s why limitations are there, otherwise there is no reason for these features to be restricted.
AL language has nothing to do with having business in mind. Nor do those limitations I listed here. AL is replacement for C/AL. As a language it has been through a lot of evolution and improvement. And it can. The limitations are there because when AL was started nobody needed those features, and it’s slow to improve primarily because Microsoft’s internal budgeting reasons, more than anything else. “Business in mind” is a nice buzzphraze, just doesn’t mean anything at all in this context.