This blog should share with you some current thoughts I have on how to shape the coding in the planning area of TM over the next years and how you will profit on that because of a easier structuring of enhancement.
To be honest the main reason why investigating on how to make modifications much easier weren’t you but the very good shift in SAPs mindset away from user test to a mindset of automatic testing with user tests for finding edge case issues (which should primarily fixed test driven). With this shift colleagues like me got more time to think about how to structure their unit tests, how to improve them and how to install certain concepts for easier automated test development.
One central point to test units rather than components is the possibility to inject dependent objects. Sadly, ABAP don’t know general dependency injection frameworks, so we needed to create our own way to inject dependencies.
I think the most common and most simple way is using constructor injection. In this concept your classes are getting optional parameters in the constructor to set certain member objects. In the logic it’s then checked whether the member is set and only if not, the real dependent object created and used. Now your test can fill the dependencies while in productive code the constructor is called without those parameters.
I don’t like this pattern for a simple reason: I believe that test code should be clearly separated from productive code. With the constructor injection the constructor and the place where the dependency is created need to add some code which is only there for testing purposes. For me this a best practice. Even though I cannot name or recommend you literature for that I feel in my own work as developer/architect that productive code should be as clear and easy to understand as possible.
So, I needed to find a better concept for injecting which I found with factory injection.
Basically, what I need here is to use the factory pattern and hand over responsibility to create classes to factories. The factories itself are implemented as singleton (not as a bunch of different static methods) with the factory as a global protected member.
In addition to the factory I create a second class which is the injector factory. This class can be defined as FOR TESTING and therefore is clearly test code. Now the trick comes into play, the injector factory is inheriting from the original factory and sets its own instance onto the singleton of the real factory.
With that the injector factory can take over all responsibilities of the origin factory and create dependent objects as they are injected from test code into members of the injector factory. The productive code does not know any of these adjustments.
A nice and easy example of this pattern can be found in the /SCMTMS/CL_COMMON_FACTORY but there are already other examples of this pattern to be found all over TM planning code (e.g. /SCMTMS/CL_PROF_ACCESS_FACTORY, /SCMTMS/CL_VSS_IL_FACTORY, /SCMTMS/CL_PLN_OL_FACTORY) and I expect the number to grow with the following releases as it’s a concept made for the future.
Nice Stuff – but What About Me?
Now I talked a lot about our ambitions to be better in our test automation but what has this to do with you guys? Well basically you can make use of the same concept as my test implementation does too. When writing custom code, you might overrule the standard factories with own factories allowing you to modify or exchange the standard logic in a much better way then pre-, post- or overwrite-exits.
Why is it better? Well you can easier decide when and whether during your logic the standard should be called (if you inherit the modification class from the standard class – which I would recommend you anyways). Furthermore, you directly have an own class for all adjustments of a standard class which might enable you to structure your enhancements much better.
From my feeling this kind of modification is much more convenient to you and will help you in custom projects (for sure you can mention your experiences and thoughts [especially disagreeing once] below in comments.
Modification or Enhancement?
It’s a pretty good question whether my enhancement concept is an enhancement, or a modification and I cannot tell you as I’m not a lawyer and I’m not sure about the real definition in our contracts. For me as someone who can write code (and I guess therefore for most of you) it’s clearly a modification if you overrule a standard class creation to create a modified version. From a definition perspective it might be that it’s an enhancement if you find a nice BadI running before the origin factory creation to inject yours. But please do not stress our maintenance contracts as I would really hate to make the factories private attributes which are only visible to my injectors (which I would FRIEND then).
Let’s play fair and threat it as the modification it is 😉