SysExtension Framework – to the rescue


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)

image

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:

image

Then you can rewrite the factory method to this:

image

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!

Now notice:

  • 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.


Comments (5)

  1. jaestevan says:

    Awesome! The need of modifying the factory class was a point against the "minimal over layered objects" principle, and in 2012 is more important than ever to maintain the best independence between models. Nice improvement.

  2. Max Arephin says:

    Oh, well and we completely losing ability to cross-reference class hierarchy. Yes, that's truly is "how's it should be done", but with the existing lack of coding tools in real environment I'd prefer to stay at old proven position; At least to that time, when coding tools in AX2012 will catch up coding technologies.

  3. Kenny Saelen says:

    Nice one!

    I constantly use the strategy and the one thing I hated about it was the switch indeed! The SysExtension framework has been on the radar, but now I finally see a nice example of what it can do for us.

    This is the stuff I hope for when openening up my reader 🙂

  4. OK … now the real question comes … why would I want to have anything like that? Because someone wrote somewhere that you should have a class factory so you bend backwards to make one even when it serves no purpose?

  5. mfp says:

    @Max Arephin: From a tooling perspective this is not much different from using an interface. You can use crossreference on the interface to find which classes implements it. Just like you can use crossreference on the attribute to find the classes decorated with it. Also you have the Type hierarchy browser to quickly give you an overview of a class hierarchy. Yes, it is correct that introducing a layer of abstraction adds a level of indirection that you need to understand when reading code and navigate when using tools.

    @JendaPerl: Take a look here: en.wikipedia.org/…/Factory_pattern for some good reasons to use a factory pattern. But as with every other pattern – it should only be used when it makes sense.