In my earlier SAP years, I used to go from project to project, and was forever finding that I wanted to do the same things that I did last time - programming wise. I quickly grew tired of this repetitiveness - so something just had to be done about it.
It became a bit of a game - how could I alter the way I had to program, and record all those little juicy code snipets, for anything from updating the screen status bar, to speeding up DATA declarations.
My answer was to have a personal program INCLUDE, and to accumulate the knowledge and experience, in code fragments housed in MACROS. Before I knew it, an interesting side effect occured - I had started creating my own version of ABAP - for example - I didn't like the "REFRESH" command , so I reinvented it as "zap".
define zap. free &1. clear &1. end-of-definition. data: xtab like tab512 occurs 0 with header line. zap xtab. |
See - that was four less key strokes! And, it just sounds like what I want to do to an internal table.
So, I would merrily accumulate these macros (I have approx 100), as I went from project to project. Each place I went to got the benefit of the macros that I had built up from the last place, and I took with me the new ones as they evolved. This was always an agreement that I made with the Management, and they were usually quite happy when I explained that it would mean that I would code faster/be more productive as a result (I'm sure we could get into "Holy Wars" over what this means in terms of IP, and also the issue of ABAP, just not looking universal anymore, but I'll leave that discussion as an exercise for the reader :-).
Now, as a Perl programmer - the three tenents of Perl - "laziness, impatience and hubris", are dear to my heart, and Macros play right into this.
Macros don't just save you time, by reducing the typing you have to do for repetitive tasks, they also allows you to define new actions, and grammar in a programming language, like this:
define uc. translate &1 to upper case. end-of-definition. data: x type string value 'the quick brown fox'. * convert to upper case uc x. |
or:
define cat.
concatenate &1 &2 into &1.
end-of-definition.
data: x type string value 'the quick brown fox ',
y type string value 'jumped over the lazy do'.
* concatenate two strings together
cat x y.
|
These time saving devices have also allowed me to bring ABAP just that little bit closer to other more "natural" languages that I like programming with, while also gaining (a little) satisfaction by further obliterating it's COBOLesque roots.
But - that is not the main thrust of this spiel - what I really wanted to show was how you can further push the boundaries of ABAP, by using RFC, and the "smoke and mirrors" quality of Macros, to bind other programming languages to your applications.
The example detailed below, is a functioning Application Server, that is RFC enabled. It just so happens that the Server is written in Perl, but there is no reason why it couldn't be Python, or Ruby, or any number of other programming languages - it was just easier (for me) to do it in Perl.
The Server provides the functionality of executing the various snippets of Perl code passed to it, but it is the Macros that hide away all the unpleasant verbosity of translating those RFC requests, into what looks like a new set of commands in the ABAP language.
For instance, you can execute an arbitrary snippet of code:
perl_string = 'print "Hello + return!\n"; "the return bit";'. pexec_return perl_string result_string. write: /01 result_string. |
and result_string will have "the return bit" in it, as it is the last evaluation in the Perl code block.
"Well - what is the use of that?" I hear you say. Well - take a look at another example of what we can do:
method_name = 'MIME::Base64::encode_base64'.
pstring_table = 'my piece of text'.
append pstring_table.
pstatic_method method_name pstring_table result_table.
loop at result_table.
write: /01 'base64 encoded string: ', result_table.
endloop.
|
This piece of code allowed a static method name (encode_base64) from a Perl package (Mime::Base64) to be called, passing it an arbitrary list of parameters, and receiving an arbitrary list of results - in this case, specifically calling a function that base64 encoded a string
I now have a means of base64 encoding ABAP strings in any of my programs (if I really wanted that - your mileage may vary).
But even that is not the extent of the point that I'm trying to make here - CPAN has literally thousands of packages and libraries that could be useful in your code, and now they are all available!
Also, because of other Macros available in this Perl Server, you can execute code blocks in various ways, perform Perl style regular expressions, instantiate Perl objects, call instance methods, and delete objects.
Note: to obtain the full details of what commands/macros are available, and how they operate, please refer to the INCLUDE file (it is documented), and the test Report referenced below in the "What you need" section.
Additionally, this is functionally no different to how the outbound communication with the NetWeaver JAVA application server works, as it relies on the Registered RFC interface for communication with the JVM.
However - where Perl (and certain other languages) differs (and I think excels) is that Perl has a very universal set of data types (scalars, and arrays) and uses the concept of coercing values into the appropriate form for a given context (eg. changing a string to an int if doing a numeric comparison etc.), making it very easy to represent it inside another language - in this case, ABAP.
The whole set of examples are available for you to try. There are two main components to this. Firstly, you need to setup and run the Perl server, and secondly, you need to create the program INCLUDE containing the macros, and the test Executable ABAP program.
What you need:
The environment I used for developing this was:
If you are running the test suite, then you can expect output like this from the Perl Server:
Mon Jun 7 09:06:10 2004: Debugging is switched on... Mon Jun 7 09:06:10 2004: VERSION: 1.31 Mon Jun 7 09:06:10 2004: START Mon Jun 7 09:06:14 2004: Running do_exec_perl... Mon Jun 7 09:06:14 2004: call type is: E Mon Jun 7 09:06:14 2004: Command is: #print "Hello!\n";# Hello! Mon Jun 7 09:06:14 2004: Finished iteration - returning... Mon Jun 7 09:06:14 2004: Running do_exec_perl... Mon Jun 7 09:06:14 2004: call type is: ER Mon Jun 7 09:06:14 2004: Command is: #print "Hello + return!\n"; "the return bit";# Hello + return! Mon Jun 7 09:06:14 2004: Exec result is: the return bit Mon Jun 7 09:06:14 2004: Finished iteration - returning... .... |
The test Report output should look something like this:
A lot of the focus with SAP seems to be (to me) on how to make SAP more "open", and accessable to the rest of the (Computing) world, but why shouldn't we look for ways in which SAP (or more specifically - R/3) can be extended by bringing in applications from the outside.
In this example, I have hopefully shown how this can be achieved, as I have opened SAP up to the potential of the extensive code base of the Perl community.
however - it is not just Perl that has something to offer. There are many other communities built up around programming languages, that also have large application resources available - so why not these too?