A “framework” for specific requirements in data transfer routines (and everywhere else?)
I’ve just finished another framework design for this scenario using SAP’s BAdI technology. You can find it here.
Hi guys and gals!
I’m pretty sure this has happened to pretty much everyone out there working in an international company. Sometimes a requirement comes along which is only supposed to be developed for a certain country. Or certain sales organization, certain whatever. It happens. The natural (and lazy) solution? The good old “IF” statement, correct? Now, if you’ve been around long enough you’ll know that, sooner or later, this will be a complete nightmare to maintain, with developers blocking one another, fighting over who is locking the include, fighting over who gets transported first, etc etc… so, what to do?
This blog post will propose a solution for a data transfer (or copy routine, or pretty much whatever) which I “designed”. Well, in all honesty, I didn’t really design it myself. Basically it is a “merge” of a pretty nice framework that was already in place somewhere I’ve worked before, and this blog post right here: Factory-Pattern in ABAP OO.
Ok so what’s the idea? Not very complicated actually. Let’s say that there will be requirements common throughout the entire system, the entire landscape of companies/users/whatever using the system. Let’s call these (and this is not an original idea) the “CORE” requirements. Next, will come maybe requirements for a specific country? Maybe a specific sales organization? I guess someone should decide how “granular” this encapsulation should be, the compromise being, if you’re too specific, you’ll have to configure a lot of table entries (or ifs) for the same requirement. Not specific enough and you’ll still have some fighting over who is locking what, but not as bad as before. Or you can start general and then repeat the process on a more specific level. I don’t know, that’s why I’m writing this blog post, let’s discuss 🙂
So, I picked up a pen and a piece of paper and tried to design something. I came up with this. An interface that the specific classes will implement. A factory that will return one object implementing this interface. A class that will execute the CORE requirement and will ask the factory for the specific requirement and execute it. I’m going to try and draw it based on other examples. Let’s see:
Wow… this came out worse than I thought it would… You can still refer to the blog post I mentioned above. The drawings are prettier 🙂 Hopefully you’ll be able to get the full picture when we get to the implementation!
Ok so, we’re going to be looking at something pretty standard (I think). Data transfer from a sales order into a delivery. From the standard routine we have following information:
* The following work areas are available: *
* LIKP – Header of the delivery *
* CVBAK – Header of the reference document *
So I thought… I should probably start with an interface for that. A very simple interface it turned out to be indeed:
With the following parameters:
I created a class for both the core requirements and the specific requirements, both implementing this interface… not that it would be important for the core class to implement it, but it’s nicer! Keep in mind that if you want to implement the interface in the core class, it will have to be instantiated, so for now I didn’t implement the interface in the core class!
Ok so now we should implement the factory! As you can see in the blog post I mentioned above, you can read some customizing table, and you can pretty much return any object you see fit, as long as it implements the interface we created in the beginning. I think that’s pretty cool. So here’s my factory:
Now the static method that I will call from the data transfer routine!
And that’s it! To test this I wrote a very small program. Oh, yes, I forgot to catch the exception, so if I enter a sales organization different than 4230 (I hope that’s not confidential information…) it will dump… keep this in mind ok? 🙂
PARAMETERS: p_vkorg TYPE vkorg.
SELECT SINGLE * FROM vbak
INTO CORRESPONDING FIELDS OF ls_vbak
WHERE vkorg = p_vkorg.
i_vbak = ls_vbak
c_likp = ls_likp ).
So now the interesting part (for me). Let’s discuss! What would you have done differently? While pasting I thought… it would probably be really cool to have the factory return a table of implementations and execute them one by one, pretty much like the BAdI framework. Would this be easy to implement? How? Leave your comments below, let’s see if we can come up with an optimal solution 🙂
All my best,