Let’s continue where we left off last week when I shared with you two blog posts about my opinion regarding best practices for Per Tenant Extensions.
I used you as a guineapig for the project I am currently working on a PrintVis to get some early feedback from the community before I pitched my ideas to the development team there.
In short I can say that it went both good and bad and I’ll explain a bit why.
The biggest problem is perhaps that an average PrintVis implementation does not require that many customizations. The solution has been implemented about 400 times in 25 years and it is very mature. Most projects would not have more than the “Core” and “Report Pack” folder.
That does not mean they did not like the idea of having more complex modules in separate folders and make them compile individually.
At first I thought that the next blogpost in this series would be about the folder structure of the “Core” module, but I decided to skip that until the next post and move to the most frequently asked question I got from both the PrintVis developers and the community.
How the heck do you work around not having dependencies and multiple table and page extensions in one project?— Everyone…
The solution here came from my good friend Michael Nielsen as he pointed me in the right direction.
The AL development language is based on C# even though it’s core syntax is based on pascal. – Confusing –
Everything we do in AL is actually converted into C# code. In the old days you could even debug this generated code. I cannot believe I am calling this the old days since I remember the demo at Directions NA like yesterday. I am getting old.
Since C# is essentially the base of our language, most new features we get are actually copied from this into AL. We are moving into a hybrid Pascal/C# language. #Fun…
A very clear example of this is the use of the Dictionary type which works almost exactly the same as in C# and allows you to run AL code a million times faster than the old temporary tables did.
Another thing we got from C# are PreProcessorSymbols. They have been with us for quite a while and they are extremely powerful for clean code fanatics like me.
What does it do?
The first thing you need to do is to add the PreProcessorSymbols tag to one of the App.json files you are working with.
Personally I recommend adding it to your PerTenantExtension and code exceptions against it. This way your modules don’t need it in the app.json and you cannot forget to put them in or remove it when maintaining them in their own Git repositories.
As you know, I like descriptive names, so we call this one “PerTenantExtension”.
The next thing you do is to add exception code to duplicate objects. Whenever you need a table extension or a page extension in a module, add it in two places and use this in the module folder
This means that if your app.json file contains the PerTenantExtension tag it will compile the code, but else it will ignore it.
But this is code cloning!
Yes it is. And that is all that can be said about it. It is duplicate code, it is error prone and it requires discipline.
Unfortunately this is the only way right now.
Not all is lost. What if we find a way to manage this somehow with a Visual Studio Code extension? What if there were an extension that “recognises” this tag and handles this for us in our “Core” extension.
After my miserably failed webinar I got a few offers from community members to investigate this and I plan to spend some time trying to get this organized.
And what about Microsoft?
Another solution could be that Microsoft pitches in and allow us to have multiple Table and Page extensions in one project and merge them into one C# file at compile time.
It would be wonderful if they could do that, but as there are procedures we probably first need community buy in, pitch it as an idea on the ideas website and then upvote it.
That may take some time, but it may be worth it.
It’s worth the discipline!
If you want my personal opinion, it’s worth the effort and discipline. If I were owner of a Business Central shop with a few hundred customers this is what allows you to manage customizations without the hassle of dependencies, maintaining AppSource apps and more.
Customers will be on different versions right?
Let’s compare this way of working to dependencies and AppSource.
Personally I think dependencies belong in AppSource. It’s way too complicated to maintain dependencies for multiple Per Tenant Extensions. It may be possible when you are doing the initial implementation and everything still lives in your head, but if the customer goes into production you’ll forget. Someone else needs to maintain it and the’ll spend ours untangling your dependencies.
“When I wrote this, only God and I understood what I was doing. Now, God only knows.”— Unkonwn
Do customers really want updates?
When customers are happy and up and running they often don’t want updates.
Let’s say that after the first implementation you took a module and added things for a second customer, do you really think your first customer actually cares? And you may have introduced a bug for the initial customer.
If you clone a module into a Per Tenant Extension your customer will be on that version until you explicitly decide to upgrade them and then you can manage it.
You can have a situation where you visit the customer six months after production, have a cup of coffee and tell them how you enhanced the code and sell them an upgrade, with some consultancy hours to.
If your module were on AppSource the customer would have gotten it for free at a time they did not want it and be upset and demand you to spend time fix it for free.
Your Feedback Matters!
Best Practices only work in a community! I enjoyed all of last weeks comments and used them to improve and learn. Please continue to leave comments here, on Twitter, LinkedIn or simply send me an email.
Thanks and with love,
So can I have the preprocessorSymbol in app1’s app.json, and then use the symbol in app2?