Dark is the Sun ; Bright, the Sky
Dear All,
First off this is very, very, technical, so unless you are in love with the minute details of ABAP programming you might not be that interested. Luckily, lots of people have just such a love affair.
In a previous blog
I talked about how Australian SAP expert Chris Paine had asked if I could pass in an array of values as opposed to having ten input parameters.
This is very common in programming world the best example is the MESSAGE statement in ABAP where SAP have decided that four parameters are all you will ever need, and you have MSGV1 to MSGV4. As an aside I find it a daily source of hilarity that in SAP you have about six message structures, all different so you have MSGTP, MSGTYP, TYPE etc, all for the same thing. It is fairly clear that the word “REUSE” had never been heard of at SAP interanlly, at least in the past.
So, in the blog above I describe creating a ZCL_BC_PARAMETER class where using recursion I can pass in one to a million parameters, howevere many I feel like, all of different types.
That worked, all was good, but I was not happy Jan (that reference would make no sense outside Australia).
I was not happy because I had tied my PARAMETER class to my LOGGING class and they were “tightly coupled” (oh-err missus) so a change to one might mean a change to the other and you could not use the PARAMETER class on it’s own in another context. All the OO books that I read say this is a Bad Thing.
I could not rest easy in my bed until I had a solution to this. So, yesterday, as I came home on a Saturday night, as drunk as drunk can be, I saw a solution inside the computer, where my own solution should be. So I called my wife and I said to her, will you kindly tell to me, who owns that solution inside the computer where my own solution should be?
“Oh, your drunk, your drunk, you silly old fool, still you cannot see – that’s an ITERATOR that my mother sent to me”
Well it’s many a day I travelled, a hundred miles or more, but a proper iterator in SAP, I never saw before.
http://en.wikipedia.org/wiki/Iterator
Now, an iterator just does something rather akin to looping through an internal table full of different types of things. The problem is an internal table is supposed to consist of lines that are exactly the same e.g. a structure such as VBAP. You don;t have the first line looking like VBAP and the second line looking like LIPS.
I have passed in a lot of random things, different each time. Luckily this is not a problem in ABAP due to the so-called dynamic duo, oh sorry that’s Batman and Robin, I mean the so called dynamic data objects.
Before I started I thought to myself – I am sure I have seen the iterator pattern used in standard SAP, it’s used in ABAP2XLS as well. Why don;t I go looking for an iterator interface. I do a search and sure enough there are twenty billion, all slightly different. Clearly every time there is an internal project in SAP to add a new function that needs an iterator (or whatever) the developer is horrified at thought of looking at what went before, and makes up there own new one, and then calls it a name specific to their project e.g. CL_SCOTTISH_TREE_EATING_ITERATOR to make sure no-one can ever re-use it in a future project. Then they go off and give us “customers” a stern talk about how re-use is the be-all and end-all of life.
So, sod it, I’ll write my own. My current use case is sending different sorts of values into the application log, but another use case I can think of is having an exception class where I can pass in three values, or five values, or however many I want. That way I don’t have to write a different exception class each time with a set number of input paraemeters with concrete types.
As we have seen, I have the calling program send in a random number of parameters – the below is far more verbose than you would probably want, I am just hammering home a point.
CALL METHOD do_something( io_input_parameter = zcl_bc_parameter=>get( value = ld_i_am_a_string
predr = zcl_bc_parameter=>get( value = ld_i_am_a_quantity
prder = zcl_bc_parameter=>get( value = ld_i_am-a_money_value ) ) ) ).
Then, inside the DO_SOMETHING I need a way to “unpack” the values that I have just been given. I am going to put all the instances of the parameter class passed in into a static internal table.
METHOD unpack.
FIELD-SYMBOLS: <value> TYPE any.
IF if_i_am_first = abap_true.
CLEAR mt_parameters.”Static table
ENDIF.
APPEND me TO mt_parameters.
CHECK mo_predecessor IS BOUND.
mo_predecessor->unpack( abap_false).
ENDMETHOD.
This is using the recursive call I described before to loop trhough all the parameters passed in and out them in an internal table.
Now, it is quite clear that ABAP wishes it was Java, despite Java being owned by Oracle, and every release of ABAP brings the two languages closer together Given that, I might as well use the Java type synatx when dealing with iterator behaviour as oppsoed to evil behaviour like looping over an internal table. Who would do such a horrible thing? That is so ten minutes ago.
METHOD has_next.
IF mt_parameters[] IS NOT INITIAL.
rf_yes_it_does = abap_true.
ELSE.
rf_yes_it_does = abap_false.
ENDIF.
ENDMETHOD.
METHOD next.
DATA:lo_parameter TYPE REF TO zcl_bc_parameter.
READ TABLE mt_parameters INTO lo_parameter INDEX 1.
IF sy-subrc <> 0.
CLEAR ro_value.
ELSE.
ro_value = lo_parameter->mo_do_value.
DELETE mt_parameters INDEX 1.
ENDIF.
ENDMETHOD.
There we go, the parameters class is now totally independant of the logging class. I told Donna Summer – she was very impressed and told me “this state of independence will be, this state of independence will be”.
OK, in my logging class I have passed in an IO_INPUT_PARAMETER an instance of my parameter class.
io_input_parameter->unpack( abap_true ).”i.e. clear static table
WHILE io_input_parameter->has_next( ) = abap_true.”oh, matron, just like Java
lo_do_value = io_input_parameter->next( ).
ASSIGN lo_do_value->* TO <value>
CHECK <value> IS ASSIGNED.
add_input_to_log( EXPORTING id_input = <value>
CHANGING cd_message = ld_message ).
ENDWHILE.
There we go. The dependencies have been removed, I am sure the “gang of four” who wrote the book on design patterns would be really pleased with me if they were not too busy bursting into flame and turning invisible and extending their arms to twenty foot long.
Just to lighten the load of heavy techincal ABAP I would just like to leave you with two totally unrelated things. Firstly, here is an SAP job advert that was emailed to me from Germany the other day. This company, based in Munich, is looking for SAP experts. I have to say you don’t get SAP job adevrts like this in the UK or Australia.
On an even more unrelated note, before I became an Australian citizen, I lived in the West Country of England, near Bristol. I would just like to introduce the world to a pop group from that next of the woods who have been going strong since the 1960’s.
http://www.youtube.com/watch?v=v2CF8HHbWdo
This is the Wurzels version of Pulps’ “common people”. The lyrics are almost exactly the same as far as I can tell, but I think there are more farm animal noises than in the original. The accent of the lead singer reflects the way I spoke when I was young, I had to learnt to tone this accent down or no-one would be able to understand a word I said.
Anyway, that is it for now, time to go down the pub.
If anyone woud like to tell me what is wrong with my PARAMETER class as described above, or tell me how to achieve the same thing in a better way, I am all ears.
Cheersy Cheers
Paul
One of the most entertaining blogs.The effort put into achieving the result is commendable and the narration part is one of the best even outside SDN 😆 .
terrific narration 😀
I have no clue if that is good or bad ABAP, but no doubt this is good blog and has the style I love to read.
It's good. Trust me. I'm a developer and I've got a brand-new combine-harvester.
I had tried to speed-read your older blog, but couldn't understand it.
The advert in this post was interesting, and made me read your blog at slower pace.
As a result, I am now your follower.
In this particular case, the end justifies the means 😏
Conclusion: I have to drink more... 😘
Good one (again)
As always, I've learned more in the intro to your blog than in most blogs' content. The part about reuse is so true - I discovered that while trying to find an OO wrapper to the application log myself (I found fifty written by SAP and three written by my coworkers).
One question, though - what is the advantage of using an iterator vs. looping over an internal table (one of whose columns is a TYPE REF TO ANY)?
Secondly, if you want to save four lines (and come on, who doesn't):
METHOD has_next.
rf_yes_it_does = boolc( mt_parameters[] IS NOT INITIAL ).
ENDMETHOD.
But I suppose I'm nitpicking now 😛 .
The advantage is abstraction. OK - when it's a simple internal table, what's the point? - but I've encountered more complex looping situations where it has made life a lot easier.
I think I understand. I'll keep my eyes open for any situations where that would help. Based on Paul's recommendation and the reviews on Amazon, Clean Code is on my list of books to read so I'm sure that will help make sense of it.
I was being sarcastic in the blog - obviously in this case it is better to use an internal table - I was just poking fun at the love of Java that seems to be prevalent, even when it is clearly inappropriate.
As far as I can see in Java and presumably many other languages they struggled with a good way to store collections of data objects, and came up with a myriad different ways, different sorts of arrays and hash smoking maps and all sorts of things. If they were 24 ways to store a collection of objects, then a common front end - the iterator - makes lots of sense, to hide the actual way you are storing things, and let you change the way you store data when something better comes along.
In ABAP world we are spolit as we have the internal table which neatly solves all the things Java was trying desperately to get around, so the iterator seems redundant.
That said, the art of programming is trying to guess what might change, and if the way you store a list of things is complicated in the first place i.e. not just one internal table, or you have the slightest suspicion you may need to change it in the future, then an iterator provides a layer of abstraction, just as Matthew has said.
Cheersy Cheers
Paul
Gotcha, that makes sense now. Thanks for the explanation.
the advert in your blog is nice....(thiumph)...nice blog...
regards,
sampath