Quantcast
Channel: SCN : Blog List - ABAP Development
Viewing all articles
Browse latest Browse all 943

OO Design Patterns - Decorator - in ABAP

$
0
0
I am happy bunny to see more and more blogs on SDN about object orientated programming in ABAP. Even after 12 years OO is still struggling to gain traction in the ABAP community so the more the merrier. My mate Matt Harding asked the other day “why do we still have procedural programmers out there?” – I would say they are still in the vast majority.
I was reading this blog http://scn.sap.com/community/abap/blog/2013/01/28/getting-the-brownfield-clean-but-not-green--part-ii by UweKunath about how to improve existing (object orientated) code and before getting to the main subject of this blog, in an apparent digression, I want to talk about something that has puzzled me for ages, namely that when you start to learn OO people talk about segregating things into separate classes, as in the following diagram:-
001 Decorator 001.png
                       
So I get my head around that, we need a separate database access layer so we can change the way we get data and the other parts don’t care, we need a separate user interface layer so we can swap ALV for Web Dynpro or UU5 or whatever comes next and the rest of the architecture does not care etc. I thought I had it nailed.
I would, I thought, write programs which would look like this:-
003 Descorator Fram Subclass.png
I am changing the analogy a bit, but the separations of concerns is still there. Then we get into unit testing, and the idea of mocking up layers like the database and the user interface, and injecting them into the constructor of the main class.
Again, after a while I understand all this, the last piece of the puzzle – as I asked Uwe in the above blog – is why do we inject using an INTERFACE as opposed to a subclass of the class we are mocking? He tried to explain it to me, but I’m dumb, so I had to do some more investigation.
And the light bulb finally came on. Initially I just could not see the point of interfaces – abstract definitions of method names and interfaces with no code behind them – but then suddenly I’m through the looking glass and I could no longer see how you could live without them.
The important bit that got through to me is that you shouldn’t be using an interface for mocking objects in unit testing, you should be using interfaces all over the place as a matter of course. Someone said that in a comment at the end of my very first blog in SDN when I started talking about subclasses, but at that point it went right over my head. My farm example would then look more like this:-
002 Decortoar Farm Interface.png
The attributes would be tables now instead of single object references, but then the farm does not know (or care) what humans live upon it, what animals are in the farm, or what vehicles are used, or the exact details of how they do what they do, the farm just sets the high level requirements and leaves the classes to carry these out as they see fit. This means we can add animals and vehicles and the farmer can run off with Postman Pat leaving the wife running the farm, and the main class doesn’t need changing.
It is the same with a database access layer class, if the client only accesses it through its interface you can make radical changes, even substitute another class entirely that implements the same interface and the client neither knows nor cares.
Now, some of this may seem random or incomprehensible, as it did to me not so long ago, and indeed as much of OO world still does, so the way I crawl along is to isolate one concept at a time, from the most interesting article I read at the time, and try and replicate this in ABAP first as a generic example like you see in the articles, and then ask the difficult question which is “can this REALLY be useful?”.
If you have colleagues who feel OO is the devil’s work then that last question is the million dollar one.
Here is a question that occurred to me once I locked on to what interfaces are for:-
“If these are so useful, then presumably all classes should expose their public methods as an interface, and no clients should ever hold references to them any other way”.
Now, like all blanket statements that can’t possibly be true, so can anyone explain why not? Any takers?
In the meantime, I read a good article the other day on the “Decorator” pattern so that is next cab off the rank to try and replicate in ABAP and then try and find a realistic use case. You may ask since this is the title / subject of the blog then why have I been waffling on about interfaces and the like?
In a clever twist this will all come together at the end, just like Snoopy and his novel “It was a Dark and Stormy Night”.
Decorators
I think the book “Design Patterns in Object Orientated ABAP” (http://www.sap-press.com/products/Design-Patterns-in-Object%252dOriented-ABAP-(2nd-Edition).html)  is a work of genius. It was the straw that, for me, broke the procedural camel’s back, and made me realise the benefit of OO programming.
Of all the patterns described, the only one I was really struggling to see the practical benefit of was the Decorator.
As I may have said before, even if the OO concepts are clearly better than procedural ones, it is easy to get so caught up that you just say “this is better because it is”.
Here is an extract from “Asterisk the Gaul” where the exact same thing is going on. Centurion Crismus Bonus has just drunk what he thinks is the magic potion to give him superhuman strength, but he has not really.
004 Decorator CB 001.png
You could say that OO programming and design patterns are the magic potion and that big rocks are business problems that need to be dealt with using the superhuman strength these tools give you.
test2.png
test3.png
From the book I was plugging, in regard to the decorator pattern:-
Igor 001.png
Igor 002.png
006 Decorator CB 003.png
The inference is that it is clearly impossible to add another instruction saying the name with just one line of code without OO and design patterns. You just can’t do it in procedural programming? Or maybe I can?
PERFORM SPEAK USING “HELLO”.
PERFORM SPEAK USING “HOW ARE YOU DOING?”.
Now how would I add the extra instruction with just one line of code, in my procedural world? Any ideas? Oh dear, someone’s just dropped a rock on my foot.
I am being really unfair here, but now that I am convinced this (OO) is a really good thing, at least in principle, I have a mission to try and spread the word.
Another example of the decorator pattern comes in the sample chapter from another great book series called “head first” which tries to provide an idiots guide to OO design and programming in an entertaining way.
The way they present the material is what I like best, it is all jokes and silly examples, but everything is technically valid. Now why would I like that?
So, I will do a quick translation of their example into ABAP, using a slightly different concept, and then we can start the debate.
The first problem I have is how to paste the ABAP code into the SCN. There are several ways, most of which mangle it beyond recognition, some of which make it look OK on the screen but you can’t print it as it vanishes when turned into a PDF or formats itself into one big line, whereby you see only the first few characters. Am I the only one who has noticed this?
So, first the easy bit, the translation from Java to ABAP, and then the difficult bit, which is to actually THINK about this, and find a use for the concept.
The head first example uses types of coffee, which are then “decorated” by subclasses representing the various things you can put into coffee like milk and chocolate and the like.
Naturally I could not use the same example, that would be BORING, so I tried to think of another product which has different things inside it, and since I seem to spend an inordinate amount of time in hotels, I thought that would do. They have different brands for different income groups and each can contain a mixture of “features” like pools or bars or what have you. Also, in the same way you can have two shots of something in a coffee you can have two bars inside a hotel.
I should write the unit test first and go backwards as that is what all the articles tell me to do. If you have read any of my recent blogs you will guess I am going to go totally bonkers on this, and use a whole bunch of helper classes just to make the unit tests look like plain English and thus be “executable specifications”. Later on, you will see just how useful this can be when I attempt to totally redesign EVERYTHING and want to see if I still get the same result.
*--------------------------------------------------------------------*
* IT SHOULD ... Behaviour expected of Class Under Test
*--------------------------------------------------------------------*
 
METHOD tell_me_about_fleapit_hotel.

    given_fleapit_hotel
( ).
    when_asking_about_hotel
( ).
    then_hotel_details_are_correct
( ).

 
ENDMETHOD.

 
METHOD tell_me_about_lenny_hotel.

    given_lenny_henry_hotel
( ).
    when_asking_about_hotel
( ).
    then_hotel_details_are_correct
( ).

 
ENDMETHOD.

 
METHOD tell_me_about_normal_hotel.

    given_normal_hotel
( ).
    when_asking_about_hotel
( ).
    then_hotel_details_are_correct
( ).

 
ENDMETHOD.

ENDCLASS."Test Class
This is what we are working towards; each hotel has various features, so when I ask about each one I expect a different result. I will first talk about the classes in use, and then we will move on to the class under test and how the test class uses this. Everything revolves round the unit test, I haven’t even written any other code yet.
So based on the example I am working from we have one class for the hotel and a subclass for the “decorators”.
CLASS lcl_hotelDEFINITION ABSTRACT.
 
PUBLIC SECTION.
   
METHODS: get_description ABSTRACT
                            RETURNING value(rd_description) TYPE string,
             get_cost        ABSTRACT
                            RETURNING value(rd_cost)        TYPE vbap-netwr.

ENDCLASS."Hotel Definition

CLASS lcl_hotel_decorator DEFINITION INHERITING FROM lcl_hotel ABSTRACT.


ENDCLASS."Hotel Decorator Definition
In real life the hotel would have all sorts of hotel specific methods as well. I follow the example step by step and then code up several types of hotel, I will just show two here:-
CLASS lcl_fleapitDEFINITION INHERITING FROM lcl_hotel.
 
PUBLIC SECTION.
   
METHODS: get_descriptionREDEFINITION,
             get_cost       
REDEFINITION.
ENDCLASS."Fleapit Definition

CLASS lcl_lenny_henry_hotel DEFINITION INHERITING FROM lcl_hotel.

 
PUBLIC SECTION.
   
METHODS: get_descriptionREDEFINITION,
             get_cost       
REDEFINITION.
ENDCLASS."Lenny Henry Hotel Definition
CLASS lcl_fleapitIMPLEMENTATION.

 
METHOD get_description.
    rd_description
= 'Fleapit'.
 
ENDMETHOD.

 
METHOD get_cost.
    rd_cost
= '1.00'.
 
ENDMETHOD.

ENDCLASS."FleapitImplemenation

CLASS lcl_lenny_henry_hotelIMPLEMENTATION.


 
METHOD get_description.
    rd_description
= 'Lenny Henry Hotel'.
 
ENDMETHOD.

 
METHOD get_cost.
    rd_cost
= '29.00'.
 
ENDMETHOD.

ENDCLASS."Lenny Henry Hotel Implemenation
For the benefit of non UK people Lenny Henry is an English comedian who advertises budget hotels. Now we know that, then I create some classes for the decorators, bars and the like. I am putting silly values in for the costs, it is the concept that is important – the feature we are adding adds some sort of value to the main object.
CLASS lcl_hotel_bar DEFINITION INHERITING FROM lcl_hotel_decorator.
 
PUBLIC SECTION.
   
DATA: mo_hotelTYPE REF TO lcl_hotel.

   
METHODS: constructor    IMPORTING io_hotel TYPE REF TO lcl_hotel,
             get_description
REDEFINITION,
             get_cost       
REDEFINITION.
ENDCLASS."Hotel Bar definition

CLASS lcl_hotel_barIMPLEMENTATION.


 
METHOD constructor.
    super
->constructor( ).
    mo_hotel
= io_hotel.
 
ENDMETHOD.

 
METHOD get_description.
    rd_description
= mo_hotel->get_description( ).
   
CONCATENATE rd_description '+ hotel bar' INTO rd_description
  SEPARATED BY space.
 
ENDMETHOD.

 
METHOD get_cost.
    rd_cost
= mo_hotel->get_cost( ) + '0.20'.
 
ENDMETHOD.

ENDCLASS."Hotel_Bar Implementation
You will notice that for a decorator like the hotel bar, even though it is a subclass of LCL_HOTEL the key difference is the redefinition of the CONSTRUCTOR whereby you can create this object with reference to another one, which as we will see in a minute enables you to put lots of decorators inside the main object - a goal of OO is to hide the internal details of individual object instances from other programs (clients) which have to deal with them. The client does not need to know or care about the internal technical structure of an object it is using, the client just needs the correct information when it asks the object a question. This client is guilty.
Now, let’s get back to the unit test. We need a class to test – client - which makes use of what we have defined so far. We are going to a hotel. We are going where the sun shines brightly. We are going where the sea is blue.
*--------------------------------------------------------------------*
* Application Model
*--------------------------------------------------------------------*
CLASS lcl_summer_holidayDEFINITION FRIENDS lif_unit_test.

 
PUBLIC SECTION.
   
METHODS: get_hotel_details IMPORTING io_hotel     
                              TYPE REF TO lcl_hotel
                             
EXPORTING ed_description TYPE string
                                         ed_cost       
TYPE vbap-netwr.
ENDCLASS."Summer Holiday Definition

CLASS lcl_summer_holidayIMPLEMENTATION.


 
METHOD get_hotel_details.
*--------------------------------------------------------------------*
* IMPORTING io_hotel       TYPE REF TO lcl_hotel
* EXPORTING ed_description TYPE string
*           ed_cost        TYPE vbap-netwr.
*--------------------------------------------------------------------*
    ed_description
= io_hotel->get_description( ).
    ed_cost       
= io_hotel->get_cost( ).
 
ENDMETHOD."Get Hotel Details

ENDCLASS."Summer Holiday Implementation
I am going to do the important bit of inserting the decorators into the main object inside the unit test, on the grounds that I haven’t actually got a main program in this example. In real life you would do this in a setup method of your application, possibly based on a configuration table, or BRF+ ( which I have a soft spot for, I used to read the Carsten Zeigler SAP Press book every lunchtime when I worked in Germany, in a beer garden pub naturally (Züchterklause, Wiesenweg 30, 69121 Heidelberg), and a big woofy dog called Emma would come and say hello) or by a similar mechanism.
As I said earlier I have developed an unhealthy obsession with making code look like plain English, so I have used a macro for the core part of this. You could say that is complicating the example and how right you would be.
So here comes the core part – a macro that decorates the hotel with an added feature, making the hotel object look exactly the same after the transformation.
*--------------------------------------------------------------------*
* Helper Methods - to make the actual unit test read like plain
* English
*--------------------------------------------------------------------*
 
DEFINE add_features_to_hotel.
    mo_helper
= mo_hotel.
   
createobject mo_hoteltype &1
   
exporting
       io_hotel
= mo_helper.
 
END-OF-DEFINITION.
You need the helper variable otherwise the ABAP runtime system gets all confused and goes into an endless loop. Apparently Java and C# have no such problems, this is just one of the technical changes you have to make whilst translating code from one language to another as I am doing here.
METHOD given_lenny_henry_hotel.

   
CREATE OBJECT mo_hotelTYPE lcl_lenny_henry_hotel.

    add_features_to_hotel:
lcl_restaurant,
                            lcl_hotel_bar
,
                            lcl_swimming_pool
.

    mo_hotel_type
= 'LENNY_HENRY'.

 
ENDMETHOD.

*--------------------------------------------------------------------*
* What we are going to demonstrate here is adding the same feature
* twice
*--------------------------------------------------------------------*
 
METHOD given_normal_hotel.

   
CREATE OBJECT mo_hotelTYPE lcl_normal_hotel.

    add_features_to_hotel:
lcl_hotel_bar,
                            lcl_hotel_bar
,
                            lcl_swimming_pool
.

    mo_hotel_type
= 'NORMAL'.

 
ENDMETHOD.
That was the first third of the unit test methods, setting up the objects to be tested. The rest is just calling the class under test, and making sure the results are correct.
METHOD when_asking_about_hotel.

    mo_class_under_test
-get_hotel_details( EXPORTING io_hotel          = mo_hotel
                                                                   
IMPORTING ed_description= mo_description
                                                                                           ed_cost           
= mo_cost).

 
ENDMETHOD.

 
METHOD then_hotel_details_are_correct.

   
CASE mo_hotel_type.
     
WHEN 'FLEAPIT'.
        cl_abap_unit_assert
=>assert_equals(act = mo_description
                                           
exp= 'Fleapit'
                                            msg
= 'Incorrect Description' ).
        cl_abap_unit_assert
=>assert_equals(act = mo_cost
                                           
exp= '1.00'
                                            msg
= 'Incorrect Cost' ).
     
WHEN 'LENNY_HENRY'.
        cl_abap_unit_assert
=>assert_equals(
        act= mo_description
       
exp = 'Lenny Henry Hotel + restaurant + hotel bar + swimming pool'
        msg
= 'Incorrect Description' ).
        cl_abap_unit_assert
=>assert_equals(
        act= mo_cost
       
exp= '29.45' "29.00 + 0.15 +0.20 + 0.10
        msg
= 'Incorrect Cost' ).
     
WHEN 'NORMAL'.
        cl_abap_unit_assert
=>assert_equals(
        act= mo_description
       
exp= 'Normal Hotel + hotel bar + hotel bar + swimming pool'
        msg
= 'Incorrect Description' ).
        cl_abap_unit_assert
=>assert_equals(
        act= mo_cost
       
exp= '100.50' "100.00 + 0.20 +0.20 + 0.10
        msg
= 'Incorrect Cost' ).
     
WHEN OTHERS.
        cl_abap_unit_assert
=>fail(msg = 'Unexpected Hotel Type' ).
   
ENDCASE.

 
ENDMETHOD.
I will try and attach the entire source code of the test program to this blog – I have been assured this is possible – and there is no better way of seeing what is going on than debugging a test method. This is especially important given that the SCN will have done it’s best to mangle the code I have tried to put in this blog.
We live in an SAP world…
When I lived and worked in Israel most of the consultants had just come off an SAP implantation from a light bulb company, and then moved on to our concrete producing company. Many times when faced with a tricky concrete industry related problem they (consultants) suggested changing our concrete production process so it was more like the light bulb production process as “that would fit in better with SAP”. That is what consultants were like 15 years ago, even a few years later things had improved dramatically.
Sadly a cubic metre of concrete is not much like a light bulb no matter which way you look at it, so they couldn’t just run with what worked last time. In the same way I can’t just present abstract examples about coffee and hotels without trying to think about how all this would fit into SAP world.
In the examples presented thus far, the decorator objects are subclasses which mean they are in essence the same sort of object as the parent. I can think of two examples in SAP where one object contains zero to many objects of the same type.
In plant maintenance one piece of equipment can have other pieces of equipment attached to it, so a scrungemachine can contain several scrunge enhancing units. The  mother and child objects are all of equipment business object type.
In the same way a bill of materials (BOM) is one material made up of other material objects, though this a bit more complex as you have quantities of the child material in the main material, and it would seem tricky to add 3.25 objects to another object.
Here we have the obvious point that comes up with the decorator pattern – the decorator being a subclass of the main object. Can you really say that milk is a type of coffee or that a swimming pool is a type of hotel? That sounds a bit odd.
On a more technical level, a hotel class would have all sorts of hotel specific methods. Does a swimming pool really need to have all these as well?
I wondered how to get around this problem so I asked Joe Dolce. He said:-
“What’s the matter you, hey? Gottano respect / Whatta you think you do? / Why you looka so sad? / It’s a not so bad / It’s a nice a place / use an INTERFACE”
What a co-incidence! That’s just what I was talking about earlier in the blog, about why using interfaces (composition) was better than inheritance.
VERSION TWO
OK, I will re-write the example, this time using an interface. Let’s see if it makes a difference.
In particular I am thinking about when I went to the bar of a top class hotel in Moscow last year (one of the so called “Stalin Skyscrapers” ) and noticed there was (literally) a Rolls Royce showroom built into the hotel. This is the hotel that has the scale model of Moscow in a section off the main bar. Below is a picture of my wife and Ioutside the Kremlin with some friendly locals we found.
007 stalin.jpg
That car showroom in the Russian hotel was most likely owned by a different entity than the main hotel, and certainly would have very different business processes. In the same way in the USA I recall most hotel bars and restaurants are owned by different companies than the hotel they are in.
In the next example then, I will attempt to have the decorator classes not inherit from the hotel class, and thus not inherit hotel specific behaviour, but implement an interface instead. Thus they could be any sort of unrelated class we suddenly want to attach to a hotel.
Luckily, because I have some unit tests which are so removed from the details of the implementation, I can change some really fundamental things about my class structure and still leave the test methods virtually intact, specifically the data I am passing in, and the results I expect back. So if my radical surgery stuffs up the result I can tell instantly.
I’ll move the behaviour in which I am interested into an interface, and then make my hotel class implement that same interface, and the spooky bit is to give the hotel an instance variable of that interface type. You will see why in a minute.
INTERFACE lif_hotel_features.
 
METHODS: get_description RETURNING value(rd_description) TYPE string,
                       get_cost            RETURNING
value(rd_cost)            TYPE vbap-netwr.
ENDINTERFACE.

CLASS lcl_hotelDEFINITION ABSTRACT.
 
PUBLIC SECTION.
   
INTERFACES lif_hotel_features.

   
DATA: mo_featuresTYPE REF TO lif_hotel_features.

   
METHODS: constructor.

ENDCLASS."Hotel Definition
Again, my hotel class would have lots of hotel specific methods e.g. “have chambermaids walk into your room without knocking” which all subclasses which are actually hotels will inherit, but bars and restaurants don’t need to.
CLASS lcl_hotelIMPLEMENTATION.

 
METHOD constructor.
    mo_features
= me.
 
ENDMETHOD.

 
METHOD lif_hotel_features~get_description.
    rd_description
= 'Hotel'.
 
ENDMETHOD.

 
METHOD lif_hotel_features~get_cost.
    rd_cost
= '1.00'.
 
ENDMETHOD.

ENDCLASS.
It looks like the “features” variable is being set to an exact copy of the hotel object itself, but in fact it just represents the decorator type behaviour. This is the sort of thing which makes procedural programmer’s heads spin round; it certainly threw me for six when I was first trying to grasp the concept.
CLASS lcl_fleapitDEFINITION INHERITING FROM lcl_hotel.
 
PUBLIC SECTION.
   
METHODS :lif_hotel_features~get_descriptionREDEFINITION,
                           lif_hotel_features~get_cost           
REDEFINITION.

ENDCLASS."Fleapit Definition

CLASS lcl_lenny_henry_hotel DEFINITION INHERITING FROM lcl_hotel.

 
PUBLIC SECTION.
   
METHODS :lif_hotel_features~get_descriptionREDEFINITION,
                           lif_hotel_features~get_cost           
REDEFINITION.
ENDCLASS."Lenny Henry Hotel Definition
The hotels are still hotels so they inherit from the main class, redefining the interface methods, and any of the main hotel methods they feel like, and adding any methods specific to themselves e.g. a Lenny Henry hotel might have special offers on Tuesdays.
CLASS lcl_lenny_henry_hotelIMPLEMENTATION.

 
METHOD lif_hotel_features~get_description.
    rd_description
= 'Lenny Henry Hotel'.
 
ENDMETHOD.

 
METHOD lif_hotel_features~get_cost.
    rd_cost
= '29.00'.
 
ENDMETHOD.

ENDCLASS."Lenny Henry Hotel Implemenation
The above is the same as before, nothing to see here, move on.
CLASS lcl_hotel_barDEFINITION.
 
PUBLIC SECTION.
   
INTERFACES: lif_hotel_features.
   
DATA: mo_hotelTYPE REF TO lif_hotel_features.

   
METHODS: constructor    IMPORTING io_hotel TYPE REF TO lif_hotel_features.

ENDCLASS."Hotel Bar definition

CLASS lcl_hotel_barIMPLEMENTATION.


 
METHOD constructor.
    super
->constructor( ).
    mo_hotel
= io_hotel.
 
ENDMETHOD.

 
METHOD lif_hotel_features~get_description.
    rd_description
= mo_hotel->get_description( ).
   
CONCATENATE rd_description '+ hotel bar' INTO rd_description
    SEPARATED BY space.
 
ENDMETHOD.

 
METHOD lif_hotel_features~get_cost.
    rd_cost
= mo_hotel->get_cost( ) + '0.20'.
 
ENDMETHOD.

ENDCLASS."Hotel_Bar Implementation
At first glance the above looks the same as before as well, the subtle difference is this time it is not inheriting from the hotel superclass, go for a walk, ring the bell, kiss, comb your hair, give them a wave, SUPERCLASS!
*--------------------------------------------------------------------*
* Application Model
*--------------------------------------------------------------------*
CLASS lcl_summer_holidayDEFINITION FRIENDS lif_unit_test.

 
PUBLIC SECTION.
   
METHODS: get_hotel_details IMPORTING io_hotel            TYPE REF TO lcl_hotel
                                                     
EXPORTING ed_descriptionTYPE string
                                                                             ed_cost
            TYPE vbap-netwr.
ENDCLASS."Summer Holiday Definition

CLASS lcl_summer_holidayIMPLEMENTATION.


 
METHOD get_hotel_details.
*--------------------------------------------------------------------*
* IMPORTING io_hotel            TYPE REF TO lcl_hotel
* EXPORTING ed_description TYPE string
*                        ed_cost           TYPE vbap-netwr.
*--------------------------------------------------------------------*

    ed_description
= io_hotel->mo_features->get_description( ).
    ed_cost       
= io_hotel->mo_features->get_cost( ).
 
ENDMETHOD."Get Hotel Details

ENDCLASS."Summer Holiday Implementation
Again, not much different in the client, the change is we are querying an object instance variable of the hotel class rather than the hotel class directly.
Another really small change in the unit test macro:-
*--------------------------------------------------------------------*
* Helper Methods - to make the actual unit test read like plain
* English
*--------------------------------------------------------------------*
 
DEFINE add_features_to_hotel.

    mo_helper
= mo_hotel->mo_features.

   
createobject mo_hotel->mo_featurestype &1
     
exporting
        io_hotel
= mo_helper.

 
END-OF-DEFINITION.
I don’t need to change anything else at all in the unit test code, not one thing, due to the fact that when I first wrote it I went bananas in breaking everything up into tiny methods. This is what they mean by the “open / closed” principle I presume, the less you change in existing code, the less chance of stuffing something up.
In the ABAP editor I know take the menu path PROGRAM -> TEST -> UNIT TEST and BINGO! Everything passes i.e. with the same input data I get the same results as before, despite having changed the fundamental underlying structure of the universe, I mean the essence of every non-test class involved in the program.
As we know the only constant is change, so now if the requirement comes in that it turns out what my hotel REALLY needs is an aquarium, and I already have an aquarium class in a totally different part of my system. In the first example I would have had to create a new aquarium class inheriting from the hotel class, in the second example I could just add the interface to my existing aquarium class and Bob is your uncle.
Wrap Up
Well now it’s goodnight from me, and its goodnight from him, but I couldn’t let you go home empty handed, so I am going to leave you with some questions I have a burning desire for the SCN community to answer.
·        Have I made any fundamental, obvious, mistakes in what I have been coding above? Remember the second example is supposed to be an improvement on the first. I am still a beginner here so all constructive criticism is more than welcome.
·        Has anyone out there actually used the decorator pattern in a real live SAP application that is in productive use? If so, could you share some details, if anything is a trade secret you could change the names to prevent the innocent but still say the general concept…..
·        When are subclasses better than interfaces? Was SAP barking up the wrong tree when their (incredibly expensive) training courses told me to subclass everything?
Cheersy Cheers
Paul
P.S. After a hopefully big debate on this matter, the next thing I will turn to is looking at cleaning up so called “legacy code” by which I mean procedural ABAP….
P.P.S. At this instant I have not posted by blog - the code samples look lovely. I have a horrible suspicion the instant I press the "post" button they will get mangled beyond all recongnition.
P.P.P.S. I have attached text files of the two example programs I wrote, the first one using subclasses, the second one using interfaces.

Viewing all articles
Browse latest Browse all 943

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>