In bigger and long-running projects you are faced more often than not with task to rework already existing coding. For example, the project used a specific version of a library and now it is time to upgrade this version to benefit from new features. Therefore the places in the coding where the library is used have to be found and adjusted.
In ABAP development, we see from time to time that some constructs are defined as obsolete. While there is in most cases no need to rework the code that makes use of these constructs as backward compatibility is done to the max in the ABAP stack (even to a point where it starts to get painful…), one might get rid of these obsolete coding for different reasons like
- being state of the art
- using it as a good “excuse” for doing additional refactoring work in the surroundings
- just for feeling better not to rely on obsolete and possibly not supported features
But what to do if your project is a very long-running one and the amount of coding that would need a rework is really huge (say: above one million lines of code)? Wouldn’t it be nice to first concentrate on that parts that are actually used daily in your productive system? If this is the case I probably have a little hint for you.
Let me give you an example that I had to deal with recently: We just upgraded one of our main ABAP systems from 7.01 to 7.40 SP7. A giant step forward and it went ok, except for one little problem. It seemed that using an old construct that was marked as deprecated years ago lead the using programs to dump when used heavyly in parallel (after some weeks it turned out that it was “just” a small bug in the ABAP kernel, but this is another story…).
As I searched for this construct in the code base of our 15 year old application with over 10 Mio. lines of code using a Code Inspector test, I found round about 400 places. Adjusting all of these places seemed to be a little bit too much even for a boring and rainy Friday afternoon, so I thought about how to strip this set down to reduce my work. Always remember: A good developer is a lazy one. 🙂
Within a mailing thread with Boris Gebhardt concerning the Code Inspector tests for HANA readiness he gave me the hint to use one of the many, but not so well-known object collectors to reduce the set of development objects to scan. A good advice for my task, as one of these object collectors was just the one I was searching for! But it needed a little bit of support from another tool.
Recently, we activated the Usage and Procedure Logging (UPL) on our productiv system to know about the used and the not used development objects. There is a nice document about Usage Procedure Logging (UPL) from Ashishkumar Banker that explains what UPL is and how it can be used. The link for an official how-to guide to UPL can also be found in Getting started with Usage and Procedure Logging (UPL) by Shuge Guo and Bjoern Panter. The official guide clearly explains the benefits of UPL compared to other monitoring tools like ST03, ABAP Coverage Analyzer and others. One of these benefits is that you get nearly no performance penalty from activating it, so you can safely do so even in productive systems to monitor the real stuff that is going on.
While UPL is well integrated into Solution Manager’s Custom Code Lifecycle Management for managing obsolete and not used objects, there are also use cases when used on the monitored system in stand-alone mode. One of these use cases is to get a list of executable development objects that were actually used during the monitoring phase for further analysis.
Let’s start the work!
If you have actived UPL according to the guides mentioned and let it do its magic for the planed amount of time (in our system it keeps a history of 31 days), you can start to harvest the results. Just start the report /SDF/SHOW_UPL and just the parameters to your needs. For example, I was interested in our own code so I narrowed the results to custom packages (“Z*”).
Marked red in the screen shot you find the parameter that will return the found results in a format that can be used with Code Inspector and one of its object colletors.
After some seconds, you will get a file that contains all the used objects in the following format:
As you can see it is simply a tab-separated list of the object type and the name, similar to the TADIR table.
Important to notice here: The export will always return the surrounding objects in cases of methods, From routines and function modules. The UPL records down to this level of granularity and could be more specific, but the current version of the object collector expects the list in exactly this format.
What does this mean? For the presented use case it will result in some “false positives” as the Code Inspector will scan a whole class and not perhaps just the few methods that were actually executed. This is not correct from an academic point of view but for most use cases, the reduction of needed work will probably be good enough. And it is perhaps another argument against monster classes with too much responsibilities. 🙂
For my use case I tried to check how this would affect my results. Therefore I used my free SAP Lumira account at https://cloud.saplumira.com to do a bit of analysis of the executed objects. As you can see in the diagram below, the top 25 packages are used very similar throughout a week and this also holds true for the top 10 development objects.
When I analyzed the data set a bit further I found out that in most cases surrounding objects are used to nearly 80% of their sub parts. So for me it was acceptable to look at the surrounding objects instead of the fine level of methods and single function modules.
Ok, now we switch to the Code Inspector. With the list fromUPL we can create an object set using the object collector.
You will find the list of installed object collectors on the last tab of the main screen:
To actually see the list of object collectors, use the search help that is marked in the screen shot above and you will get a popup like this:
As you can see, there are many interesting object collectors available but I won’t go into details for all of them now. The object collector that is need is called “Objects form File Upload” and accepts a simple text file with the format mentioned above. When you select it you will be for the file and that’s it. You have just created an object set containing the really used objects in your productive system!
From here, it is the normal work with Code Inspector to search for certain constructs or errors. Create a new inspection with a matching check variant and the just created object set. When working on the result list of the inspection run you will be sure to work on just the objects that used. Nice!
There is of course one thing to remember: There is no guarantee that the set of objects that was executed during a small period of time is correct for a whole year. Some objects might just be used once a year on special dates. Keep this in mind when using UPL data on the managed system for narrowing down the search. Again, form an academic point of view, this way of doing things is not 100% correct. If you need more certainty you should probably have a look into Custom Code Management in the SAP Solution Manager. For my task (and perhaps also for some of yours) it was ok to probably miss out one or two objects. So I traded speed and ease of execution for absolute correctness.
Using the described procedure I was able to cut down the amount of needed rework to a half. As I started there were over 400 objects on my list. After matching these objects with the list from UPL, only 200 objects were left to concentrate on. Not bad for about 10 minutes of work.
The rest of the original list can be patched on another day or even be ignored. This depends on the probability of being used again and what happens if the problem should occur.
This will lead me to the end of my blog. I hope you enjoyed the ride and you cloud get some inspiration on using SAP tools in cooperation the reduce the amount of tedious work. If you have any comments or questions, just feel free to do so. I am looking forward to your feedback!