Hi SCN community,

This blog post is a logical follow-up from this blog post of mine, where I share my design for a region specific implementation framework using ABAP OO and the factory pattern strategy design (what a fancy name!). From the discussion that followed the idea came up to try and make use of the BAdI technology available in SAP, and this is my proposal for a design using this technology!

This proposal is based in a lot of other blog posts, like this one by Andrea Olivieri, this one by Thomas Weiss, and many others. Check my bookmarks, I usually bookmark interesting stuff. These blogs show a more or less static view over BAdIs. What I found out while designing and implementing this approach, is that actually the BAdI technology is amazingly flexible and powerful. Hopefully you’ll share my point of view after reading this post.

Thanks to Debopriyo Mallick and Suhas Saha and their valuable contributions in the comments I have revised my design and, consequently, this blog post. I believe the design is now one step closer to that “idyllic”, probably non-existent, perfect solution. By the way, if you’re looking for an interesting way to activate/deactivate several BAdI implementations at once on different levels you should check this blog post that Suhas shared in the comments.

Also, Eitan Rosenberg has shared a very simple and flexible way to sort custom BAdIs in this blog post.

The premise

The premise remains pretty much the same as before, so I’m not going to go into it again in great detail. If you’re working in a system shared internationally, or by different regions, eventually you’ll get user-exits with so many IF and CASE statements, and shared by so many developers, that you will definitely want to have a framework put in place to cope with the specific requirements for each region/country/sales organization/whatever.

In my previous blog, the solution presented doesn’t have any flaws “per se” (not that I can think of), but it does represent a very strict and formal solution. If you want more flexibility and freedom, while retaining the same advantages, I think this BAdI design might be the way to go. It also doesn’t feel like you’re redesigning the wheel 🙂

Let’s get to it! I’m going to showcase this design with the user-exit INCLUDE MV45AFZZ. Anyone that has ever developed anything for SD should probably know this user-exit, so I think it’s the perfect candidate.

Oh, by the way, this is NOT meant to teach you how to create a BAdI. If you are unfamiliar with BAdIs, please take a look into the blog posts I mentioned above.

Let’s go!

We start by creating the BAdI definition. The multiple use definition is arguable. For this example I will leave it on, and I guess this would be pretty much standard unless you want to make sure that ONLY ONE implementation of the BAdI is executed. You should keep in mind that when using this option you cannot have parameters defined as exporting/returning, as this would be against the idea behind it. Read in the comments for a more detailed explanation, or press F1 on it 😉 . Developers implementing this (and any multiple use) BAdI should pay attention to the fact that other implementations could also be executed and affect variables they are trying to determine, so proper documentation and descriptions of the BAdIs is not a bad idea. Also, in my first version of this blog post, I had defined one BAdI for the entire MV45AFZZ include, with one method per routine. After Debopriyo pointed out, and rightfully so, that this would mean many unimplemented methods in the BAdI implementations, I decided to revise this and have one BAdI definition per routine. I agree this makes more sense. Now, nabheet madan asked in the comments if it would also be a good idea to define one BAdI per method when applying this design on a standard BAdI. Quite honestly I’m not sure. I guess that would depend on the BAdI… if the BAdI has methods that are related to each other and should all be implemented, I guess one BAdI definition with the same interface as the standard BAdI would make more sense. Otherwise, to avoid having several unimplemented methods, it might not be a bad idea to define one BAdI per method. If you have something to say about this leave a comment below!

Picture1.png

Figure 1 – BAdI definition

Now, in my situation, we have different clients per region, so a filter that will come very handy for sure will be the client filter. So I set it up straigh from the start.

Picture2.png

Figure 2 – BAdI filter definition

In the discussion in the comments it was also pointed out that a BAdI with many parameters in the interface was a BAdI poorly designed, and this could be a problem in user-exits from include MV45AFZZ, since there is no formally defined interface. To “solve” this problem, I thought of defining one structure for the BAdI’s interface, like this.

Picture3.png

Figure 3 – Defining a structure to use in the BAdI’s interface

In this case I’ve already defined internal item table XVBAP, but if you don’t think you’re going to need anything special for now, you can just declare some dummy field, or don’t create this structure at all and create it only when you need it. It will not cause you any pain afterwards, even if you already have BAdI implementations created, as they will simply not use the newly created parameters. So, after revising the design thanks to the discussion in the comments, the BAdI interface now has only one method (in this example I’m showing the method for userexit_move_field_to_vbak).

Picture4.png

Picture5.png

Figure 4 – BAdI method definition

And that’s it for the BAdI definition (for now)! It wasn’t that difficult. Now all you have to do is call it from your routine.

Picture6.png

Figure 5 – Calling the BAdI from your user-exit

Ok so now we implement it! For this implementation, the requirement is specific to client 077. Couldn’t be easier.

Picture7.png

Figure 6 – Implementing a BAdI with a filter value

The rest of it is standard, yes? All you have to do is implement the method with the requirement you want. Personally I think the best would be one implementation per requirement. Major advantage is total independence per requirement. You can have one developer per requirement working at the same time on as many requirements as you’d like, no problems with object locking. The disadvantage could be low-awareness between developments. Meaning that a developer implementing a new requirement should take a look at already existing implementations to check if there’s not going to be some conflicting implementations (like a field being overwritten or something).

Now comes the really interesting part for me. What if a new requirement comes along which needs a new parameter? At first glance I would think this would mean a lot of trouble. Going through every implementation and adjusting. Well, not really… or at least I could do it without much trouble (but I guess you’d better not change the parameters already existing, just add new ones)! You change the structure we created earlier and add your new parameters:

Picture8.png

Figure 7 – Adjusting the BAdI’s interface

Now we need to populate this variable in the code and that’s it. The interface will update every implementations method signature, and if the parameters aren’t used… well… they’re not used, no problems there.

Picture9.png

Figure 8 – Adjusted BAdI call

You can now implement your second requirement easily. So, we now have implemented two BAdIs, filtered to be executed only for client 077. What if now we get a third requirement, which is to be executed globally? A core requirement? It also couldn’t be easier, we implement a filterless BAdI!

Picture10.png

Figure 9 – Implementing a filterless BAdI

The rest you already know. What happens in runtime? In runtime, regardless of which client you are on, the filterless BAdI is executed, and if you happen to be in client 077, the previous BAdIs get executed as well. As you should already know, there is no guarantee to which BAdI runs first (unless you implement a sorting mechanism), so make sure one implementation does not rely on a result from another implementation, and also try not to change the same fields, because only one value will prevail, and you have no idea which one. It means you can’t implement some default values for the “core” implementation and hope that the specific implementations will prevail, you have to implement this accordingly.

Actually, as Sougata Chatterjee pointed out in the comments, there is a way to sort BAdIs in the new Enhancement Framework. To do this you implement BAdI “BADI_SORTER”. You can find documentation on this here. Personally, I would try to avoid this. Even though it could be interesting to have a BAdI implementation for a global requirement being executed first, and then the local/specific requirements executed overriding the global requirements, I think this adds too much complexity and could be hard to maintain. I would rather have a requirement either global or specific, and if it’s not global, each region will have to implement it its own way. But now I know (and you know) this option is available.

Eitan Rosenberg has also shared a simple and flexible way to sort custom BAdIs. Check it out here.

There’s no such thing as too much flexibility, is there? 😛

Ok, last but not least, let’s say that even if we have successfully separated implementations per client, we’re still getting many conflicts. We want a new filter, per sales organization. That’s also not a problem, we change the BAdI’s definition! This is mostly valid if you are implementing multiple requirements in the same BAdI implementation, but I’ll keep this here for educational purposes.

Picture11.png

Figure 10 – Adding a filter to the BAdI’s definition

The existing implementations will not care! They will keep being executed as long as the values for their filters match. How cool is that? But of course, you will have to adjust the BAdI’s call, otherwise you’ll get a nasty runtime error!

Picture12.png

Figure 11 – Adjusting the BAdI’s instantiation for the new filter

Done properly, this will allow you to have a nice overview of your enhancements and requirements implemented in your system. You can also use the search feature in the enhancement spot implementation “implemented BAdIs” tab to search for filter value! Which is nice.

Picture13.png

Figure 12 – Enhancements overview

Picture14.png

Figure 13 – Checking BAdI implementations for a certain filter value combination

Conclusions

That’s it from me! I’ll admit, I think this approach is very elegant and powerful. Some care must be taken to make sure there are no conflicting implementations, but I don’t think there’s any way you can avoid that risk.

Let me know what you think and what you would do differently!

All my best,

Bruno

To report this post you need to login first.

36 Comments

You must be Logged on to comment or reply to a post.

  1. DEBOPRIYO MALLICK

    Hi Bruno,

    Thanks a lot for the article. Yes, I liked your attempt to design solution to resolve the MV45AFZZ routines coding problem for multiple implementation .

    However, I do feel that these userexits are not good candidates for migrating to BADI based approach. This is because in MV45AFZZ  userexits, we play around with the global variables and we never know from which global variable we will be using to fill or validate one field. For one case ,we may be needing 20 of these variables and in another only one.

    Ideally, interface signature should be static and enhanced if and only if absolutely  needed. In the scenario given above, why for one specific case, we should have 20 parameters in the signature (19 optional ).  Also, a lot of methods for each  BADI will be unutililized.

    Also, I want to share you another link on BADI designing :

    http://help.sap.com/saphelp_nwpi71/helpdata/en/44/f4440aa76b0c4be10000000a11466f/content.htm?frameset=/en/bd/523842134bad04e10000000a1550b0/frameset.htm

    I thoroughly enjoyed reading your first part of the series and design solutions by Matthew, Paul and Andrea.

    Regards,

    DPM

    (0) 
    1. Bruno Esperança Post author

      Hi Debopriyo,

      First of all, thanks for taking the time to read and comment, appreciate it.

      I will agree that customer-exits, with formally defined interfaces, and even standard BAdIs, are much better candidates for this solution. However, I don’t think include/routine based user-exits, like this popular MV45AFZZ are not candidates for this solution.

      What better solution would you propose for this situation?

      Nonetheless, your comment has given me a few ideas which I will implement and I will revise this blog post. For example, instead of adding the needed variables in the interface one by one, I will create an interface structure, and will populate the structure’s variables before calling the BAdI. Since I would have to change the standard include anyways when changing the BAdI’s interface, there is no downside to this approach, and everything will be neat and tidy.

      Also, you are right when saying that with this approach we will probably have many unimplemented methods. I don’t see this as a big problem, but at the same time defining one BAdI per routine might also be a good idea, and this would eliminate this problem. However, one BAdI definition per requirement is a BIG no no, as this would bring the exact problems we are trying to avoid, which are mainly poor readability/maintainability and “fighting” over locked objects…

      Thanks for your comment and for challenging this approach. There is ALWAYS room for improvement 🙂

      Best,

      Bruno

      (0) 
      1. DEBOPRIYO MALLICK

        Hi Bruno,

        Thanks for the clarification. Yes, we can have deep structures containing global variables of SAPMV45A.

        Another question I have is, most of the clients I worked for had too many enhancements in MV45AFZZ and requirements kept  on coming sometimes in cluster . One of my clients had around 65 enhancements spread across the userexits for the same company code & sales area  ( mostly in SAVE_DOCUMENT_PREPARE, MOVE_FIELD_TO_VBAK, MOVE_FIELD_TO_VBAP & SAVE_DOCUMENT ). Sometimes three of us were working on the different enhancements under same userexit and release to production lined up on the same date. To prevent object locking what we had done is –

        I) We put one include under each form userexits of MV45AFZZ. Inside those includes, we had added INCLUDES b

        FORM userexit_save_document_prepare.

          INCLUDE ZMV45AFZZ_SAVE_DOCUMENT_PREPARE.

        ENDFORM.

        INCLUDE ZMV45AFZZ_SAVE_DOCUMENT_PREPARE.

          contained

        INCLUDE RICEFW_1. ( my code)

        INCLUDE RICEFW_2 ( 2nd consultant’s code)

        INCLUDE RICEFW_3 ( 3rd consultant’s code)

        So, basically I want to know, for such scenarios, shall we create BADI implementations for each scenarios. According to you, what will be the best practice.

        Regards,

        DPM

        (0) 
        1. Bruno Esperança Post author

          Hi again Debopriyo!

          That an interesting question you ask, and actually, the strategy you share is the one I’m facing at the moment, and I can tell you why the company is investing in fixing it. Two major problems come from that strategy:

          • There is a very poor separation of concerns. This means that your code could very easily impact the code for other developers, and their code can have an impact on yours. The data declaration is not isolated, so very easily you could reuse someone else’s variables, and this will most probably lead to problems. Tell me, were you really “isolated” from the other developments? Or did you have to go in and look at what they were doing to make sure nothing would get broken? This might be feasible when there are 2, 3, maybe 4 requirements to implement, but when you get requirements by the dozens, I think it’s impossible.
          • The whole program has to be compiled every time there’s a modification, and a syntax error in one implementation will bring everyone to a halt. I don’t know how many requirements/lines of code you had in your case, but around here each time there’s a modification to MV45AFZZ people can wait almost for an hour for the transport to finish, and the program takes ages to compile. This is a problem. Also many times people face a runtime error from an implementation which is not relevant for them.

          To conclude, in my opinion, and this is what I’m going to push for around here, will be to have a BAdI definition per user-exit (instead of the whole include, thanks to your contribute), and what I’m still undecided about is whether it should be one BAdI implementation per requirement or if the requirements for the same region/organization should be called sequentially within the same BAdI implementation. I will ask this in my next revision for this blog post, maybe some of the (other) experts can chime in 🙂

          Thanks again for your contributions Debopryio!

          Best,

          Bruno

          (0) 
          1. Suhas Saha

            Hello Bruno,

            You can have a look at the Enh. spots – BADI_SD_SALES*.

            Afaik these BAdIs are for internal SAP use 🙁 You can use them as your reference & develop your framework.

            BR,

            Suhas

            (0) 
            1. Bruno Esperança Post author

              Interestingly enough, these BAdI interface definitions have a LONG list of parameters, just like the link shared by Debopriyo was advising AGAINST. Funny 🙂

              Thanks Suhas!

              KR,

              Bruno

              (0) 
          2. Nishant Gupta

            Hi Bruno,

            Thanks for sharing wonderful solutions and I thoroughly enjoyed the discussion which is happening here. Now, coming back to question which we have in hand “How to tackle multiple requirements for same filter” ? Of Course, one way could be having a separate implementation for each requirement. The other one which I could think of is developing one function module per requirement. The interface of this FM should be standard as of BADI method. Say, if we have 2 requirements for same filter, we can have 2 separate FM’s one for each requirement (having same interface). Then these call be called sequentially OR I would propose to maintain these FM’s in a customising table – say, for each implementation and method name – we can maintain these in a customising table. Then we can call this fm dynamically in a loop. The advantage here is we can switch off a requirement in production directly by just removing entry of that FM from this table. And in case of we have new requirement, we don’t need to touch the implementation again, we just have to develop the new FM and add an entry in customising table.

            So, it will look as follows –

            BEGIN of method.

            Select to read FM names from database.

            Loop at int table (  having FM names).

            call function (fm name)

            Importing

            par1

            exporting

            par2

            endfunction.

            endloop.

            endo of method.

            Regards

            Nishant

            (0) 
            1. Bruno Esperança Post author

              Hi Nishant!

              I’m glad you are enjoying the discussion. I am too, I have learnt a lot already from this discussion alone 🙂

              I want to thank you for your contribution, however I would go for a slightly different design. Let me tell you why. There is one thing I don’t like about dynamic calling of function modules… you lose the “where-used” functionality in SAP. If you think about it, the way you implemented it, is pretty much the same thing as how the BAdI works. The only difference is that with the BAdI’s you are not able to turn them on/off in production.

              If being able to turn them on/off in production is important, I would develop a Z table (customizing table but without transport) that would be checked at the top of each BAdI implementation, like Sougata does but he checks for switches instead of a customizing table.

              Now, there is one thing I don’t like about being able to turn implementation on/off at will in production, and it is a very serious thing… if you allow for this, very soon you will have different behaviors throughout your landscape, with completely different BAdI implementations being executed in development, quality and production systems. This will make it very difficult to test bug corrections and to provide support.

              In the end, I do as I’m told, and if the business “demands” for this option, I will provide it, but I will always vote against it.

              Thanks again for chiming in, and let me know what you think about what I wrote 🙂

              Best,

              Bruno

              (0) 
            2. Suhas Saha

              Hello Nishant,

              We had this same design in place 5 yrs ago, but honestly i didn’t like it.

              This is another example where you can use the OO & not procedural ABAP. You can build an interface & it’s implementing classes to achieve this in a more elegant way. (or custom BAdIs as Bruno has highlighted).

              BR,

              Suhas

              (0) 
              1. Nishant Gupta

                Hi Suhas and Bruno,

                I fully agree that for exits the above solution is quite nice. But, lets us discuss how to implement BADI’s which are provided by SAP. Say, I have a BADI (multiple use but filter independent as per definition) say SAP_SALES_BADI (dummy name). If I would like to implement this BADI for multiple logics like say, based upon Sales Org etc. What should be the best way to handle it ? Would you like to create multiple implementations for the BADI SAP_SALES_BADI , may be one for each Sales Org.?  Or here also, you would define a custom BADI with Filter as Sales org. say, ZCUSTOM_SALES_BADI. Then create filter dependent BADI implementations of this custom BADI ZCUSTOM_SALES_BADI. Then create only 1 impl. of standard SAP_SALES_BADI. call the custom BADI using GET_BADI and so on.

                Regards

                Nishant

                (0) 
                1. Bruno Esperança Post author

                  Hi again Nishant,

                  The second option, for sure 🙂

                  For many reasons:

                  • First, there is no disadvantage in defining your own custom BAdI inside a standard BAdI.
                  • Maybe there’s no real need for multiple use with a filter when your first requirement comes in, but if you define a custom BAdI immediately, when this time comes you will already have it ready and maintenance will be REALLY easy.
                  • Most of standard BAdIs are not multiple-use and don’t have a filter defined. By defining your custom BAdI you can bypass this lack of flexibility.

                  My opinion! Would you have anything against implementing your own custom BAdI inside a standard BAdI?

                  Also, it would be really easy to define a custom BAdI, since you can reuse the standard interface!

                  Best regards,

                  Bruno

                  (0) 
                  1. nabheet madan

                    Hi Bruno

                    Thanks for writing such a wonderful blog and with such a detailed and practical discussion.

                    My 2 cents. I have gone through all the comments and what I feel is in a SAP system if we have N number of standard BADI’s with Multiple checkbox without filter active you will choose to create N different BADI’s and then their respective implementations.

                    Wont this increase the number of custom objects to be handled.. ?

                    Seconldy if I go by above blog you are planning to create One BADI per subroutine. Will you follow the same approach for BADI’s methods also..?  For example if one BADI has 10 methods will you create 10 separate BADI definitions..?

                    Nabheet

                    (0) 
                    1. Bruno Esperança Post author

                      Hi there Nabheet!

                      Thank you for your kind comment. Coming from such a knowledgeable person as you it obviously means a lot to me 🙂 A lot of research and time went into it. I want to find the best solution for this common problem, that is why I’m sharing, and your comment mean a lot to me.

                      I’m not sure I understand your first question. Let me try and answer the way I understand it, and you’ll tell me if I understood it correctly or not. My suggestion for a standard multi-use filterless BAdI would be to create one custom BAdI definition for it, and ONE implementation of the standard BAdI definition to call this custom BAdI. There is only one advantage from this, it will enable you to have filters and only the BAdIs relevant to your region (or whatever you specify in the filters) will get executed. I do not see a disadvantage on doing this. Yes, in each method of the standard BAdI’s implementation you will have to call your custom BAdI, but you can do this as your requirements come in, I don’t think this would be much of a problem. What do you think?

                      For your second question, this one made my brain hurt 😀 Indeed, from Debopriyo’s share above on BAdI designing, it is said that having implementations with many unimplemented methods is poor design and not very good performance-wise. That is why I suggested, after I revised the post, for a BAdI per “userexit” approach. However, it is true that for standard BAdIs, when we implement them, we usually implement the method that we need and all the others will stay unimplemented. However, this is a problem with the new enhancement framework. If I recall correctly I had to go in and double click on every method to be able to activate everything properly.

                      So I guess that maybe the answer is yes. It might be a good idea to implement one BAdI definition per method in a standard BAdI… this would mean that you could not reuse the standard BAdI’s interface… which is not nice… very difficult decision!!

                      What do you think Nabheet?

                      Thanks 🙂

                      Bruno

                      (0) 
                      1. nabheet madan

                        Hi Bruno

                        Thanks for your comments. Just FYI we are still trying to be at least a beginner in OOPS world. Its been more than 2-3 years and i am still trying to be at least a beginner 🙂

                        One question which comes to my mind is if using this concept of filter we are able to bring flexibility why were the original BADI’s as defined by SAP are not defined in this way. What i mean to say is you see we have different type of BADI’s single use/multiple use with/without filter. Why did not SAP created all BADI’s with single implementation allowed and let each customer add the flexibilty.?

                        What do you think?

                        Nabheet

                        (0) 
                        1. DEBOPRIYO MALLICK

                          Hi Nabheet,

                          I presume we may see some changes in the later releases. SAP is evolving, the design limitations we had in the previous version may be overcome with a new design in place. If you look at the BADI’s BADI_SD* ( Suhas’s reference ) , you will see SAP has already created the template. No idea whether SAP will use that in the near future ( remove tick from internal use checkbox ) .

                          Just went through Dr. Herst Koller’s notes on SP7.4 . SAP is trying to phase out lot of things .

                          Don’t know whether this will be phased out ( chances are less, because lot of companies customized business processes are coded in those user exits ).

                          Interfaces with dynamic polymorphism, gives you lot of flexibility and makes the software more scalable.

                          Regards,

                          DPM

                          (0) 
                  2. Nishant Gupta

                    Hi Bruno,

                    Here, I am talking about BADI’s where “Multiple Use” is checked and Filter is not available as per SAP definition.

                    Of Course, there is no harm in creating custom BADI’s, but in this case we are actually not making use of “Multiple Use” checkbox. So, we are not bothered if its “Single or Multiple Use”. We are just focusing to attach a filter to it via custom definition, so that we can make appropriate calls.  Isn’t it ? I am really not able to conclude if this is the best approach at least as of now 🙂 .

                    Regards

                    Nishant

                    (0) 
                    1. Bruno Esperança Post author

                      That is correct Nishant,

                      Regardless of weather a standard BAdI is multiple-use or not, I would create a custom BAdI for it and only implement the standard one once. Like I just said to Nabheet, and like you said also, this allows you to have the filters you see fit on it, and I don’t see disadvantages on this. However, this should be well documented and enforced throughout your development team, because if people start mixing up the methodology, it would become a big mess 🙂

                      Best,

                      Bruno

                      (0) 
                      1. Nishant Gupta

                        Hi again Bruno,

                        I would like to differ here, bcoz what I feel its a kind of re-inventing a wheel if you start defining your own BADI’s for implementing any SAP filterless BADI. What about factory pattern which you explain in earlier blog. I think that will fit more here in this case, Isn’t it ? We will get rid off issues like how to define custom BADI’s, like one BADI per method etc. What do you think ?

                        Regards

                        Nishant

                        (0) 
                        1. Bruno Esperança Post author

                          Hi Nishant (and also Nabheet),

                          I totally understand why you would want to differ here. A BAdI inside a BAdI only to implement a filter does seem excessive. I guess this will depend mostly on your “reality”. In my case, the same system is shared with different regions of the world, with one developer team per region. Each region has their own client. This is why it’s so important to me to have this filter, because sometimes there are runtime errors from objects that are developed for other regions, and these objects are tested for that region only. When they reach production, sometimes, they have a bad impact on the rest of the “world”. If I can have BAdIs with filters that are only executed on their respective client, this would never happen again.

                          You’re also right when you say the factory strategy pattern would more or less solve this problem. But the problem with this approach, in my case, is that it would be harder for me to “sell” this idea, training would most probably be necessary, and I’m pretty sure people would still reject this idea and code the user-exits as they saw fit 😛

                          I’m gonna try and implement a BAdI inside a BAdI today to see if it would mean a lot of extra work. I don’t think it would. As shown above, defining, implementing BAdIs, once you know what you’re doing, is easy, and besides, this is an extra work that would only have to be done ONCE, so when you’re talking about several dozens of requirements/implementations, having one extra one doesn’t sound like a big deal, right? 🙂

                          Cheers!

                          Bruno

                          (0) 
                          1. Bruno Esperança Post author

                            Hi again,

                            Now that I got out of bed (I took the day off today 😛 ) I logged in the system and tried to implement this design we are talking about. I will admit, it’s a lot of hardwork. Worth it? I don’t know, I think so 🙂

                            Each standard BAdI will have one implementation and one implementation alone. From this implementation, you click one method, and you get the custom BAdI call for the method alone. Good readability? Yes, I think so!

                            Also, when looking at the already existing implementations, if they’re not well documented or explicit, I find myself clicking into every method to see what’s implemented and what’s not. Has this happened to you as well? With this design, this would not happen any more. I also think this is good.

                            The extra effort should be no more than 20~30 minutes.

                            Go ahead and try it when you have the time and let me know 🙂

                            If you would like a step-by-step example just say so!

                            Cheers,

                            Bruno

                            (0) 
  2. Suhas Saha

    Hello Bruno,

    Now you can see the use-case & the power of OO 🙂 Let me highlight that the BAdI architecture draws its parallel from the “Strategy” pattern.

    Similar approach was discussed by Sougata Chatterjee in his blog Simplify & structure your Enhancements by using Switchable Kernel BAdIs. In fact i have implemented one in my current project as well.

    Did you face this situation that you cannot define a BAdI as “multiple-use” if it had an interface-method with EXPORTING/RETURNING parameters?

    BR,

    Suhas

    (0) 
    1. Bruno Esperança Post author

      Hi Suhas!

      Hey I never “dissed” about OO 🙂 I simply was looking for an example which would present to me clearly how one could benefit from OO’s features and potential in ABAP, which was what Matthew Billingham did when he shared that blog post regarding BEx variables. And hopefully this user-exit implementation example is also a good example, even though it’s more from the BAdI than from OO.

      Thanks so much for sharing that blog post. Great information about how to integrate the BAdI framework with the switch framework. I’ll look into it and will try to implement it in my application.

      Regarding the “multiple-use” switch. Yes I think it is logically. In case you haven’t grasped the concept yet, let me try and explain it. Let’s say you have one BAdI responsible for the determination of a product price. You are expecting one product price and one product price alone! Therefore, the multiple-use switch should be off, and you can use “returning” in your BAdI. You can have more than one implementation for the BAdI, but you have to make sure only one implementation will be executed by proper usage of the filters, otherwise you will have a runtime exception. On the other hand, you can have BAdI to check values when saving a sales order for example. This is a good example of a multiple-use BAdI, and you can implement as many “checks” as you want.

      In between, you have for example form move_field_to_vbak. This could be an example of a multiple-use BAdI, but you have to be careful that you will not have two implementations of the BAdI being executed for the same field in vbak, this will lead to inconsistencies, since you cannot guarantee the order by which the BAdIs will be executed.

      Hopefully I made it clearer (if it was not clear for you already).

      Best,

      Bruno

      (0) 
      1. Suhas Saha

        Hello Bruno,

        Thanks for explaining this in detail.

        I had figured out the logical reason (and had it confirmed here – Multiple Use (SAP Library – Enhancement Framework)) why multiple-use BAdIs are not allowed to have RETURNING/EXPORTING 😛

        Did you face this situation that you cannot define a BAdI as “multiple-use” if it had an interface-method with EXPORTING/RETURNING parameters?

        This was more of a tip-off so that you add this in the blog text 😉 Not many will think about it unless they actually face it.

        BR,

        Suhas

        (0) 
  3. Bruno Esperança Post author

    Guys,

    I have revised the blog post!

    Kindly take a look at it and let me know what you think! Personally, I would be happy to implement this 🙂

    Best,

    Bruno

    (0) 
  4. Sougata Chatterjee

    Bruno Esperanca wrote:


    As you should already know, there is no guarantee to which BAdI runs first, so make sure one implementation does not rely on a result from another implementation, and also try not to change the same fields, because only one value will prevail, and you have no idea which one.

    Hi Bruno,

    FYI that is not entirely correct – there is another sorter BAdI (BADI_SORTER) which you could implement to control the sequence of the BAdI implementations that you have done i.e. to call/sort them exactly in the order you want. Note that this only works for Kernel based BAdIs which are assigned to an Enhancement Spot.

    Cheers,

    Sougata.

    (0) 
    1. Bruno Esperança Post author

      Hi Sougata,

      First of all, thanks for taking the time to read this blog post! You are obviously very knowledgeable on BAdI’s, so I don’t think you learned anything from it, but I hope you found it enjoyable to read at least 🙂

      Thanks so much for pointing that out. I had NO IDEA that a “BAdI sorter” existed. Thanks, I will update the post accordingly!

      Would you think it would be helpful for this kind of situation? In my opinion, I think the added complexity would compromise the design, and the benefits are arguable. I can see where it could be useful if we wanted a “global” requirement executed first, and then specific requirements overriding the results from this global implementation, however I think from the moment a requirement is specific it cannot coexist with global implementations and each “region” will have to decide whether to implement it or not. In my opinion this is easier to maintain and understand than a BAdI sorter.

      What do you think?

      Thanks!

      Best,

      Bruno

      (0) 
      1. Bruno Esperança Post author

        Hi again,

        Post revised to mention the BAdI sorter and the possibility to define the order on which BAdI implementations get executed.

        Thanks!

        Best,

        Bruno

        (0) 
    1. Bruno Esperança Post author

      I’m glad you liked it, thanks.

      As far as I know, the only way to sort BAdI’s is using the BAdI sorter, but in my opinion, if you have developments which are dependent of each other, I would put this in the same BAdI implementation.

      I haven’t had a real world case for it though, so I haven’t compared both situations to be able to say with a good degree of confidence which way is better, but for simplicity sake, I would avoid putting two dependent developments in two separate BAdI implementations, and worry about the order.

      Best,

      Bruno

      (0) 
      1. Eitan Rosenberg

        Hi,

        You are right of course .

        But it seems posible to sort.

        I noticed that the implementations reside in a public table .

        An this is the base for this code:

        FORM test_01 .

          DATA: ob_y_eitan_badi_01 TYPE REF TO y_eitan_badi_01 .

        * Start of “normal” BADI call .

          GET BADI ob_y_eitan_badi_01 .

          FIELD-SYMBOLS: <st_imps> LIKE LINE OF ob_y_eitan_badi_01->imps .

          DATA: it_return TYPE bapirettab .

          CALL BADI ob_y_eitan_badi_01->get_message
            CHANGING
              it_return = it_return.

          BREAK-POINT .

        * End of “normal” BADI call .

        * Start of “Sorted” BADI call .

        * The BADI interface contain a method get_sort_value that return the sorting value

        * Sorting table
          DATA: BEGIN OF st_sort .
          DATA: sort_value   TYPE syindex .
          DATA: imp TYPE REF TO y_eitan_badi_01_int .”
          DATA: END OF st_sort .

          DATA: it_sort LIKE TABLE OF st_sort .

        * Copy the implementations to the “Sorting table”
          LOOP AT ob_y_eitan_badi_01->imps ASSIGNING <st_imps> .
            st_sort-imp ?= <st_imps> .
            st_sort-imp->get_sort_value( CHANGING sort_value = st_sort-sort_value ) .
            APPEND st_sort TO it_sort .
          ENDLOOP.

        * Sorting….
          SORT it_sort BY sort_value DESCENDING .

          FIELD-SYMBOLS: <st_sort> LIKE LINE OF it_sort .

        * Clear I hope that it does not cause damage…
          CLEAR: ob_y_eitan_badi_01->imps[] , it_return .

        * Copy back…
          LOOP AT it_sort ASSIGNING <st_sort> .
            APPEND <st_sort>-imp TO ob_y_eitan_badi_01->imps .
          ENDLOOP .

          CALL BADI ob_y_eitan_badi_01->get_message
            CHANGING
              it_return = it_return.

          BREAK-POINT .

        ENDFORM .                                                   “test_01

        Regards.

        /wp-content/uploads/2014/10/screenshot_04_556416.png

        /wp-content/uploads/2014/10/screenshot_01_556417.png

        /wp-content/uploads/2014/10/screenshot_02_556466.png

        /wp-content/uploads/2014/10/screenshot_03_556467.png

        Regards.

        (0) 
        1. Bruno Esperança Post author

          Very interesting, thanks for sharing!

          Should you post that in a separate blog, I’ll point to it in mine 🙂

          Let me know if/when you do!

          Best,

          Bruno

          (0) 
  5. Jaideep Sharma

    Awesome blog and wonderful discussion around various possibilities to design a solution. Thank you Bruno and all for providing valuable inputs. 🙂

    I have recently developed a report for one country and soon there would be need to have similar report developed for all other markets. Planning to redesign existing report or create a new one and try implement this design using BADI approach suggested above having flexibility to call respective implementations of BADI based upon company code and country.key.

    (0) 

Leave a Reply