A lot has been written and talked about extensions, so why should I write more about it? Or better, why should you read more about it? I think, there is still a lot of confusion around extensions and also misconceptions of what extensions should be used for and what not. And, since extensions are the only way to extend Dynamics 365 for Financials, they also won’t go away.
What are extensions?
Microsoft states on their page Extending Microsoft Dynamics NAV using extension packages:
You can extend and customize a Microsoft Dynamics NAV deployment without modify the original application objects. With extension packages, you install, upgrade, and uninstall functionality in on-premises deployments or for select tenants in a multitenant deployment. Customers can easily add or remove horizontal or customized functionality to their solution that upgrade much easier than past solutions.
Doesn’t that sound great? I can customize a NAV deployment without modifying the original application objects. And I don’t have to worry about upgrading – the extensions upgrade themselves.
Yes, I am a bit sarcastic here, especially, since I think that this “selling point” of extensions also creates the biggest confusion, but I will go into that a bit more later. Now back to “what are extensions?”. Extensions are indeed packages that contain additional functionality, report layouts (at least starting in NAV 2017), permissions, and more and can easily be installed and uninstalled and upgraded.
There are a lot of different articles out there that define how to develop an extension, how to publish, install, and uninstall them. Microsoft has everything in the link I posted above and you can also find a lot of tips and walkthroughs in different blogs. But basically, you develop the functionality in a stock NAV database, export the changes, create a differential and combine that into a navx package and then you can publish it and install it wherever you want.
How do I develop an extension?
You cannot make changes in standard code when developing an extension. You can modify standard objects and add fields or keys to tables and you can add fields or actions to pages. But you cannot add any code to the triggers of the new fields, to any existing triggers, to existing or new actions, and you cannot modify reports.
This sounds like a big limitation. Yes, it is. However, you can still develop a lot of functionality as an extension. You will have to use events, the new “hype” in Dynamics NAV. Events were introduced in NAV 2016, but there were not a lot available. With NAV 2017, you now have events available in a lot of places so that, if you design the code properly, you can nearly develop anything you want as an extension.
And, since you cannot create a navx package without also taking care of upgrading your data from one version to the next (or even from any version of the extension to the newest version), it is really great – extensions can be installed without having to change standard objects and they upgrade themselves. Therefore, upgrades will be a lot easier in the future when extensions are used.
Once the extension package is created, it is also not that easy anymore to see the code of the extension, which means that your code is protected. You can see the source code of an extension through the debugger, but you cannot access the code through the development environment and you can also not modify an extension, unless you have the source code.
Who should develop extensions?
This sounds all really great, so shouldn’t I just write any new modification as an extension? NO! Please don’t do that. Extensions are meant mainly for ISVs, who want to create functionality for Dynamics 365 and want to be able to sell that functionality to Dynamics 365 users. And since Dynamics 365 is based on Dynamics NAV, ISVs can also deliver their add-ons as extensions to Dynamics NAV partners and customers.
I am working for a NAV VAR, what is the problem, if I develop a customer’s modification as an extension instead of normal object modifications? Well, technically there is no real problem, it will work and the customer will get the functionality. However, if someone else would want to modify the functionality, it would not be possible, because the functionality can only be modified, if the developer has the source code. So, if you create an extension for a customer modification and do not deliver the source code to the customer, you are holding the customer hostage. It means that the customer would not be able to have an internal developer make modifications or leave one partner and go to a different partner, without having to invest a lot of resources and money to recreate functionality – during an upgrade or if the extension functionality doesn’t work as desired.
Modifications for customers should still be made as normal object modifications, extensions are not meant for this. While it sounds great to be able to bind the customer to the current VAR, it is not good business practice. A customer should want to stay with you, because you provide vertical expertise, great customer service, and just provide great value for your customer. If a customer only stays, because you are the only one who can make changes to their functionality, you should rethink that relationship with your customer.
What can I learn from extensions?
Although you shouldn’t actually create extensions for modifications for one specific customer, you should look at the way extensions are developed. Since standard code is not modified, it is easy to upgrade any code that is written in an “extension like” manner. I guess, a lot of us have always spent a lot of effort to create functionality that is not invasive in standard code and that is easy to upgrade. There are a lot of different patterns officially described that can just achieve that. Events are only one possibility to get you there. Events solve issues, but also create more issues, unfortunately. I will talk about this more in a different post. Using events or hooks or other patterns will, however, make it easier to upgrade your modifications to future versions. If you keep your modifications of standard objects to adding fields and actions and use events or hooks to implement your custom business logic, you will be able to use the PowerShell commands to merge objects to upgrade your code.
Just as a small example. I have upgraded a vertical solution from 2015 to 2016 and have spent days and days and weeks to upgrade the functionality while also refactoring some of the code (redesigning code to make it less invasive and implement patterns). I have continued refactoring the code while bringing the solution to 2017. Instead of spending days for a code upgrade, I now am able to utilize the PowerShell commands to upgrade the code from one CTP to another CTP (since I was part of the TAP program for NAV 2017, I started moving the vertical solutions through the different releases). The upgrade from one release to the next now takes a few minutes only. Isn’t that great? The majority of NAV customers did not upgrade to each new version of NAV, since it was just too expensive to do so. Companies cannot invest $100,000 or more a year in upgrading. However, if we only need a few days to upgrade to the new version, even if we have a highly customized solution, doesn’t this make it more affordable?
If you are working for a VAR, you probably now think: Why should I do that? I am making less money when I can’t sell my development services. Not necessarily. A customer that upgrades every year and wants to take advantage of new technologies and functionality requires additional services – services that actually bring business value to the customer and make their daily tasks easier. And you as the VAR can sell the customer the additional services.
So, to summarize everything: Extensions are not for everyone. Unless you are an ISV or want to sell functionality for Dynamics 365 or NAV as an add-on, you do not need and should not create extensions. But you should start going back to the basics and question every single line of code you are writing – is this code in the right spot? Do I have to make this change? Can I do it differently with less impact on standard objects? This will not only make us better developers, make our code look prettier (and who doesn’t like pretty code), but also improve upgradeability of our code. And this results in more value for your customers.