There is a coding pattern that has been proliferating the X++ code base for years. It is not an X++ best practices – nor is it object oriented; yet it is used quite heavily (unfortunately). Consider a simple class hierarchy with an abstract base class and 3 derived classes. A typical implementation of a factory would be a static method on the base class, like this: (Please ignore the type of the parameter – it could be anything, I choose str for simplicity)
Now; the problems with this approach are many.
- First of all the base class has references to the sub classes. Why is that a problem? Consider the base class is a framework class – is it a good idea for framework classes to have references to consumer classes of the framework? Of course not – we don’t like that coupling.
- Secondarily; the 3 subclasses are all referenced by the same method. Any new sub class would require an update to the factory. This turns the method into a congestion point, and it creates a coupling between sub-classes.
The coupling between the 4 classes spells trouble. If you try to modularize an application written like this, you will quickly realize that the pattern above is bad. You cannot have references from lower-level models (aka. assemblies/modules) to higher-level models. Yet; having a single factory method is valuable and a good practice.
SysExtension Framework to the rescue.
Consider you decorate the subclasses with an attribute, like depicted here:
Then you can rewrite the factory method to this:
The extension framework returns an instance of the right subclass automatically. It uses the attribute to determine which subclass instance to create. Quite simple – extraordinary powerful!
- Truly decoupled! New subclasses can be added without any changes to the base class.
- Less code is required! In the example here the delta is not significant – but sometimes you have switch statements spanning hundreds of lines.
- No change in the public API! The contract stays the same – this is an easy and low risk refactoring.
A few words of caution: There is a small performance impact on cold systems when using the SysExtension framework. In most cases you will not notice it; however – for performance critical paths, you should measure the impact of this change before going for it.
To learn more about the SysExtension framework see here.