D365 : Open but protected source code – Class Extension Approach


Hello guys.

My previous two posts were related to two fundamental concepts of OOP and I also gave the examples about how to use and test them as simple as possible. I will assume that you have already seen those posts and continue to a new subject.

In this post, I will try to explain class extension approach of D365. This is not a common OOP principle but still should be considered inside OOP methodology. You may find similar approaches for other platforms or solutions. For D365 this is a way of “open but protected source code” solution.

Microsoft always offers a flexible and easy – to – implement ERP solution with Dynamics products. In terms of TCO (Total Cost of Ownership) long term usage costs is always a matter of discussion. Even license and consultancy costs are usually lower than the competitors, upgrade costs are always unpredictable and unmanageable. The flexibility of the product has a drawback of unnecessary and uncontrollable developments.

In the early releases of D365, overlayering (traditional way of development) and extension model (new way of development) were supported at the same time. But Microsoft had officially announced support for development with overlayering will not continue in the future. And Partners should have to move their solutions to the extension model. Extensions are easier to maintain and upgrade but flexibility is limited.

“Extension” term might be a little bit confusing because the term “extends” is previously used and well known concept of OOP and also exists in X++. Please see this post for inheritance in D365.

childclass

As you can easily say, to use additional functionality of the child class (ClassB) should be directly called (instantiated) in the code.

The new concept of extension in X++ is quite different. To differentiate the concept, it is mostly referred as Augmentation” or “Chain of Command (Coc)”.  If a ClassY augments the ClassX in ModelM, even no change is made on the calls for ClassX, additional features of ClassX which are provided by ClassY will be “effective” on the ModelM.

If this is still not complex enough for you, than you should try this one : ClassX can have multiple different augmentations on different models. “Effective” version of ClassX is determined by the model of the call.

In any given condition, a class always have a single “effective” version on a specific model. Not like classic extension model, augmentation of a class are never referenced directly by the code, only by the runtime system.

Let’s see an example about this approach. Before we see the example, I have to say that there is a naming restriction about augmentation classes. It has to have “_Extension” as a suffix and it has to be final. And you have to use [ExtensionOf(classStr(className))] command at the top of the class. Here it goes :


[ExtensionOf(classStr(ClassA))]
final class ClassA_Extension
{
}

You can try to remove final keyword and _Extension suffix to see the compiler errors for yourself. But please see the screen shot below. Instead of super(…) call, this methodology uses next(…) command and it is mandatory unless the referred method explicitly marked as “Replaceable“.

cocerror

Let’s write a couple of lines and see the difference.


[ExtensionOf(classStr(ClassA))]
final class ClassA_Extension
{
public str methodPublic()
{
str ret;

ret = next methodPublic();

ret = strFmt("This part comes from CoC, %1", ret);

return ret;
}

}

If there are more than one augmentation of the same class, this next(…) call will find and run the other augmentations. At the and of the chain, the original method is called. This will create a “Chain of Command (CoC)” which is also the name of this new concept in D365.

I have commented the call for ClassB at the runnable class the rest is the same. This means call for classA is not changed but result is different. This is the most critical part, please pay attention.

class RunnableClassForTest
{
    ///
    /// Runs the class with the specified arguments.
    /// 

    /// The specified arguments.
    public static void main(Args _args)
    {
        ClassA objectClassA = new ClassA();
        objectClassA.integerPublic = 1;
        objectClassA.setPrivateInteger(10);
        objectClassA.setProtectedInteger(100);
        info(objectClassA.methodPublic());

        //ClassB objectClassB = new ClassB();
        //objectClassB.integerPublic = 2;
        //objectClassB.setPrivateInteger(20);
        //objectClassB.setProtectedInteger(200);

        //info(objectClassB.methodPublic());
    }

}

Here goes the result.

cocresult

It might be a little bit confusing and hard to understand. But it is a really key feature of extensions.

Next post will be about CoC alone and it will be a little bit deeper.

Ray (Emre) TUFEKCI

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s