As with most OO related discussion (i.eWhy object oriented? Import parameters), the arguments get interesting really quick. In that blog, a fellow SCN user described her dislike for OO, and how it relates to procedural, as the following:

The funny thing is that this aspect I dislike most about FM’s is their greatest parallel to OO concepts. Basically you can say that a function group is something similar to an object, with the FM’s being its methods. Fortunately, most of the time the FM’s are independent and provide a well-defined functionality that only depends on the parameters you are providing at run-time.

The point the user is making is that class attributes are a lot like global variables, which are more annoying to debug since it’s harder to find out where they were actually set. I really get where he is coming from. As always, it’s a matter of design and following OOP guidelines.

What you should do:

  • Public atributes should be set in the constructor;
  • Private attributes should be set in specific getter/setter methods (or the constructor).

What you shouldn’t do:

  • Change an attribute directly outside of the constructor and getter/setter methods.
  • Create attributes for temporary variables that are not related to the object itself;
  • Create attributes with obscure naming like WERKS, use Plant instead. Use _ if you have to, the attribute name should always be self descriptive.

The rule of thumb is: If the attribute is not worthy of public or a getter/setter then it is temporary method variable and shouldn’t be an attribute at all.


This explains why they aren’t so bad if used well, but doesn’t explain why you should use them. I think the most immediate way to summarize their power (in the context of SAP WM, and TO confirmation) is this:


lo_to->confirm( ).


Why is this powerful? Because import parameters are messy, and the more “the merrier” (joking). Translation, the more parameters, the more mistakes you can make and the more information you need to use them correctly.

This is the exact opposite of the FM with zero state, where all information must be provided by IMPORTING parameters. Lets picture the scenario where you need to confirm a TO (from SAP WM) without using OO attributes. SAP provides a FM for that:



    call function 'L_TO_CONFIRM'
      exporting
        i_lgnum                        = lv_lgnum
        i_tanum                        = lv_tanum
        i_squit                           = lv_squit
        i_komim                        = lv_komim
        i_tbeli                            = lv_tbeli
        i_update_task                  = 'X'
      tables
        t_ltap_conf                    = lt_ltap_conf[]
        t_ltap_conf_hu              = lt_ltap_hu[]




This is not an extreme example there are way more complicated FM interfaces. There are two main problems with this:

  • Filling lt_ltap_conf and lt_ltap_hu is far from trivial;
  • The FM call is completely coupled to the calling program (more on that in an instant).

I’ve used this function in RF programs which are a pain (if you ever touched one, you will know it…), and have persistency requirements: a warehouse worker can’t lose his work if Wi-Fi goes down, so every item picked gets saved to the database. Now let’s assume that an error is thrown at TO confirmation, and you need to find out why.

If you used the traditional procedural way, you would need to run the calling RF program, get to the place where you make the TO confirmation and debug (with the extra annoyance that RF is system-guided, so getting that specific TO means superuser specific code). Either that, or you could SE37 the FM and fill by hand all the parameters of the FM (remember the counterexample is a FM with not state).

With OO, it’s as simple as SE24, create instance, insert number of TO (and warehouse number), and then press “CONFIRM”. Two parameters and you are ready to debug. I cannot stress how important this decoupling becomes when you are debugging errors or making unit tests, this separation between caller and callee means you can focus on particular behaviors.

This is a specific situation with persistence where OO gives you a really advantage. I’ve found over the years that dealing with persistence is one of the greater advantages of OO since most of the data is already available. In a more general situation the CONFIRM call would be preceded by calls to ADD_ITEM, but even that is simpler than manually filling the lt_ltap_conf with absolutely no rules (check Why object oriented? Import parameters for my argumentation on that subject).

All this could be made using Function Groups, since this blog more about Object Oriented Programming then Classes/Methods.

To report this post you need to login first.

76 Comments

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

  1. Suhas Saha

    Hello Joao,

    What are your thoughts about public-read only attributes?

    Instead of creating a GETTER method i generally define such attributes as public-read only. Just saves me the time of creating a SETTER 🙂

    Do you use them as well?

    BR,

    Suhas

    (0) 
    1. Joao Sousa Post author

      Due to the way OO ABAP works I don’t usually define getter/setters for public attributes. If I think that he logic may be complex enough I define it as private.

      But I believe your solution is completely valid.

      (0) 
    2. Wim Verschueren

      The goal is to adhere to the principle of data encapsulation as much as possible, so indeed avoiding public attributes.

      But there are some exceptions in which I allow myself to define public attributes:

      * defining constants which are useful outside the class too

      * defining some key-attributes as public READ-ONLY:  this allows you to find easily back objects based on specific identification-attributes.  For example: you could use “READ TABLE lt_my_object … WITH KEY table_line-><my_public_read_only_attribute>.”  This is especially for performance reasons (in some cases it is a dramatic improvement), otherwise you need to loop over the table and call for each object the GET-method to identify if that is the object you are looking for.

      (0) 
  2. Lucas Tétreault

    I don’t think I’ve ever used a public instance attribute. Nor do I think anyone should…

    If you don’t have getter + setter methods you lose all control over what someone outside of that class can do with that variable…You also break encapsulation of the class –  the client needs to know what type it is, if there are business rules around what it can and can’t be set to, etc… And if you ever change the representation of the data for some reason and you wanted to leave the interface of the class intact you would still break any place that uses your public attribute without a getter/setter.

    If it’s a constant class attribute sure… But other than that I see no reason to ever make an attribute public.

    (0) 
    1. Joao Sousa Post author

      If you don’t have getter + setter methods you lose all control over what someone outside of that class can do with that variable…

      If that attribute has absolutely no correlation with other atributes, and the type defines it’s allowed values (like in a date), I don’t see a problem. But yes, the usage is very limited.

      (0) 
      1. Lucas Tétreault

        If it has absolutely no correlation with other attributes or methods in the class then why is it in that class?

        Even for a date I would say no… If you want the clients of the class to use a straight up date format: YYYY-MM-DD but you need to persist it at the DB level as a timestamp then how do you facilitate that if you are using a public attribute to provide access to it? Even if you are showing your clients YYYY-MM-DD and persisting YYYY-MM-DD if you expose the inner workings of the class to the client by letting them use the class attribute directly then you create problems for yourself if you ever need to change how it is persisted.

        (0) 
        1. Joao Sousa Post author

          If it has absolutely no correlation with other attributes or methods in the class then why is it in that class?

          Because it belongs to the object. For example, a PO Reference in a Sales Order. Belongs to the sales order, has zero correlation to any other field, and is freely manipulable.

          (0) 
    2. Suhas Saha

      I don’t think I’ve ever used a public instance attribute. Nor do I think anyone should…

      I generally don’t program a class to such extremes, but for me it is generally a mix of private & public read-only attributes 🙂

      Seldom do i allow a client to manipulate of the attributes of my class.

      (0) 
      1. Lucas Tétreault

        I wouldn’t call it extreme at all… It takes seconds to create getters/setters and clients of the class probably don’t care if they have to use getters/setters vs. direct access. For the added flexibility… Why wouldn’t you use getters/setters for everything?

        When writing Java code in Eclipse it actually gives you a warning if you have public attributes accessed outside of the class and offers to create getters/setters and refactor the places where the public attribute was used.

        (0) 
        1. Suhas Saha

          Hello Lucas,

          If you read my comment i had said that i seldom allow a client to manipulate attributes of my class.

          I said “extreme” because of the number of setters/getters which need to be defined. Instead of defining getter methods i use public “read-only” attributes.

          BR,

          Suhas

          (0) 
        2. Joao Sousa Post author

          It takes seconds to create getters/setters

          In OO ABAP? How? I actually find it quite time consuming, maybe there is something in AiE I haven’t used.

          (0) 
          1. Lucas Tétreault

            We haven’t upgraded in a while so I can’t even use Eclipse… it’s even easier in eclipse.. But here’s how to do it in a couple seconds in SAP GUI:

            1. Try to use a method that doesn’t exist. try to use a method that doesn't exist.PNG

            2. Double click on the method name:

            double click method name.PNG

            3. Select yes and define your method:

            define your method.PNG

            define your method2.PNG

            4. Fill in the implementation:

            fill in the implementation.PNG

            Done.

            (0) 
            1. Jeffrey Vander Graaf

              Lucas, you’re bang on with what you are saying about encapsulation. Thank you for making that point.

              I would like to ask your opinion on public READ-ONLY variables. My mentor and I were discussing the use of these. I advocate for using getter and setter and not making direct references to the read only variable. I believe directly referencing these, breaks encapsulation, breaks consistency and can hurt modularity. He believes that if it is made public read-only only consistency and potentially modularity are violated. Your thoughts?

              (0) 
              1. Jens Petersen

                I am not Lucas, but I believe making such a distinction and introducing additional overhead by creating such single-line methods is petty. A public attribute that deserves the name ❗ is one whose semantics is clearly defined and should never change. As such it should not be direct part of the internal computations of the method (which may be subject to future changes). In doubt you can always have a private variable holding your results which you then copy into the public attribute. By doing so, you consider the latter as what it is: part of the interface.

                Often enough, not even that should be necessary. If the purpose of your method fetches, say, the name of a material number, then that material number itself may well be a public attribute, seeing that it belongs to the very basis of the functionality. A change of logics concerning the material number in such a method would defeat the whole method; it would cause the method to serve a totally different purpose, effectively being a different method. However, changing a method into a totally different method with a different purpose obviously does not allow for stability in any respect.

                Unless, of course, you only keep those interface variables for downward compatibility and fill them with meaningless default values (you cannot fill them with the expected values if your method has completely changed its purpose, thus stopping to provide those). But under those circumstances I consider it infinitely better to leave the method as it is, stopping to use it if its purpose no longer fits into your concepts, and making a new method for your new needs rather than abusing the old one for that purpose.

                (0) 
                1. Joao Sousa Post author

                  A public attribute that deserves the name ❗ is one whose semantics is clearly defined and should never change.

                  Until they do. I use public read-only for key values like material number which is intrinsic to the object and a key.

                  As a rule public read-only must be handled in the construtor, because otherwise you have no way of making sure the access is correct. If you put too much in the construtor, things you may never use, it will weight on the performance.

                  (0) 
                  1. Jens Petersen

                    Until they do.

                    If they do, you messed up in the first place, IMHO. Any such attribute should be well-defined enough never to “accidentally” change (except in case of a bug, which is outside our scope here). If you need a different value to be exported, leave the attribute as it is and introduce an additional one. If the change is even bigger than that, make a new class.

                    As a rule public read-only must be handled in the construtor, because otherwise you have no way of making sure the access is correct.

                    Not necessarily, at least not in the sense that it requires any action in the constructor. For instance, if your class is “parking ground” and you have a public integer attribute “# of occupied parking slots”, then upon creating a new instance the number will default to 0, which is correct.

                    If you put too much in the construtor, things you may never use, it will weight on the performance.

                    True if obtaining the information for those attributes requires serious computations. For those, methods are the approach of choice anyway, but I do no think you would label such a method a “Get” method.

                    For public attributes, I am thinking more of trivial (yet necessary) information, which is easy to calculate, like the # of available parking slots. A single initialization line in the constructor like

                    total_parking_slots = 25

                    is so negligible performance-wise that it will hardly ever matter. The effort for creating an instance is far higher than such an assignment, so if you have a performance problem, it originates from elsewhere.

                    (0) 
  3. Eng Swee Yeoh

    Hi Joao

    I would like to understand the reasoning behind the two following points you mentioned above.

    What you shouldn’t do:

    • Change an attribute outside of the constructor and getter/setter methods.

    The rule of thumb is: If the attribute is not worthy of public or a getter/setter then it is temporary method variable and shouldn’t be an attribute at all.

    From what I understand from these points, you are saying that a private attribute of the class should not be changed by other methods of the class apart from constructor or setter.

    Since the attribute is private to the class, the class should have the freedom to change it if necessary. Otherwise, that would mean any changes to that particular value needs to be pre-calculated by the client of the class and passed into the class via the corresponding setter. That would not seem very flexible at all and also introduces tight coupling between the class and its client (the value of a private attribute is dependent on the logic of the client.)

    Hope to get some clarification from you on this.

    Rgds

    Eng Swee

    (0) 
    1. Joao Sousa Post author

      From what I understand from these points, you are saying that a private attribute of the class should not be changed by other methods of the class apart from constructor or setter.

      Yes that what I’m saying, because it makes the class logic much more legible. You don’t have to look at all the methods to find where that variable is changed, and this logic is very useful for lazy loading. I’m not saying however that another class method can’t call the setter/getter.

      Let’s say I create a new delivery object, and want to leave the sales_order attribute initial for  lazy loading. If the attribute is only manipulated via getter I can make sure, even inside the class, that it is correctly initialized. If I directly check the attribute without the getter, I lose the lazy loading functionality (or I have to keep reimplementing it everywhere, which is bad coding).

      Since the attribute is private to the class, the class should have the freedom to change it if necessary.

      Yes, via setter. I’m not saying the value needs to be changed by the client, I’m saying that the class itself should also use the setter/getter internally.

      (0) 
      1. David Encinas Fernandez

        This is something I like doing in my code but unfortunately not every developer likes because of the additional effort.

        IMHO, not following this approach means having the same headache as with global variables in routines/FM where you have to pay attention where to put your code because you don’t know if the variable is already initialized or not.

        (0) 
  4. Yuvaraj Shanmugam

    Hello Joao,

    I cannot agree more about debugging and getting the state of an entire class by giving just the key ( like Sales order or TO) in SE24 and see all its data and operations that we could do on its data just seconds away, ready to debug.

    When I realized this feature, it was a total bliss and assurance that I am doing the design in right way.

    But I am not really sure about naming attributes as ‘Plant’ and not ‘WERKS’. Every class developed in SAP is and will be used by developers in SAP. It is not going to serve any API functionality as it is only possible by remote enabled FMs. Since the user of the class that I creat is going to be a person who understands what a ‘WERKS’ is, then I think there is no problem in naming it so. (We have a short description anyway to explain a bit about the role of the attribute). Naming it like how its named in the database table will serve the purpose of understanding from where exactly the attribute is fetched from.

    Cheers,

    Yuvaraj S

    (0) 
    1. Suhas Saha

      Hi Yuvaraj,

      I don’t agree with your rational behind naming variables/attributes.

      For e.g., you have to use a class where an attribute is named as RANL. Do you recognize what data does this attribute hold? I guess the answer would be NO. But if the same attribute is named as LOAN_NUMBER, it makes more sense to you doesn’t it?

      You must remember that the class may not provide an external API but it can be used by different clients. So it’s very important that the names of attributes, constants, methods should be as descriptive as possible. Make use of every character allowed in the name.

      I always try to name the element as close to the “Default component name” as possible.

      /wp-content/uploads/2014/08/2014_08_19_094807_522812.jpg

      (0) 
        1. Suhas Saha

          WERK is the German word for plant, if you wonder -> it’s not an “obscure” naming 😉

          Now that i’m learning German and working with German colleagues, most of the table/field/data element names have suddenly started to make so much sense. For e.g., I no longer have to remember if Haben is the credit indicator 😛

          (0) 
    2. Joao Sousa Post author

      But I am not really sure about naming attributes as ‘Plant’ and not ‘WERKS’. Every class developed in SAP is and will be used by developers in SAP.

      Developers who have worked in SAP for more then a few years will know what WERKS means, but it’s not true for people who are having first contact with SAP, or have worked mostly in other modules like HR (which has little connection to Logistics).

      It probably comes to another rule which I didn’t write in the blog because it would be rather controversial, but as I rule I make all the naming in english. It’s not my native language either, but I have found that it’s the easiest and the most ubiquitous.

      PS: Yes, I know Mandarin is mostly widely spoken, but it’s very concentrated in China and the chinese. English is much more widely spread (besides being easier to learn, it’s a very simple language).

      EDIT: And actually the data element WERKS is not the plant, it’s a structure. WERKS_D is the correct one for the plant. Surprise! 🙂

      (0) 
  5. Fred Verheul

    I will might comment more extensively later, but happened to read (part of) this paper from 2004 about Mock Objects today, where in paragraph 4.2 it’s said: don’t use getters (let alone setters): you’re exposing implementation details to the outside world!

    After already a lot of discussion about attributes and getters/setters: what do people think of this advice? 🙂

    (0) 
    1. Joao Sousa Post author

      Well after reading that example I don’t know if I quite agree (and I’m assuming they mean we can use private getter/setters, since I’ve made my argumentation in this post why they are important). Basically their argument is, as far as I can understand it that:

      lv_xblnr = lo_delivery->get_sales_order( )->po_reference.

      should be written as

      lv_xblnr = lo_delivery->get_reference_for_sales_order( ).

      If I understood correctly, although I see how this can be appealing for an outside client, it decreases reusability, since I can’t access the methods of the sales order directly. Maybe I didn’t understand it correctly, if anyone wants to jump in….. 🙂

      (0) 
      1. Fred Verheul

        Hi Joao,

        That’s not what’s meant IMHO. But I have to admit, the article doesn’t really explain it (it’s also not the core topic of the article). I think you’ll find this one easier to ‘get’ 🙂 .

        I was (once again) in a hurry when I really shouldn’t…

        (0) 
        1. Uwe Fetzer

          Hi Fred,

          Summary of the document:

          Don’t ask for the information you need to do the work; ask the object that has the information to do the work for you.

          Good one. We always have to think about the reason, why we need the data from the object. Do we really need the data? Fine, use a getter (I’ve got no problems with it).

          (0) 
        2. Jānis B

          In the context of ABAP and Data Dictionary, I find the argument from the risk of possible data type incompatibilities in the case of changes fairly unconvincing. Yes, those can and therefore will happen on occasion – but they can arise only from pre-existing incorrect/sloppy use of physically matching but logically mismached types in the first place, isn’t it..?

          Given that the DDIC possibilities are there, I’d question the choice of not using it for type definitions. In the rare case one must drastically change the (accessor) interface by replacing an entire (DDIC) type with a completely different one (rather than changing the type definition itself) – well it is your responsibility the to make sure you are adjusting the users who were relying on the old method interface…

          cheers

          Janis

          (0) 
  6. Jens Petersen

    I fail to see how obeying OOP principles fixes the basic problem that you described. To point this problem out even a little clearer: The object is a black box whose interior you do not know (unless you invest the time and energy to analyze it in all details, which is exactly what you are supposed not to do with regard to OO philosophy and the encapsulation concept).

    OO programmers claim that this black-box-feature is good because they know what the object is supposed to do and need not care how it does it (“yes we can”). I claim that in fact they do not know exactly what the object is supposed to do (“no you can’t!”) unless they were the ones who programmed said object. The same goes for a FM. The difference is that the behavior of an FM is not that hard to debug. Objects, however, contain a lot of internal values (private attributes) that have somehow been set before the code piece in question is calling the object. So when you start debugging a program at any given point, unless you know both the detailed supposed behavior of the object and the exact history of the current program run, up to that place in the code so you know how all objects have been initialized and which values have been hidden inside their private attribututes, you have no means to tell how that object will behave and how one of its methods will react to being called with a defined set of parameter values.

    What you should do:

    • Public atributes should be set in the constructor;
    • Private attributes should be set in specific getter/setter methods (or the constructor).

    Setting private attributes by means of a method means hiding valuable information inside the object that will afterwards no longer be visible from the outside, but influence the behavior of said object, so that it becomes practically impossible to predict its behavior in the further course of the program run. In procedural programming, you can always check the state of all variables to see where you are, and why which command behaves the way it does. In OO programming program behavior is unpredictable because the information you need to predict or understand it is hidden in a private object enclosement. The crazy thing is that this is supposed to make the program easier to debug.

    What you shouldn’t do:

    • Change an attribute directly outside of the constructor and getter/setter methods.
    • Create attributes for temporary variables that are not related to the object itself;
    • Create attributes with obscure naming like WERKS, use Plant instead.

    You need to keep in mind who is supposed to be able to understand your naming. Not end users should be able to interpret your variable/attribute names, programmers should. IMHO there is hardly anything more understandable to a programmer than the typical 5-character-name of standard SAP table fields. At least in HCM, WERKS, for instance, is not a plant (even though the German word “Werk” may suggest that). Instead, WERKS is the personnel area (as in PA0001-WERKS). Chances are that in other modules, WERKS stands for a plant or something else, but the module of a program should hopefully be clear from context and familiar to any programmer being active in that module.

    As a programmer, you are working with the standard SAP table field names all the time and usually know their meaning by heart. IMHO there is hardly anything more confusing than a programmer who thinks that he needs to rename these to make them better readable for end-users that will never read the code, whilst at the same time obscuring the exact SAP table field the attribute is referring to.

    I think the most immediate way to summarize their power (in the context of SAP WM, and TO confirmation)

    Unfortunately, this is the point where you are losing me for good, seeing that my SAP WM knowledge is zero. Afaik SAP WM is not that common a module anyway, so I reckon that most ABAP programmers will be just as unfamiliar with it as I am. Since your whole example and subsequent lreasoning is closely SAP WM-related, I feel completely unable to understand what you are doing there.


    IMHO general ABAP examples should be located somewhere in SD, MM, or a common part of FI. As far as I am concerned, HCM would also be great. But WM? Sorry, but before googling it I did not even know what the abbreviation stands for.


    Same goes for “RF” btw, only that googling did not help me in that case either.


    With OO, it’s as simple as SE24, create instance, insert number of TO (and warehouse number), and then press “CONFIRM”.

    Only that you are sticking to the false axiom that you know the purpose and exact intended behavior of that object up front so you know what you look for. Since in reality, when working with code that is not yours you don’t, you are completely lost how to fill the import parameters before pressing “CONFIRM”, what to expect when you do, and how to interpret the outcome after you have done so. In order to achieve that, you will have to shed your encapsulation, dive into the object and its implementation, curse about the numerous other objects it works with, seeing that you know purpose and functionality of none of them, and be a whole lot more lost than you would be with procedural code, which is not always easy to debug either, but where the content of variables is the very bottom on which you can always start.

    (0) 
    1. Joao Sousa Post author

      OO programmers claim that this black-box-feature is good because they know what the object is supposed to do and need not care how it does it (“yes we can”). I claim that in fact they do not know exactly what the object is supposed to do (“no you can’t!”) unless they were the ones who programmed said object.

      This is the same discussion we had in another blog. All I can say is that I and thousands of developers use the Cocoa and Android API all the time and have no problem using it. And I’m sure they don’t know the internal workings, nor have programmed the objects.

      But WM? Sorry, but before googling it I did not even know what the abbreviation stands for.

      Well, now you know. I have to say I assumed people who work with SAP knew about warehouse management.

      Since in reality, when working with code that is not yours you don’t, you are completely lost how to fill the import parameters before pressing “CONFIRM”

      Again, all I can say is that I disagree, and my disagreement is supported by the fact that many thousand people use OO APIs everyday to develop your mobile apps.

      (0) 
    2. Uwe Fetzer

      Just a short explaination:

      • TO = Transport order (transport a pallet from one place to another. If you CONFIRM a TO, the goods are at the destination place)
      • RF transaction = Radio Frequency (Transactions for portable devices, Scanner)

      And why do you always tell us that you can’t debug classes / private attributes? Sure you can:

      CLASS lcl_app DEFINITION.

        PUBLIC SECTION.

          METHODS main.

        PRIVATE SECTION.

          DATA test TYPE boolean.

      ENDCLASS.

      data(go_app) = NEW lcl_app( ).

      go_app->main( ).

      BREAK-POINT.

      CLASS lcl_app IMPLEMENTATION.

        METHOD main.

          me->test = abap_true.

        ENDMETHOD.

      ENDCLASS.

      If you start the program, you can see the private attribute:

      oo.PNG

      And at last: unfortunatelly (?) it doesn’t matter if you/we like it or not, SAP is doing it everywhere now and you/we have to work with it. I think we can stop this discussion here because we will not getting any further.

      (0) 
      1. Jens Petersen

        The latter is not really true. If we had to abolish old concepts just because SAP declares them obsolete, then SAPScript would have stopped working many years ago. There are things so widespread that SAP has a hard time getting rid of them, and procedural ABAP is too widespread for SAP to stop supporting it anytime soon. Of course that says nothing about advantages and disadvantages; I am just saying that procedural ABAP will keep working for a very long time, so right now we still do have a choice.

        Making a statement and then declaring “Now that I have hereby had the last word, we can end the discussion.” is a very poor arguing style anyway, because nobody should assign himself the last word. But I agree that there is little point in having the discussion going in circles, so let me add some new aspects to it.

        While I have basically understood the syntax of ABAP OO, I have always had difficulties understanding how to use it for real applications. IMHO, ABAP OO apologists keep making the following mistakes when explaining their stuff to procedural programmers:

        • When trying to give real-life examples, OO apologists only provide small code fragments, believing that doing so they prove how efficient OO is, whilst in reality giving a useless example because someone not having a lot of practice in OO will have no chance to see how the complete program would have to look like (see this thread for examples for this). IMHO it would at least sometimes be necessary to provide small but complete programs that could be used productively as they are and still show the advantages of OO. TBH I have yet to see a single one. ABAP OO apologists keep complaining that other programmers abuse OO commands by using them without adhering to OO programming guidelines, but they fail ever to give complete, good examples of their own. If possible it would be advisable to provide an example that could not be transcribed into well-readable procedural code with only 50% of code lines *duck* 😉 .
        • Giving removed-from-reality examples. In pretty much all documents that explain the use of ABAP OO, including ABAP OO teaching books and videos, sample programs use a car or airplane as object, things like the brand as attributes and methods like “accelerate” and “brake”. I can understand 100% of such a text and corresponding code and still fail to see how I could possibly employ objects in my own SAP programs, seeing that in SAP I try to do things like generate and display data lists, not modify abstract “vehicle objects”. For instance, how do I write a simple report that selects employees (or materials if you feel more at home in SD/MM), reads information about them from a couple database tables and then displays them in an ALV in good OO?

        Eventually I have found one video that explains that objects in OO are supposed to replace what internal tables do in procedural programming. So rather than creating a table of, say, employees with their required data in additional table columns, you create a data reference per employee and then a table of data references to manage them. That does make some sense to me, but leaves the following questions open:

        • Declaring an object for the employees complete with what methods you will need will result in a considerably longer code than simply creating an internal table for the same purpose. (Shortening the code by doing part of the declarations in DDIC will not lessen the effort to do so, rather the contrary.) IMHO there is nothing both shorter and easier to understand than a simple DATA command with the heretical OCCURS addition (making it unnecessary to even use the clumsy TYPES command which does have its uses but is IMHO massive overkill in a simple report) and then listing all the fields you will need, filling them in one or a few SELECTS, and then outputting them. Note that “shorter” also means “faster to implement, costing less expensive consultant man days”.
        • Assuming you have your complete table of references to employee objects, how do you output that as an ALV? Assuming a report output (i.e. no manual dynpro container) I understand that there are two flavours of ALVs between which you can choose: SLIS-based and LVC-based. SLIS is usually easier and shorter to use, but has a reduced feature set (and probably counts as obsolete today). LVC has a more object-oriented flavor as far as I can see. However, as far as I know, even LVC-based ALVs expect you to pass a table with the data to be output to them. I do not think the standard SAP ALV output FMs (are there also methods?) will accept a table of object references?

        Assuming that I am not missing something, you would have to convert your precious object-table that you just assembled with great effort back into a simple procedural -style table that contains the actual data in its columns so you can pass them to the ALV output. How much sense does that make?

        (0) 
          1. Jens Petersen

            Thank you, nice try. But the code you linked to is just a tutorial how to properly feed the methods of the class CL_SALV_TABLE so that you get your content onto the screen. In other words, it explains that class and its usage. It says nothing about your own code that leads to the data that you want to output.

            In fact, this example you provided proves every single of my assumptions:

            • The code that reads the data prior to feeding it to CL_SALV_TABLE is purely procedural. It has a simple ABAP table with the actual data in its columns (i.e. no objects for the flights), it fills the table with a simple select, then passes it to the class.
            • The class CL_SALV_TABLE is most obviously unable to output any data that comes in objects. The data that is to be output in the ALV has to be supplied in the columns of a simple internal table in which every procedural programmer would store it in the first place. In a true OO program, however, I take it that you would not be having such a table. You would be having a bunch of “Flight” objects containing data that its methods read from table SPFLI. In order to actually output them, however, you would have to implement another method that reverse-transforms them into a simple data table as usual in procedural programming.
            (0) 
            1. Uwe Fetzer

              The example is the framework itself and how to use it. Every parts of the framework are objects. You can learn how to proper use attributes, methods (incl. setter/getter) and events.

              Sorry I’m out now.

              (0) 
              1. Jens Petersen

                The framework is not a program, more like an API, and it certainly is no simple example for how to write good OO programs. End-user developers will typically develop programs that work with company data, not code GUI functionality.

                (0) 
        1. Jacques Nomssi

          Hello Jens,

          let us first agree on the design principle divide and rule: we master complexity in software by dividing the system in parts with high cohesion and low coupling. I will argue that OO helps to achieve low coupling.

          Object Oriented Analysis and Design (OOAD) rely on top down decomposition of the problem domain to identify and name powerful abstractions (the parts are objects). Two different views are used:


          • The top-down view of objects as black boxes implementing a protocol to communicate with other objects by message passing. The code is less a concern than the relationships between the parts, the objects.
          • The bottom-up view inside an object, where algorithmic decomposition and structured programming help us implement the protocol.

          A successful protocol must not have a lot of methods (e.g. HTTP has few methods: HEAD, GET, POST,…) but must have a stable interface. I am not a talented architect, so my objects do not always have a useful and stable public interface, but I propose this as a metric for good OO design.

          An example: presuming an application should export and import data to a text file on the application or the presentation server, I invent a FILE object as an abstraction for the storage system.

          /wp-content/uploads/2014/08/file_class_527301.png

          The handling of different storage media is private to the object, the client has to master the protocol: sends either message LOAD( ) or SAVE( ), then CLOSE( ). Data and filename are passed in the constructor. I can imagine a strategy pattern implementation based on some interface implemented by subclasses. That would be 3 classes and a lot of lines of code, but I would have achieved my goal of a stable and useful interface.


          The interface would not change if I decide to add other file formats (e.g. Excel).  The code for saving to file is well contained into this one FILE abstraction and can still be enhanced.


          So the fact that a method call can always be enhanced helps to reduce coupling, but we must work hard to enforce a stable interface. The various UML diagrams help to review the pro and cons of the protocol.

          regards,

          JNN

          (0) 
        2. Jānis B

          Hi,

          Jens Petersen wrote:

          Eventually I have found one video that explains that objects in OO are supposed to replace what internal tables do in procedural programming.

          That (thank you, ABAP Fathers) couldn’t be further from truth in ABAP OO, I believe:

          Developers who have experience with object-oriented development in other programming languages should be aware of the differences between ABAP Objects and Java:

          • In Java, all superior data objects (especially container variables such as strings) are modeled using classes. By contrast, ABAP provides very powerful, predefined types. Besides the predefined ABAP strings, internal tables are also provided that are used for structured data storage. These tables represent the most powerful ABAP type. Therefore, it is generally not beneficial to implement own container types using ABAP classes.
          • Java reaches a high processing speed for methods, by using optimizations and JIT compilation. In ABAP, however, the high processing speed is primarily attained using very powerful and complex individual statements. This is another reason why implementing own container classes is usually not beneficial. Direct access to a suitable internal table, for example, is always faster than handwritten access logic in ABAP.

          Indeed, the OO “extremists” on our team, too, pushed through a concept of what they call “Business Data Object” (basically encapsulates a structure, has a bunch of accessors and is supposed to be passed around instead of structures, and can be gotten from “Business entity”) and of “List Object” (an Iterator that is a collection of BDOs, BEs and so forth that’s supposed to be passed around instead of internal tables). Just to be “extra OO”, I’d say, and even the above link was not authoritative enough to dissuade them 🙂 Looping and reading sucks; get_first( ), get_next( ), get_at_index() etc. rocks. Because OO, baby…

          We made peace once I was promised that I wont be ostracized for using internal tables in my “pretending to be somewhat OO” code and when the recognition came couple of months later that BDOs (and other objects) need to have at least GET_AS_STRUCT( ), GET_KEY( ), GET_DATA( ). Because nobody can do anything directly with BDO (much less their iterator) in, say, a Smartform (even if one manages to smuggle those OO tidbits through SF interface) and that easily getting the structures are, diplomatically speaking, quite handy, when you want to pass something into those “stone age” SAP APIs 🙂 or, say, write it to DB… I think there are by now some objects that even have public SET/FILL_FROM_STRUCT( )… I must admit , though, that the colleagues have “templated” everything and at least can come up with all their (IMO unnecessary and even counterproductive) OO container boilerplate astonishingly quickly

          I’m genuinely puzzled, though, why you do not want to accept (correct me if I have gotten wrong impression) that an ABAP class, as a form of organizing, structuring and, more importantly, maintaining the code, is superior to function groups (and form routines)… After about couple of years of trying to program OO it seems so self-evident that I find it hard coming up with arguments to try to convince someone of that… Not that I particularity believe in practicality of doing so via comments or even want to do so, but I just can’t think of anything from procedural programming I’m missing… 🙂

          I disagree vehemently about about the supposed ease of debugging unfamiliar procedural code vs the OO code. It depends much more on how well the application is architectured and how well the code is modularised, I feel –  be it procedural or OO code.

          cheers

          Jānis

          (0) 
          1. Joao Sousa Post author

            We made peace once I was promised that I wont be ostracized for using internal tables in my “pretending to be somewhat OO” code and when the recognition came couple of months later that BDOs (and other objects) need to have at least GET_AS_STRUCT( ), GET_KEY( ), GET_DATA( ).

            The problem with that approach is shown on the SET_DATA() that SAP uses on their Purchasing objects (used for example in MM BADIs).

            Since you can do anything with the structure you got on GET_DATA() it leads to some unpredictable behavior that I’ve had the misfortune of having to debug, including “almost infinite” loops (that break after 100 loops or something).

            PS: I understand you case is a bit different, they were taking it to extremes (I use internal tables when I feel they are appropriate), but for real objects the SET_DATA breaks the OO concept/design.

            (0) 
            1. Jānis B

              I try to think about it as an object that has to take external data input. Anything taking external data input must validate the input. Whether it takes the input strictly as an instance of “dumb” class having nothing but a bunch of accessors (container class encapsulating structure) or as a “naked” structure as well, is at that moment only a matter of showing some courtesy towards all the “structured” non-OO world out there, as well as implementing mapping from a structure to OO container once and only once in the system, I feel. If the structured world is out there, mapping is virtually unavoidable. Which does not mean the efforts to avoid it/keep the SET/FILL_FROM_STRUCT() private need not be made…

              (0) 
          2. Jens Petersen

            That (thank you, ABAP Fathers) couldn’t be further from truth in ABAP OO

            I see your point, but then, what is left that should be done in OO? To put it differently, what should be “objects”? Sticking with the simple – but close to real-life as opposed to purely academical considerations – example I have given before: A report that reads and outputs a list of employees (or materials). You just pointed out that the materials should not be the “objects” of this report (see your link). But then what is? What kind of OO-based coding would be superior to simply defining a table, columns being the employee or material traits to be output, then filling it with one or a few SELECTs and then passing it to FM REUSE_ALV_GRID_DISPLAY? Correct me if I am wrong, but as far as I can see introducing any form of OO-based coding here would just inflate the code with lots of lines containing all sorts of complex structures that help zero either concerning readability or functionality.

            I’m genuinely puzzled, though, why you do not want to accept (correct me if I have gotten wrong impression) that an ABAP class, as a form of organizing, structuring and, more importantly, maintaining the code, is superior to function groups (and form routines)…

            Before discussing that you would still have to explain what the “objects” are supposed to be, i.e. exactly how you plan on replacing, say, an FM with a class. Of course you could say you simply put the functionality of the FM into a method of a class, create one and only one instance of it and instead of calling the FM, you call a method of that instance, passing the same parameters both ways. But is that good OO coding? What have you won, other than a useless object reference overhead? Your method has well-defined parameters, but so does the FM. The functionality of working with multiple instances is never used or needed in this case. I fail to see the gain. However, I accept any bet that this class takes longer to implement than the equivalent FM, and creating and maintaining an instance so you can use the method is at least a little harder to read and understand than simply calling the FM that does not need any instanciation in the first place.

            FORM routines are even easier to read and understand. You have the full interface right at the place where it is called as well as at the place where it is implemented (as opposed to local methods where the interface definition is at a totally different location in the code so you need to hop back and forth just to read it). Creating a new form just means typing the PERFORM where you need it and then doubleclicking the name you invented. SAP does the rest on automatic and only asks you for the desired include. For a local method, you need to add code at two different places in the program. For a global method, you even need to call another transaction in a different window and add the method traits in various tabs. All of this is far more time-consuming while I fail to see the gain. You can use tools like Eclipse to make this work easier for you, bu it is stil lwork that does not arise in the first place in procedural programming.

            Of course we need to keep in mind where FORMs are called for and where not. They should be used for local subroutines only. I am a strong opposer of subroutine pools (or generally calling FORMs from other programs). FORMs also allow you to use global variables or to not properly define your interface where methods force you to specify exact data types. But nobody forces you to use FORMs sloppily: you are free to specify your parameter data types in FORMS just as precisely. FORMS are leaner, quicker to code, and do the job. Methods do the same job, but require more coding at several ends of the code.

            As for subroutines that are supposed to be called from other programs, FORMs are the wrong choice. I agree on that. FMs fill that role nicely though. In fact there is hardly any difference between a FM and a method, other than the fact that the method works on instances. And so far in this discussion, nobody has been able to tell me what typical objects in real-life programs (such as the sample report I mentioned) should be. One thing is sure: A class that is supposed only to have one instance created and the methods of that instance which are then being used like FMs confer no advantage to real FMs. I see many OO apologists complain about other OO programmers not coding good OO code (including right here in this thread, where the claim is that not even SAP codes or teaches OO properly). But I have yet to see one of these apologists provide a complete ( ! ) easy example for such a program.

            I am still waiting for a realistic example of a good, short OO report that

            • shows any advantages of OO over its procedural equivalent
            • is not considerably longer code-wise (examples I have seen so far show +100% code lines for the same code in OO)

            I can imagine OO advantages for huge projects with ten thousands of code lines, possibly even from multiple programmers, where interfaces need to be maintained and documented very clearly and within which there are many opportunities to re-use code, the subroutines being considerably-sized programs of their own. But end-user developers rarely develop programs of that magnitude. Up to, say, 5000 code lines total I see no advantage in OO compared to well-programmed procedural coding, and I hardly ever need to code anything larger than that.

            Another aspect I would like to mention: Contrary to what OO apologists keep affirming, I believe that it is a lot harder to keep track of data types in OO code. In OO code you see a lot of CASTING constructs where the exact data type is defined at run-time and therefore not obvious when you read the code. You also see a lot of field symbols and variables with meta-data-types like REF TO DATA. While I believe these constructs can also be used in procedural code, I find myself practically never needing them, causing my code to be way easier to understand for other programmers who are not familiar with the concept I had in my head when coding it.

            (0) 
            1. Joao Sousa Post author

              Uwe has shown you that the method interface is available without going back and forth, and that you can create a method implementation just like you create a FORM, but you seem to have ignored it, and keep insisting that Forms are superior because of it.

              I can only conclude that you aren’t really interested in learning new tricks.

              (0) 
            2. Suhas Saha

              As an ABAPer i am always careful where to draw the line between using “pure-OO” v/s “OO-ABAP”.

              IMHO designing applications in OO-ABAP doesn’t mean we should shun internal tables, structures and start building our own OO alternatives (as Janis has already mentioned). But we should not overlook the advantages that OOP has to offer.

              Let me give you a “real-life” example which i encountered during the course of my current project. We had to build an API which would calculate the checksum (check-digit) for IBAN.

              SAP has provided different FMs (in Fugr. FB0P_PZV_DE)  which calculate the checksum using different procedures (viz., 00, 01, 02 etc.). If we used these FMs directly in the API then for every new procedure we wanted to support, we would have to change the API. The API would have been tightly coupled to these FMs.

              But i can easily achieve this through polymorphism. I created a factory for “checksum” object & based on the checksum procedure requested I returned the relevant instance. So the API is completely decoupled from the process of calculating the checksum.

              If i say that i have used a “Strategy” design pattern for building the “checksum” object model, i am pretty much sure most of the people here would understand what i did (another advantage of OOP). The details of the implementation are immaterial.

              Can you achieve this flexibility using FMs/Forms? If yes, then enlighten me!

              (0) 
              1. Manish Kumar

                I don’t see this FuGr in ECC system. What system are you working on?

                Doesn’t older codes achieve something like this using dynamic calls to FM names maintained in configuration table?

                (0) 
                1. Suhas Saha

                  Doesn’t older codes achieve something like this using dynamic calls to FM names maintained in configuration table?

                  BTEs being the best example of such coding practice.

                  But what if you want to change the interface of the FMs or add additional exceptions? You’ll have to change each & every FM in the framework. But if you’re using OOP you’ll have to change the signature of the method (may be abstract/interface method) at one place & you’re done!

                  Which one is easier to maintain?

                  I don’t think polymorphism can be achieved using procedural programming. (Atleast in ABAP)

                  (0) 
                  1. Manish Kumar

                    It appears if 10 methods have common interface and same change needs to be done to all methods’ signature, change would be easier if they are implementing same interface. If only some of those methods’ interface need change, something else is required, like making them implement some other interface method.

                    (0) 
            3. Joao Sousa Post author

              But I have yet to see one of these apologists provide a complete ( ! ) easy example for such a program.

              That’s why you will never understand. OO is not about small programs/reports that show data in a ALV. If you are waiting for that “proof”, you won’t find it here.  If all I’m doing is a couple of selects and a call to ALV display, I won’t bother creating objects either.

              The advantages of OO design (and MVC) are only apparent for medium to large applications where the “overhead” is compensated by superior organization, coupling dynamics, flexibility and maintainability.

              And bottomline, we don’t have to prove anything. The main purpose of this blog is to stir up curiosity, so that people will do their own research. Why should I care if you keep coding like you did 20 years ago? You’ll probably never touch Webdynpro ABAP which is OO, not to mention SAPUI5 which has weak typing and is probably incomprehensible. But that’s your problem, not mine.

              (0) 
            4. Jānis B

              Hi Jens,

              For me, as long as simple procedural report, working on a slowly growing set of data is written using proper modularisation and procedure interfaces (avoiding global data), there is no K.O. reason to employ objects. I also see no K.O. reason not to employ them either and I prefer the look and style of OO coding…

              There are IMO also lots of “small” reasons (which over the years of having to maintain and extend software do add up) to try to think about the potential reuse, separation of concerns as well as the time the report will need not remain simple anymore, and the ease of getting to that complex report. KISS is good, as long as the concern does remain simple.

              I prefer the classes for ease of seeing what is private and and what is public. To implement “instances” of some “object” using function group one would have to program an “instance manager” (internal functionality having nothing to do with the “business logic” to be implemented). That “instance manager” would be doing some arcane and convoluted  technical things like pushing the global data (context) of function group out to some “buffer”, finding and fetching the right context from the buffer, and there is no real way to keep those innards truly private… That’s completely unnecessary overhead, avoidable by employing OO. If you are familiar with Business Data Toolset (the framework underlying SAP Business Partner) you should have an idea what I’m talking about. What you meant with “object reference overhead” I’m not quite sure… I know it looks like scare tactic – but one never knows when something like object instances might be handy – couple of months down the road, couple of years, or never… 🙂

              May your concerns stay simple and cheers

              Jānis

              (0) 
              1. Suhas Saha

                If you are familiar with Business Data Toolset (the framework underlying SAP Business Partner) you should have an idea what I’m talking about.

                And the pain involved in debugging the BDT framework. For a person who’s not familiar with it, it is a real nightmare 😐

                (0) 
            5. Jens Petersen

              Uwe has shown you that the method interface is available without going back and forth

              When adding fancy Eclipse tools to your SAPGui, yes. That way you solve problems you would not be having without OO in the first place. Also remember that while a wizard technology may be able to create your initial DEFINITION and IMPLEMENTATION block automatically when you create a new local method, I doubt that any automatics will support you when you find yourself needing to modify the parameters, be it because you forget one, be it because you find yourself in need of changing the type of one. You will still find yourself hopping back and forth in the code where in a FORM you could simply have edited it in the FORM itself.

              Unfortunately (without having tried Eclipse) I have made the experience that such tools often make the GUI responsiveness slower, and I am a person that enjoys fluid working so that even an additional 0.5 seconds response time can be annoying. I am aware that other users have different priorities, like being able to do a lot with the mouse and an appealing interface optics.

              Let me give you a “real-life” example which i encountered during the course of my current project. We had to build an API which would calculate the checksum (check-digit) for IBAN.

              I see your point. However, creating an API is a very special (and IMHO rather rare) case, at least for an inhouse developer. Here reusability is most obviously of top importance, and as you pointed out, you can even benefit from polymorphism. This is a very rare and special case though.

              And to say something totally heretical: What is the real benefit of not having to alter the API code when you add a new procedure? I know the theoretical answer is that any change in the code may introduce new bugs that affect already existing procedures as well. In reality, however, when you just add another WHEN-clause to your CASE-statement of available procedures, directing to a new FM, then there will be most obviously no chance for an impact on existing functionality. The new WHEN-statement will only be processed when the new procedure is called, so any errors are limited to that case (and you will have to test your new procedure anyway). I am aware that what I am saying is a crime from the academical standpoint, but I do not see the problem in reality.

              OO is not about small programs/reports that show data in a ALV. If you are waiting for that “proof”, you won’t find it here.  If all I’m doing is a couple of selects and a call to ALV display, I won’t bother creating objects either.


              The advantages of OO design (and MVC) are only apparent for medium to large applications where the “overhead” is compensated by superior organization, coupling dynamics, flexibility and maintainability.

              Now that is an interesting and substantial statement, thank you. Our positions are converging as we speak. I can well agree to the opinion that for very large constructs that are supposed to be re-used in other programs (particularly APIs), OO provides a great encapsulation (even though I still believe that its goals could be achieved with way less confusing metadata coding than what you see in typical OO programs). But this contradicts the official SAP stance that FORMs are no longer to be used no matter what and everything should be coded in OO.


              I take it that we agree that for short and simple code (which is most code, IMHO, even one that eventually makes use of such APIs), FORMs are a faster way to reach the goal. There may be reasons when they are not the optimal choice, but I see no reason to totally disallow them for ideological reasons (which is the official SAP stance afaik and which I had the impression was also the dominant stance here up to now).


              The reason why I am conducting this discussion with you is not because I feel some mission to eradicate ABAP OO from the face of the world, but because it is the officially compulsory future without me being able to see the gain in many cases. Rather than stubbornly insisting that the old ways are the best (a notion that will quickly make you horribly outdated and useless in the IT world, no matter what the context) I chose to confront the apologists of the new technology with my concerns to see what reasons they can give and hopefully enhance my horizon. Either that, or find out that the limitations of the new ways that I see are real. As far as this discussion has taken me, it is a bit of both. Thanks to all of you for that!


              I prefer a classes for ease of seeing what is private and and what is public.

              I take it that you are talking about private and public attributes. Tbh private attributes are an OO element the existence right of which I have never understood. In my eyes, having private attributes in OO objects is just as much a crime as working with global variables because IMHO it hurts the concept of encapsulation just as much.

              The reason is that private attributes modify the object behavior without the user of the instance having any chance to predict it. IMHO an object should have a defined behavior, which depends on the parameters you pass to it and its state as described by its public attributes. When you call a method of such an object with a specified set of parameter values, you should be able to tell exactly up-front what the method will do (assuming that there is no bug and the object works as designed). However, any private attributes will break this, because they will influence the outcome without you (the caller) being able to predict it. The same is caused by global variables in function groups: They keep storing information even after your FM ends, possibly affecting the behavior of this FM (or another FM of the same function group) in the future. Such a thing makes the FM hard to understand and carries all the general disadvantages of global variables. In objects, private attributes achieve exactly the same!

              I can see the use of private attributes for performance reasons (like preloading a customizing table into memory once so that subsequent method calls are executed faster whilst yielding the same results), or for a random number generator that stores its seed in a private attribute. But beyond that, I do not think private attributes have the right to exist as they defeat all that OO claims to stand for.

              What you meant with “object reference overhead” I’m not quite sure…

              Well, you need to define a variable of TYPE REF TO your class, then fill it by creating an instance, then using it to access the method. That is obviously an overhead compared to simply calling an FM by its name. I agree that this can be somewhat circumvented by employing static methods, but use of static methods is essentially OO without objects, and then you can as well code procedurally IMHO. I believe that working with objects only makes sense when it is halfway realistic to assume there will be more than one instance of them at any given time in the future.

              Btw, can anyone explain to me the point of disallowing LIKE in OO context and in return making the TYPE keyword ambiguous (making it also have the meaning of LIKE)?

              (0) 
              1. Joao Sousa Post author

                Eclipse tools aren’t “fancy” they are the abap programming tools going forward. New functionality will come to AiE and River IDE.

                I hate JavaScript and yet I’m worried that I’m not doing enough SAPUI5. Sticking to what we like or are confortable with is a great way to become obsolete.

                (0) 
              2. Jānis B

                Hi,

                Jens Petersen wrote:

                I prefer a classes for ease of seeing what is private and and what is public.

                I take it that you are talking about private and public attributes.

                More so – the “functions” or the methods…

                The reason is that private attributes modify the object behavior without the user of the instance having any chance to predict it. IMHO an object should have a defined behavior, which depends on the parameters you pass to it and its state as described by its public attributes.

                They may modify behavior in an unpredictable fashion, but that’s a programming error then… You can’t seriously be arguing that by restricting your as user’s access to some data in itself I must necessarily have made something unpredictable or reduced the understandability of my public interface…

                Firstly, I prefer to control instantiation – via “privatizing it” and providing appropriate static CREATE_…( ) methods. I also try to keep the “state” of object as small and manageable as possible and to make even the private “state changes” as explicit as possible – over appropriate private SET_ method only (yes, more “overhead” still, and departing from SAP’s programming guidelines in that tiny-miny accessors get written). Even for setting initial state in constructor(s) (apart from instatiating private member objects obviously)… That way I have easy way of enabling the state changes for public use, should the need arrise. And private state checks often (and for flags always) happen over an explicit IS_…() method.

                Well, you need to define a variable of TYPE REF TO your class, then fill it by creating an instance, then using it to access the method. That is obviously an overhead compared to simply calling an FM by its name.

                Ok, the coding overhead… Yes, I agree, but even the brevity concerns should have been fully adressed by NEW constructor expressions/intantiation operators as well as the changes to (chained) functional method calls in 7.4 , I believe (more hope than believe, actually, because I have not had the pleasure to work on 7.4 yet 🙁 ).

                cheers

                Janis

                (0) 
                1. Joao Sousa Post author

                  Tough luck there, 7.4 is awesome. All the ABAP changes, and integrated Gateway…. It’s a pain to go back to older systems.

                  And when he says that there is extra overhead he is comparing a stateless FM, to a stateful object, and still it’s less verbose the OO way.

                  data(lo_delivery) = new ZDELIVERY( lv_vbeln ).

                  lv_items = lo_delivery->get_number_itens( ).

                  Versus

                  CALL FUNCTION ‘GET_NUMBER_ITEMS_FOR_DELIVERY’

                       EXPORTING

                            I_VBELN = lv_vbeln

                       IMPORTING

                            E_number = lv_items.

                  PS: And while the former has syntax and type compatibility checks, the latter may get you a nice dump (wrong type, or FM doesn’t exist).

                  (0) 
                  1. Suhas Saha

                    Let me spew a lil’ bit more venom, if i may, 😉

                    1. Inline data-declaration is not allowed for FMs (meh)
                    2. Parameter name is not checked until runtime (meh meh)
                    (0) 
              3. Jens Petersen

                Eclipse tools aren’t “fancy” they are the abap programming tools going forward.

                Well, basically Eclipse is a language-independent tool that has nothing to do with ABAP except that SAP supports using it with ABAP. I sincerely hope that SAP will keep providing the tools required to develop in their software in a modern fashion, meaning that you should not have to rely on such tools.

                I hate JavaScript and yet I’m worried that I’m not doing enough SAPUI5. Sticking to what we like or are confortable with is a great way to become obsolete.

                Unfortunately you are right. What does it take to develop in SAPUI5? Isn’t that some sort of cloud technology? Will it work with a a conventional 7.31 server?

                They may modify behavior in an unpredictable fashion, but that’s a programming error then…

                Well, if the private attributes never have any impact on the behavior or result of a method, then what is their purpose? As I said, I can imagine method-internal pre-buffering data for performance purposes, but hardly anything else. If it has a meaning, it has an impact. If it has no impact, there is no reason for it to be there in the first place. In that case, you could just replace it with an internal DATA command that starts fresh at every method call.

                (0) 
                1. Joao Sousa Post author

                  Well, basically Eclipse is a language-independent tool that has nothing to do with ABAP except that SAP supports using it with ABAP.

                  It is the chosen tool going forward for ABAP, and all new features will be added to it (not SE80). The part about having to rely on it, well it depends on your frame of mind, if you don’t want new Netweaver features… sure, SE80 won’t disappear.

                  Unfortunately you are right. What does it take to develop in SAPUI5? Isn’t that some sort of cloud technology?

                  It is a HTML5 based framework. Fiori apps are based on it, it is the SAP technology used to develop responsive applications. You can use Eclipse or AppBuilder (AppBuilder Tutorial – Tab Based App)

                  Well, if the private attributes never have any impact on the behavior or result of a method, then what is their purpose?

                  He didn’t say that. Anyway, you talk about buffering so you do acknowledge the advantages of state, in a critical area like performance. Most of the times I see SAP use global variables it’s because of buffering.

                  And most of the time my greatest problem is discovering where that buffered data was filled, which is a problem solved by using class setter/getters like I described in the blog.

                  (0) 
                  1. Jens Petersen

                    Well, if the private attributes never have any impact on the behavior or result of a method, then what is their purpose?

                    He didn’t say that.

                    I never claimed he did. But if he actually did not agree to it, then he would have to be of the contrary opinion: that there are some legitimate private attributes that do have an impact on the behavior or result of a method. That, however, would have the negative implications I pointed out before and pretty much defeat the core goals of OO, particularly the goal of having a well-defined interface for a clean encapsulation (seeing that these private attributes would effectively act as hidden parameters that influence the result of the method call without being part of the method signature). The outcome would be even worse than if you were using global variables: The content of global variables may have a blurry origin, but at least it can be accessed at any time in the program. Having obscure variables influencing your program that your code cannot access at all is even worse, IMHO.

                    Knowing that the following is purely academical: If I was in charge, I would remove both private and static attributes altogether (seeing that the latter are effectively global variables of classes, thus being an invitation for sloppy coding and no better than any other global variables). For buffering purposes, I would allow all flavors of the STATICS command in methods. That way methods still would have the chance to do some buffering for performance reasons, but language-wise it would be clear that this is only a part of the implementation and not a feature of the method. Variables for buffering with no relation to method outcome and behavior should not sail under the “method attribute” banner.

                    (0) 
                    1. Jānis B

                      Hi,

                      When you have put it that way, I do see your “philosophical”  and practical point and actually wholehartedly agree with part of what you are saying – the state changes affecting behaviour should be made transparent to the user. If I remember correctly, SAP suggests the use of public read only attributes. I disagree in part and prefer to try to reduce state queries to explicit IS_THIS_TRUEORFALSE( ) methods (public read-only member objects is another matter). That way I have hidden my implementation details of coming to true or false (and thereby reduced the coupling somewhat), and have the flexibility to change/extend them so long as I have not affected my public contract.

                      But lets make a clear distinction – querying the state and changing the state are two entirely different matters that need a nuanced, case by case approach. Yes, there are obvious cases of changing the state that must be publicly available – buffers must be resettable (again, obviously, using the methods and not directly on class attributes) or I as user must be able to disable the buffers (prevent object from entering certain undesirable states) entirely (I know how to implement buffering for my application, if your implementation does not fit my needs or breaks me). I as a user must IMO be able to control the SAP locks an object may set, etc. But it’s a matter of API design, being as flexible as possible and coming to an agreement… all these matters do not IMO necessitate utter rejection of parts of OO concepts and way of working.

                      cheers

                      Janis

                      (0) 
                      1. Jens Petersen

                        Well, I do not see what is wrong with public read-only attributes. I may be lacking OO practice, but I even tend to the opinion that all object attributes should be read-only for the outside world and changed only by methods of the object. However, I do not see why that should be an incentive to make those attributes private. The traits “public/private” and “full access/read only” are independent from each other and should not be confused.

                        However, while changing an attribute should require a method, I fail to understand why you postulate that reading one should require a method as well. IMHO the IS_THIS_TRUEORFALSE( ) method you suggested has no advantage over a simple public read-only attribute of boolean type. But your method will make the object harder to understand and to wield, because its current state is not completely visible by its public attributes at all times, seeing that vital information is hidden inside for no apparent reason. Simply having the boolean public attribute makes the feature obvious, saves you the hassle of coding the method, and saves the user of the object the hassle of calling the method (doing a simple IF on the public attribute of your object will make his code easier to read as well).

                        or I as user must be able to disable the buffers

                        That depends on circumstances. There are many cases in which there is not really a risk that a buffer content might become obsolete during the lifetime of an object instance. I agree the opposite can also happen. If that is a realistic case, offering a FLUSH_BUFFER method is indeed called for.

                        (0) 
                        1. Joao Sousa Post author

                          However, while changing an attribute should require a method, I fail to understand why you postulate that reading one should require a method as well.

                          Encapsulation (the true meaning). Hiding the internal implementation from the user of the class/method. I already gave an example, lazy loading. If you manipulated the attribute directly you couldn’t make sure that the attribute was loaded when you manipulated it.

                          (0) 
                        2. Jānis B

                          Jens Petersen wrote:

                          However, while changing an attribute should require a method, I fail to understand why you postulate that reading one should require a method as well. IMHO the IS_THIS_TRUEORFALSE( ) method you suggested has no advantage over a simple public read-only attribute of boolean type.

                          So I retain the freedom to change the implementation – the way I come to the true or false value. Ranging from simple renaming of the attribute to refactoring this part of state out of the class entirely and delegating keeping it to another class, for example – without breaking/having to adjust the existing uses (and obviosly with the express intent not to change the existing behavior).

                          Edit in: Perhaps it’s more illustrative if it’s not simple boolean being encapsulated (I hope I’m using the term correctly here) – is_cash_payer( ), where the conditions can be much more complex and might need to be extended many times over, say, 10 years… Or changing from boolean to, say, 4 fixed value attribute…

                          cheers

                          Janis

                          (0) 
                          1. Jens Petersen

                            Ok you provided a valid point (although a simple renaming of the attribute is not really a valid case because you could as well want to rename the method for some reason, forcing you to modify the method signature just the same. However, for both attribute and method it can be asked why such a wanton renaming should ever be necessary. I suggest we stick to your other examples, which I consider perfectly valid).

                            (0) 
                    2. Joao Sousa Post author

                      That, however, would have the negative implications I pointed out before and pretty much defeat the core goals of OO, particularly the goal of having a well-defined interface for a clean encapsulation

                      That’s not encapsulation, in fact encapsulation is almost the exact opposite. Encapsulation (object-oriented programming) – Wikipedia, the free encyclopedia

                      If I was in charge, I would remove both private and static attributes altogether (seeing that the latter are effectively global variables of classes, thus being an invitation for sloppy coding and no better than any other global variables).

                      You are basically against stateful programs. For you the number one rule that must not be broken is everything should only depend on inputs, which is basically stateless only. If you can’t understand the advantages of state in a program (which I actually showed in this blog), I won’t be the one to convert you.

                      (0) 
                      1. Jens Petersen

                        That’s not encapsulation, in fact encapsulation is almost the exact opposite.

                        You fail to realize that I was not defining encapsulation, so yes, that “was” not encapsulation. I was making a statement about how private attributes undermine the goal that is being pursued by encapsulation.

                        You are basically against stateful programs.

                        Only as long as the state is hidden from the outside world, so when you call a method, you can only pray its state is such that you will get the desired result. There is nothing wrong with meaningful program states when they are readable from the outside world in the form of public read-only attributes (and changeable by suitable methods where needed).

                        If you can’t understand the advantages of state in a program (which I actually showed in this blog)

                        TBH the example you gave was pretty poor. You compared an existing FM with a usable, but complicated interface to an OO method with an apparently easier interface (again, I am not at home in WM, and you gave so little information about that method that it is hard to tell).


                        One thing is sure:

                        lo_to->confirm( ).

                        will not do anything with a given TO unless you specify said TO somewhere earlier. Seeing that you are talking about states, I assume that you “filled” it into the object in an earlier command which you conveniently neglected to mention. Now omitting half of the necessary commands is an easy way to prove how “short” OO coding allegedly is…

                        Besides this formal mistake you made, your main point, being that this is way easier and more powerful than doing it with an FM, is not proven either. You bent circumstances towards where they serve you best by comparing an FM with complicated interface to a method (or set of methods, seeing that you need to “fill” your object up front) with probably an easier interface (that you neglected to describe). Based on your SE24-related reasoning, I take it that you just need to fill the TO number into your initialization method (probably into the constructor), and the method will then look up all the related data on its own. This can obviously done with an FM just the same, only that the one you named is older, thus requiring more detailed input. However, it would be no problem to create another FM with only the number of the TO as input parameter and have this FM look up all the required data of the TO and then call the FM L_TO_CONFIRM with it. SAP is doing this thing with nested FMs all the time.

                        Bottom line is that this is not a question of OO vs procedural; it is merely a question of “powerful routine” vs “less powerful routine”. I could as well code a powerful FM and a method that requires lots of input and then try to use that as a counterproof (which would be just as invalid).

                        Besides, FMs support stateful programming just the same, just not multiple instances of it. You could always create a function group with one FM to “load” the TO into the globals of the function group (= equivalent of private object attributes) and a parameter-less FM to confirm it. Then I could write a CONFIRM-call which is just as short and amazing as your lo_to->confirm( ). Essentially you are still passing parameters, only that you do it in a prior command.

                        The only possible advantage of OO here is the potential of supporting multiple TOs at once by means of multiple object instances. But that does not appear like a probable scenario in real programs, seeing that SAP states that you should not run internal tables with multiple object references for your documents, but instead store the relevant document data right in the columns of your table (official SAP recommendation as Jänis B pointed out before). So seeing that you are not going to have multiple TO objects in memory at once, there is no advantage in doing this OO (aside from the fact that SAP does provide the more powerful functionality in OO form than in their older FM, but that is a matter of existing code, not of programming technique).

                        (0) 
                        1. Joao Sousa Post author

                          will not do anything with a given TO unless you specify said TO somewhere earlier. Seeing that you are talking about states, I assume that you “filled” it into the object in an earlier command which you conveniently neglected to mention.

                          You’ve made several ad hominem implications before, with this one I’m out of the discussion. Learn to argue without resorting to these sorts of jabs.

                          (0) 
                          1. Jens Petersen

                            You have stated broad affirmations like

                            For you the number one rule that must not be broken

                            and now whine about the simple word “conveniently”?

                            I’m out of the discussion.

                            Farewell.

                            (0) 
    3. Shai Sinai

      Jens,
      I just wanted to add one point:

      It seems that you are consistently confusing between (theoretical) class maintenance/debugging difficulties and the ease of use of (existing) class.

      These are two different aspects…

      (0) 
  7. Suhas Saha

    Manish Kumar wrote:

    If only some of those methods’ interface need change, something else is required, like making them implement some other interface method.

    For the sake of clarity let’s use the term signature & not interface. 🙂

    If you meant that the signature of some methods need to be changed , then IMHO the framework was not designed correctly. The most important thing to remember when using polymorphism is that the classes should have an “IS-A” relation. So if the methods need to have different signatures they are not related & hence not part of the class hierarchy.

    (0) 
    1. Manish Kumar

      Right, FM has interface, method has signature. Class implements interface, but it won’t be same as FM’s interface as this interface term is used on OO context.

      (0) 
  8. Gabriel SAULESCU

    Hello Joao,

    Nice article 🙂

    It is very useful for me 🙂

    I learnt a lot from all conversations 🙂 Thank you guys 🙂

    Nice evening

    Gabriel

    (0) 
  9. Fred Verheul

    Hi,

    I’m posting this as a new comment to have more width on the page, but it’s really meant as a reply to this comment from Joao Sousa and this comment from Jens Petersen (I’m sure you guys can guess which).

    Please let’s keep the discussion civil, and not get emotionally involved. At least not too much. Many good things have been said, and there’s value in this whole discussion. I have a feeling though that we are at a saturation point, and that going on might have diminished returns.

    Specifically for you Jens: you can’t go on forever like this without starting to irritate people. Several valid arguments have been presented in favor of OO. Meanwhile you still don’t see the advantages. That’s possible and even okay of course, but I want to suggest that this might be a good moment to stop the discussion here on this blog post, and try to educate yourself on OO a little more. Even without direct relevance to your day job (in which you might indeed not see the need for much OO programming, I’ll give you that), it can still make you a better programmer if you learn more about it, practice more with it (not necessarily in ABAP), and get a feel for how things work.

    Afterwards, by all means come back to SCN, and either continue the discussion here, or write your own blog post sharing how and why it changed (or didn’t change) the way you look at programming in ABAP.

    For reference (and fun!) I also want to point you to the blog posts by Paul Hardy, who’s also been trying to get his head around OO and discovering the benefits of ABAP-OO (if there are any). Good stuff!

    But again: let’s at least keep the discussion pleasant.

    Thanks guys!

    (0) 
  10. Sara jain

    Object orientation simplifies software design to make it easier to understand, maintain, and reuse. Object Oriented Programming (OOP) represents a different way of thinking in writing software. The beauty of OOP lies in its simplicity. The expressiveness of OOP makes it easier to deliver quality software components on time.

    As solutions are designed in terms of real-world objects, it becomes much easier for programmers and business analysts to exchange ideas and information about a design that uses a common domain language. These improvements in communication help to reveal hidden requirements, identify risks, and improve the quality of software being developed. The object-oriented approach focuses on objects that represent abstract or concrete things of the real world. These objects are defined by their character and properties that are represented by their internal structure and their attributes (data). The behavior of these objects is described by methods (i.e. functionality).

    Let’s compare the procedural and object oriented programming:

    Read Morehttp://sapabapcentral.blogspot.in/p/136-sap-abap-object-orientation.html

    (0) 

Leave a Reply