Why object oriented? – Class Attributes
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:
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.