There is a lot of discussion about why we should use object oriented programming instead of plain old procedural. I have to admit it is sometimes difficult to come up with good reasons, besides the “Try it and will find out”, so I’ll blog about the reasons as I come upon them starting with: import parameters.
Last week I wanted to reuse a custom method that creates an inventory in WM, and the definition was something like this (zwm_linv_t is at table type of LINV):
Methods Create_Inventory importing !I_Link as LINK !IT_Linv as zwm_linv_t
Why is this less then optimum design?
Side Note: Before you say, “Wait, that already uses OO ABAP”, remember that using classes doesn’t make the code object oriented. Object orientation is about design principles, not whether you use function modules or classes.
With that out of the way, why could this be improved upon?
- From the interface I get very little information about exactly what parameters are required since LINK has a lot of fields,
- I can’t use “Mandatory” keyword because it applies to the entire LINK structure;
- I have to look inside the code to know which fields to fill (which in this case were only 3: date, warehouse number and storage type).
A better design would be (ignoring LINV):
Methods Create_Inventory importing !LGNUM TYPE LGNUM !LGTYP TYPE LGTYP !DATE TYPE DATUM
Again you might say “There are no objects there, that’s not object oriented!”*. Well you could, but you would be missing the point. The main difference between procedural and pure OO is that in pure OO there are no structures, everything is a class. The fact that there no structures prevents you from doing stuff like the first example (and I’ve seen many people do that).
The main difference between structures and classes is that classes are responsible for their own consistency, while structures aren’t very smart. In a class, the public and therefore “mandatory” attributes are filled in the constructor which makes sure that, IF an object (instance of a class) exists, those attributes have a value. With structures that doesn’t happen, there’s nothing to ensure it.
Let’s make that clearer by replacing the method interface with one that uses an object with the attributes of LINK
Methods Create_Inventory importing !I_INVENTORY TYPE REF TO ZWM_INVENTORY.
When I want to create an instance of the import parameter I need to use the constructor, which will give a clear indication of the mandatory parameters (lack of polymorphism makes this trickier but…moving along). Unlike the first example I don’t need to guess, I don’t need to look into the code, I just call a method with explicit parameters, and in return I get a “bullet proof” import param.
If you ever used a BAPI and had to look in the code or debug to know exactly which fields to fill, you’ve come across the reason why structures allow very bad design, and shouldn’t be used in APIs. Saves some one time effort on the side of the programmer, by repeatedly passing it along to whoever uses the API.
*Actually in pure OO (Java, C#, Objective-C) LGNUM, LGTYP and DATUM would be classes, but let’s take it one step at a time.