Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
hardyp180
Active Contributor
ABAP Objects is the Way Forward – I Want to Believe
                       
When I returned from Germany to Australia in May 2012 I made a vow to myself that I would do all new programming in Object Orientated ABAP whether I liked it or not. Since then I have written a lot of blogs on the subject, for example:-
I have been reading everything on the internet about this matter, in essence, the whole world seems to be telling be that if I write my new programs in an OO fashion, then I will get the following benefits:-
·         Programs are faster to write
·         Programs are easier to maintain
·         Programs are highly unlikely to break when you change them
·         Every project generates re-usable objects to make all further projects easier
If this is true, then to quote Ben Elton in his book “Chart Throb” I would say “I want this – I want this SO MUCH”.
Opportunity Knocks
Thus far I have been concentrating on the so called “legacy code”
i.e. the vast bulk of my companies system which is written in procedural ABAP. This year however a gigantic project has come my way, one that will need a bucket load of coding, a completely new concept, so everything has to be written from scratch. This is the acid test. Thank god my current boss lets me try out new things. Not every boss would.
It would be so easy to do everything just the way I have always done it, but now is the time to jump out of my comfort zone, and try and write the whole thing according to all the principles I have just learned.
I will take longer – of that I have no doubt – but that is because (at least for me) it takes years of playing around with OO programming before you really know what you are doing. Nonetheless, the aim of the game is can I get the other three benefits, and the more I do this the easier it will become, and then maybe I can get all four.
Or is the whole thing an illusion? Could it be a light? It’s just an illusion. Could it be a light? In all this confusion. There is only one way to find out.
He likes to keep his Fire Engine Clean – it’s a Clean Machine
I wrote a book review the other day on SCN
in regard to Robert Martins’ book “The Clean Coder”. The book I actually wanted was “Clean Code” by the same author. Once I realised I had the wrong book I ordered the right one as well, and now I have got that and am reading it.
I had a comment that said I might not find it as useful as I might like as the vast majority of it was in Java. The funny thing is that – at least IMHO - ABAP Objects has been trying to become more and more like Java as the years have gone by – in 7.40 ABAP there is even an equivalent of the Java keyword “NEW” as far as I can see – so this is maybe more relevant to the SAP world than one might think.
As far as I can see thus far the bulk of the advice relates to OO programming in general, albeit always using Java as the example language. I could relate virtually all of it to ABAP Objects. There are a few guidelines presented as good programming practise, which really are designed to get around Java specific constructs.
For example Uncle Bob says the reason you should not have more than one or two parameters in a function is because you can’t tell which parameter the value is going to  - as far as I can see in Java you have to say DoSomething( one_value, another_value, yet_another_value) and you don’t know what the parameters are mapped to. In ABAP it is 100% the reverse, the parameter names – in OO world - are compulsory.
So in Java the rule makes sense, in ABAP it doesn’t.
So, in the book it’s easy to spot the Java specific things, but they are in the minority. Once I have finished it – and the foreword says if you finish this quickly you  haven’tgot the point – I will blog about it in great detail.
It’s Alive! It’s Alive! It’s Alive!
Naturally I can’t say what I am working on, but I can use the good old SAP practice of using SFLIGHT as an example. However that is boring, so I am going to do this as in the form of a story, and say that I am working on a project for Baron Frankenstein to create a better monster. His prior monsters did not work too well, so SAP convinced him to sign up to their rapid deployment service for cloud based, mobile, in-memory, monster making.
One million euros later he realised that the “out of the box” solution didn’t give him everything he wanted so he hired me to write a monster making program in SAP whereby he inputs all the attributes he wants from a monster and my program uses algorithms as complicated as the human genome project, to prepare the final data, which then gets interfaced to his monster making machine via PI during a thunderstorm.
Now, amazing as it might seem, some people may say that is a silly example. The funny thing is, in real life, the task ahead of me is just as complicated, if not more. I also think I am going to enjoy it – a lot – for the very reason that it is so complicated. It’s better than having to write an ALV report to dump out the contents of BSEG.
Memento
The most difficult thing for a procedural programmer like me is you have to do everything backwards – that is you START by testing, before you have written any actual code. Does that sound like madness?
Normally you write everything and then see if it works. Often the only way you REALLY know if it works is when it goes live in production and then you users tell you what they think.
The other day I got a classic email from a user, after she had tested and signed off my latest round of changes to her application, and after those changes had gone into production.
The email more or less said “this is now working the way we asked for it, but this is different to the way it worked before the changes”. To me, that was the definition of success, to the user it was the definition of failure. After a bit more digging around, it turned out to be the ever popular “this is just what I asked for, but not what I want” situation.
Out of Their Minds
After you have been in IT for a while, it becomes clear the only way you will ever give the users want they really want, is to magically read their desires straight out of their brains, because the actual requirements bear no relation to what you are actually going to get on any sort of specification, or even from what people will say to you they want.
One fine day I had to write a souped up version of F-32 which used some fancy algorithms to bring together groups of customer invoices against the payments they made. In my industry customers don’t just pay one invoice at a time, it is horribly complicated, and on top of that F-32 is a horrible transaction, the J.D.Edwards equivalent beats it into a cocked hat.
Anyway, none of that is really relevant; the point is I made a huge effort to make sure this (procedural) program did everything the specification asked for. I told the manager who wrote the specification I took every sentence in the specification and found a place in my program where I could cut and paste it as a comment. If I could not find such a place then that told me I may have not fulfilled the requirement. He had no idea what I was on about, but it sounded good, he said he tested it and everything was fine, into production it went.
The next day he came and told me that the “XYZ” rule was not being followed, and that rule was the most important rule, it was the whole reason the program was being written in the first place. A naïve programmer might have asked why, if it was so important, it was not mentioned in the specification, or even by word of mouth, but I am over such things.
In the famous IT article “Design By Contract” Bertrand Mayer mentions that when you hire a cook you do not actually have a clause in the contract saying “don’t burn down the kitchen” – it goes without saying. You would still feel burning down the kitchen was a breach of contract, even if it was not in the contract. In the same way, some things are so obvious to business users they literally cannot conceive you would not know it, so why bother putting it in the specification?
I’ll Tell You What I Want, What I Really Really Want
I have been in my organisation 23 years, so I know what people want. They want the same thing your users’ want, what every user wants.
They want the system they had before SAP. They want SPREADSHEETS. Tell me that is not true!. If it isn’t true, how come every time IT turns their back, people start doing all their tasks off system using spreadsheets? This is why in the last year I have found ABAP2XLS to be such a hit with end users.
So, I tracked down Victor Frankenstein’s assistant, Fritz (known as Igor), and asked him how they made monsters before the advent of SAP. It turns out they had a massive spreadsheet, and on one sheet you put in values, and a whole bunch of VLOOKUPS and the like were down on twenty other tabs full of data, and after going through assorted formulas the final result came out on the last tab.
Then I go to the Baron and ask him “if you could have that exact same thing in SAP, would you be happy?” and naturally the answer is “of course”. So a direct translation into ABAP would be a good starting point, and only after that could we get to the underlying problem, which is the current system (spreadsheet) doesn’t do everything he wants, which is why I was called in originally.
All Right Now
This is wonderful news in all sorts of ways, because we have a starting point. In the current system – which is a spreadsheet – if you put in a certain set of input values you get a certain set of output values. Making the – possibly dubious – assumption that the current system is correct, thenyou have a high level TEST – which is supposed to be our starting point before we right the program.
As an aside, in regard to the old system being presumed to be correct, experience has shown that when the new SAP system comes up with a silly answer, and it can be proved that the same answer comes from the old system with the same input, people grudgingly admit the old system was not perfect, and then the logic can be corrected.
The other wonderful thing about spreadsheets is that the calculations are not all done in one hit – if you have a hundred calculations and lookups, you don’t do them all in one cell, you do each calculation or lookup one at a time, in a different cell.
So our list of tests would look like this:-
·         A bunch of so called “user acceptance tests” which revolve around putting different input criteria into the “black box” of the program calculation engine and then checking the final result is correct
·         A much bigger bunch of “unit tests” which test the inputs and outputs of the much smaller blocks of code which make up the “black box” i.e. the individual calculations
I stress again, we haven’t written anything yet, we are going to start with the tests, hence “test driven development”.
Figure 3 – Keep Calm
So, I have all my tests already because I have a whacking big spreadsheet, which just needs to be translated into ABAP as a first step.
I am going to start my creating the framework to run a unit test which is a “user acceptance test” i.e. I input the same things that are on the first tab in the spreadsheet and expect the same results as on the final spreadsheet tab. It will be a long time before that test passes, but we start off with an end goal and a journey of a thousand steps.
This is it. I am now actually going to write some ABAP. The instant problem is – will my colleagues let me, or will I be drowned in the sea of support?
You say Tomato, I say Tomato
In my recent blog
I talked about using the “Pomadoro technique” to try and be more efficient while I write this new beast. In essence this involves setting a wind up tomato timer to 25 minutes and trying to work on something uninterrupted for that, seemingly short, time period.
Amazingly, you can download a 45 page book telling you how to best use your wind up tomato.
There is a whole web site about this, and you can even take exams and become a “master of the tomato”. This is like “The Goodies” in the UK where you became a master of hitting people over the head with a black pudding, and the better you got the bigger hat you got to wear.
Figure 4 – The Goodies
If that is too radical for you, a read a much simpler tip the other day for being more efficient at work – it is claimed that the average work day is a constant stream of interruptions, after each one it takes twenty minutes to really get back into what you are doing. The most common interruption is the outlook desktop alert appearing in the corner of your screen telling you a new email has just arrived.
I don’t know about you but I cannot stop myself from breaking off to see what it is, which is crazy, because I KNOW what it is, because the title and sender was in the little box that popped up. It is even crazier because if they are in the same building as me, regardless of whether I read the email or not, they are going to walk over to my desk ten minutes later anyway to say the exact same thing as they just wrote. It makes you wonder why they bothered writing the email.
Office Communicator is a million times worse, because someone can see if you are at your desk and have pressed a button on the keyboard in the last few minutes, so they know for a fact you are there, and when they send an instant message people are AMAZED if you don’t break off what you are doing and answer back straight away.
Here we have examples of tools which look incredibly useful at first glance, but end up paralysing the whole organisation. Really I should switch my email off for large chunks of day, but I just can’t bring myself to do that, so last Friday I took the enormous step of switching off the “desktop alert” so the little box does not keep popping up every two minutes. Next cab off the rank will be telling the office communicator (which I can’t switch off) that I cannot be disturbed because I am in a meeting, a meeting which lasts forever.
Simon Template
To start off with I am going to make all the classes local, later on we can see what might best live in a Z repository object. Again, I am sure everybody does everything differently, but I find that after about a week in the job of ABAP programming you never do anything from scratch, but have a series of skeletal templates you copy and then alter.
In this case I have small “type 1” executable program so I can have a selection screen (as opposed to the imaginary alternative) and inside that have some includes, a TOP in case I dare to have any global variables, and INCLUDES for the local class definitions and implementations.
Since unit testing is the be all and end all, the first thing to do is make sure you can test private methods. The “clean coder” book seems to imply you can’t do that at all in Java, which seems strange, and you can’t do it in ABAP either without the following workaround. The trouble with these workarounds is that SAP might take them away at a moment’s notice. In this case I really hope they do not.
*----------------------------------------------------------------------*
*       INTERFACE lif_unit_test
*----------------------------------------------------------------------*
* You need a blank interface defintion if you want to be able to do
* unit tests on private methods
*----------------------------------------------------------------------*
INTERFACE lif_unit_test.
ENDINTERFACE.                    "lif_unit_test
Next, the class that I am going to be testing needs to be FRIENDS with that interface.
CLASS lcl_monster_simulator DEFINITION FINAL FRIENDS lif_unit_test.
Lastly, the test class needs to refer to that interface also.
CLASS lcl_test_class DEFINITION FOR TESTING
   RISK LEVEL HARMLESS
   DURATION SHORT
   FINAL
.


 
PUBLIC SECTION.
   
INTERFACES lif_unit_test.

 
PRIVATE SECTION.
   
DATA: mo_class_under_test         TYPE REF TO lcl_monster_simulator,
None of the above adds any value; it is just something that has to be done to avoid an SAP limitation. Obviously you would want to test private methods; you would want to test everything, that’s the whole point of the exercise. If you don’t have an automated test, it can (and will) break when you change some seemingly unrelated part of the program.
Method In My Madness
The first method I will define in my test class will be “make monster” which is what I would describe as a “user acceptance test” i.e. it will call the main method of the class under test with the inputs and outputs of the spreadsheet as a whole.
METHODS: setup,
*--------------------------------------------------------------------*
* Specifications
*--------------------------------------------------------------------*
   
"IT SHOULD.....................
   
"User Acceptance Tests
    make_monster
FOR TESTING,
Now we come onto the subject of “domain specific languages” …
which is how I make the implementation of such a test method read in such a way a business expert would be able to read it.
METHOD make_monsterIMPLEMENTATION.
  Given_desired_monster_features( ).
  When_monster_is_assembled( ).
  Then_it_goes_mad_and_kills_its_creator( ).
ENDMETHOD.
As an aside, it seems that all my previous blogs are fitting together like jigsaw pieces … but hang on … did not something similar happen to Snoopy?
Figure 5 - Snoopy
Anyway, back to the GIVEN / WHEN / THEN structure which is the essence of behaviour driven development testing, in the GIVEN method you set up the input variables, in the WHEN method you call the piece of production code, and in the THEN method you verify that the results are what you expected.
Now to do all that we need to think about the method we are going to test in the WHEN section, and for that we actually need to define the class under test, and the method we are going to test, and it’s signature, but that’s ALL. We just need the structure; we don’t need its innards.
Our lovely spreadsheet tells us all this i.e. the inputs and outputs, in EXCEL cells can hold any sort of value, but to translate this into ABAP we need parameters of a certain data type. As I want to keep to that domain specific language structure I am going to fill an input structure in the GIVEN method, pass the values from that structure into the production code in the WHEN method and pass the output values into another structure, which gets evaluated in the THEN method.
To state the seemingly obvious, I need to define a structure with names and types. That’s so obvious and easy it goes without saying. So here I go:-
DATA: BEGIN OF g_typ_monster,
  Xyz123                    TYPE I,
  Meaningless_nameTYPE string,
  Wibbly                      TYPE p DECIMALS 3,
  Wobbly                     TYPE c,
  Woo                          TYPE ekpo-bstae, “same length & type, but no semantic similarity
END OF g_typ_monster.
You may say no-one would do something so silly, I wouldn’t have believed it until I started looking at some of my programs, and indeed some standard SAP ones.
When I See An Element Fly
It’ easy to understand that as opposed to variable names like STRING or XYZ123 if you call a variable a name that actually describes what sort of data it contains and what it is used for e.g. ERROR_MESSAGE as opposed to STRING, or HEIGHT as opposed to XYZ123, then the code becomes self-documenting to a much greater extent.
Moving onto the type definitions, if everything is internal then the built in SAP types are wonderful. The question is – are these values ever going to be user facing i.e. is a user going to have to enter them on a screen, maybe with an F4 help, or are they ever going to pop up on some sort of report which the user looks at, or maybe a table maintenance dialog?
If the answer is “yes” or even “maybe” then you know it’s likely you have to create a repository Z structure or transparent table, so it is time to think of creating custom data elements. I can hear the screaming already, what a waste of time, so much extra effort, just use standard SAP elements of the same type and length, or built in types. To make things worse, I am going to insist that whilst creating thedata element you take the path less followed i.e. GOTO -> DOCUMENTATION -> CHANGE and then write what this value means in business terms.
A lot of developers would rather crawl over a thousand miles of broken glass than write one word of documentation in the SAP system. Many would be puzzled why I would even CARE what it means, I have the algorithm don’t I? I know it’s a value or a string, if it’s a four character string just pick EKPO-BSTAE, that’s a four character string, surely that’s good enough, and so much easier.
Time / Money / Learning to Fly
I’ll always remember that quote I read once in response to a developer posting online about testing and it went along the lines of “typical programmer … no concern about time / money”.
You have to take these comments as deadly serious as most management will look at the surface and if they think you are doing something the long way, then out of the door you go, regardless of whether it was the “right” thing to do.
This is just like training, always the first thing to be cut, and before you know it a vicious spiral occurs
·         Money is tight, so training is reduced
·         People learn from their predecessor if they are lucky / or guess
·         No-one knows what they are doing, SAP wise
·         Tasks get done slower and/or wrong
·         This has to have a negative effect on productivity, which feeds through to the bottom line
·         Money is even more tight, so training is reduced further
·         Etc. etc.
·         Then you pay a consulting company ten billion dollars to do a study to work out what went wrong
That is an over-simplification, but I am sure you get the idea. It is the same with programming – since 95% of programming effort is in maintenance, wouldn’t it seem a logical trade off to spend twice the effort on the first 5% if you could dramatically reduce the effort of the remaining 95%?
Put like that the answer is obvious, but it isn’t put like that, and to be fair to management, if all they can see is that 5%, the tip of the iceberg, then why wouldn’t they concentrate on it? All this unit testing business is so esoteric, I can’t even explain it to my ABAP colleagues, let alone the managers, not that this stops me trying with both groups. If I can’t justify that, even with arguments like “this will stop nasty surprises every time we make a change in production” then what chance do I have to justify “wasting” time by documenting things within SAP?
Anyway, I’m allowed to do it, so anything remotely user facing gets a data element so then they can press F1 and get a description of what the field means. There is so little of that in SAP- in standard programs let alone Z custom ones - most users would not even bother pressing F1 so they can see “XYZ field – this is the XYZ field”.
Welcome to the Thunder Domain
Z Data elements – do they need a Z domain as well? I have seen a lot of custom Z domains which are carbon copies of standard SAP ones, which seems strange. The only purpose I would see for these is to enable F4 helps, and for automatic foreign key checks, neither of which is to be sneezed at.
Just yesterday I created a custom domain for a Z data element, and then set the foreign key and input help in the main table which was keyed on that data element, and then all throughout the system F4 helps magically sprang up for that field, even in standard transactions like VK11 and TK11. For the past 13 YEARS people had no F4 drop down on that field and could put in any value they wanted, and I was able to fix both of these things in about five minutes in dozens of programs without touching them. That is the “open / closed” principle all over.
To quote from the book “Head First Design Patterns” by Eric & Elisabeth Freeman:-
Remember, code should be closed (to change) like the lotus flower in the evening, yet open (to extension) like the lotus flower in the morning.”
What’s this first test all about, Alfie?
I’ve gone a bit off topic here, as per usual, so to recap, I am writing the first unit test, because of the spreadsheet designed b the business user hunchback I know the signature (input and output parameters) of the WHEN section, so I need to write a method to fill an input structure (GIVEN), the method to call the production code (WHEN), and a method to evaluate the output structure (THEN). I can summarise this as follows:-
You put some data in,
You get some data out,
In, Out, In, Out, Shake it All About,
You do the Data Cokey and you turn around,
That’s what it’s all about!
And it goes like this…..
  METHOD given_desired_monster_feat."ures.

    ms_input-monster_strength  
= gc_really_strong.
    ms_input-monster_brain_type
= gc_criminal_mind.

 
ENDMETHOD."Desired Monster Features

 
METHOD when_monster_is_assembled.

    mo_class_under_test
->assemble_monster(
   
EXPORTING id_monster_strength   = ms_input-monster_strength
              id_monster_brain_type
= ms_input-monster_brain_type
   
IMPORTING ef_madness            = ms_output-is_monster_mad
              ef_creator_alive     
= ms_output-is_creator_alive ).

 
ENDMETHOD."Monster is Assembled

 
METHOD then_it_goes_mad_and_kills_it."s_creator.

    cl_abap_unit_assert
->assert_equals( act = ms_output-is_monster_mad
                                       
exp = abap_true
                                        msg
= 'Monster is still sane!’' ).

    cl_abap_unit_assert
->assert_equals( act = ms_ouput-is_creator_alive
                                       
exp = abap_false
                                        msg
= 'Creator is still alive!' ).

 
ENDMETHOD."Monster goes mad and kills it’s creator
You will notice I run up against the 30 character limit in ABAP for the names of things, something our Java cousins do not have to worry about... I don't suppose ABAP was ever intended to be a "literate" language given it's creation 40 years ago....
Global Variable Warming
As I have said in an earlier blog the world’s funniest statement was in one the SAP press text books and it said something like “ABAP Objects is easier to learn than procedural programming”. Not for me it isn’t!
I find getting your head round some of the “guidelines” makes your head spin round like an owl. For example everyone says “global variables are bad – they are the spawn of the devil”. The argument seems sound, so off I go, trying to get rid of them.
In the other corner you have the guideline – don’t put very many parameters in your methods, and you want to have “high cohesion” which is that the top level variables you declare in your class get used in as many methods of the class as possible.
I used to think that was a direct contradiction in terms, until I belatedly realised – many years on – that the private variables in the class definition are not “global” variables in the procedural sense. I thought a global variable was one that was - (a) not declared within a method and (b) not in the signature of the method - because that is the way it works in procedural programming.
The more you get into this, the more you realise that FORMS are not like METHODS at all, in the same way CLASSES are not like Function Modules. That takes a big mindset change, I take comfort in the fact that it took the programmers at SAP long enough to make the same jump, as evidenced by all the standard SAP function modules wrapped in static classes – what did that achieve?
Knuth Said
For test classes having the private “member” variables used by all the classes in the test methods certainly makes the code read a lot more like plain English, what is known as “literate programming”.
As always, there was never any separation from a new idea from a new tool to implement this idea, but the concept was clear enough – programs should be able to be read by humans as well as the complier. This is even truer for tests, which are supposed to read like the specification.
Indeed, if you can take your specification and write a test that reads just like it, you win a prize, and confetti starts falling out of the sky.
By the way, here is a picture of Donald Knuth demonstrating his WEB tool to produce programs that humans can read:-
Figure 6 – Donald Knuth
Big Signature in Little China
So I can hide the detail of the signature of the production method I am going to test, but what should the signature of the method under test look like?
I could just put all the input data in a structure, and all the output data in a structure. The benefit then would be when I wanted to bring in a new piece of data I would not have to change the signature of the method, just the structure definition. I don’t know if that is a benefit though, I would still have to change the innards of the method.
As you will see above, I started to do just that, defining an input and output structure and then changed my mind when it came to populating the method under test.
I feel the need, the need for speed, and in addition the need to have the details in the actual signature of my real production method to be tested, the details of every piece of data I need and every piece of data I bring back.
I like to explicitly state every piece of information I need in the signature and whether it is mandatory or not. In a structure, everything is optional; you have to guess what is required.
The ultimate example of big structures as input parameters is the monster signatures of BAPIS, you expose an API the size of the moon to external systems and hope for the best.
I am back to the “design by contract” thing again, I want to make it crystal clear what the method requires and what it ensures it is going to provide.
Cliff-hanger Ending
I have now written a few lines of ABAP, the test does not even compile yet, as I have not actually created the real production method … as in this antimatter world the test code comes first…
So I have not even got to the tip of the iceberg…. Where do we go from here? Is it down to the lake, I fear?
I often get accused of writing blogs that are longer than war and peace, so I will break off here, and continue in the near future….
Summary
·         I want to prove that writing new programs in OO really is better than the “old” way
·         I have a real life project which allows me to do just that
·         I am going to try to document how I go on this step by step
·         The example will be silly, but based on the real project
·         I am using test driven development, so I am starting with the tests
·         To be continued…..
Cheersy Cheers
Paul
Futher blogs in this series

PS What do you think I think is wrong with the following code?
12 Comments