Tag Archives: ABAP

run from doco

I hate doco

It’s kinda a mantra that I live a reasonable part of my life to. I think the above image is a not unjustifiable representation of my feelings about documentation:

But there are many good reasons that I should be doing doco. Most of them are supposed to save the customer money in the long run. And occasionally by doing the doco, I even find some small errors in my code that I hadn’t seen before.

 InnoJam Sydney 2011

Before InnoJam had any of that fun fluffy design thinking aspect to it, we ran one in Sydney. It was good fun, and people could build whatever the heck they wanted.

In staying true to my aversion for writing doco, I came up with an idea about auto-generation UML diagrams from SAP code.

Here’s a video of the solution we came up with:

here’s a link to the Prezi that I presented in that video:

http://prezi.com/zri5q-ib4vzp/?utm_campaign=share&utm_medium=copy&rc=ex0share

I wrote a blog post about it:

https://scn.sap.com/blogs/chris.paine2/2011/08/10/programmers-are-lazy–innojam-them

But it was long time ago and the move to a new version of SCN has kinda buggered it up.

Anyway, in short – Rui never managed to get the terms and conditions of CodeExchange changed to a level where I’m happy to support it and put code in there. I’m pretty sure he tried though. So I didn’t do anything with the code.

 

Fast forward 3 years

I have a whiteboard in the office covered in post-it notes. They all represent at least one development that I’ve done for the current project I’m working on. At the beginning of the project, I was very good, and did all my doco as I went along. Then the poo hit the fan, and everyone wanted everything done yesterday, and didn’t care about doco.

So I now have a whiteboard full of post-it notes that represent potentially weeks of doco hell for me. So in my “free time” in the evening I decided to see if I could recreate the solution that we’d built in Sydney, and perhaps make it a little nicer.

 

UML output

The first thing I decided, was that I was NOT going to try to build the graphical output myself. Having had lots of fun in Sydney trying to make Gravity do something it really wasn’t designed for I thought I’d research how else I could get my interaction diagrams created.

If in doubt Wikipedia

http://en.wikipedia.org/wiki/List_of_UML_tools

There were loads there, and I’d pretty much decided on UMLet when I discovered something about interaction diagrams. Basically, interaction diagrams are supposed to show interaction between objects. Bit bloody obvious really. However, the thing is, if I’m documenting my code, I’d really like to show the interaction within my objects too. I.e. if I make a call to a private method of my class, I’d really like that to show up in my diagram. Given that interaction diagrams are only supposed to show external interaction it’s not surprising that most of the tools for creating the diagrams don’t really support this idea of internal object calls.

So a bit of browsing later and I found PlantUML. It has some awesome functionality for creating sequence diagrams, actually, most UML diagrams it seems, but it was the sequence diagrams that I was interested in.

Here’s a simple example:simple_example

 

 

See how it’s quite possible to show “internal” calls of an instance and also show the life time of those calls. This feature I didn’t find on the other free UML tools that I looked at. There are a bunch of other formatting features that can be used too. If you’re interested check out their website: http://plantuml.sourceforge.net/sequence.html

 

Intercepting the SAP standard UML generation

So in transaction SAT there is the possibility to generate your own JNet UML sequence diagram (this exists as standard.)

press the button

 

However, it does not allow you to do things like filter out standard SAP routines (as far as I know! If anyone can tell me how to do this (without needing to list every method I call, please let me know!) When I was looking at one of my examples, where I ran a program to generate a performance review document for an employee, there were over 100,000 different routines called. Only about 400 of those calls involved my code, so you can imagine generating a UML diagram for the whole 100,000 calls would be a bit of overkill (not to mention an impossible to read diagram).

In customer systems there is a function module  ATRA_UML_DECIDER  that has been purposely handicapped. One does have to wonder why this has been done, but nevertheless it has.  It allows the user to chose from a list of potential UML extraction routines. All of these routines implement the IF_ATRA_UML_TOOL interface. There are classes for extracting to JNet, Borland Together and Altova. Now, I’m sure that Borland and Altova have good products, it’s just that I don’t really want to spend money on then when there are perfectly good (for my tasks) free and open source products out there.

There is a factory class/method CL_ATRA_UML_FACTORY  that creates an instance of a class implementing the interface. I overrode this method to use my particular extractor if it was me running the code. In the future, I might enhance this to check for a user role, or perhaps a user parameter, that’s trivial, the main point will be to allow others to access this logic too.

The guts of the code

Simply my implementation of the interface reads the table of data that is passed to the interface, removes all calls that aren’t to or from custom code and then builds a PlantUML representation of that code.

Here’s a very simple output that generates the diagram above.

@startuml
hide footbox
autonumber
participant "Instance 1 of Class\nZCL_HR_EMPLOYEE" as 1
1 -> 1: Call method GET_HELD_QUALIFICATIONS
activate 1
1 -> 1: Call method ZCL_HR_OBJECT->GET_RELATIONSHIPS
activate 1
create "Static Methods of Class\nCL_HRBAS_READ_INFOTYPE" as 2
1 -> 2: Call method GET_INSTANCE
activate 2
2 --> 1
deactivate 2
create "Instance 1 of Class\nCL_HRBAS_READ_INFOTYPE" as 3
1 -> 3: Call method IF_HRBAS_READ_INFOTYPE~READ_PLAIN_1001
activate 3
3 --> 1
deactivate 3
1 --> 1
deactivate 1
create "Instance 1 of Class\nZCL_HR_QUALIFICATION" as 4
1 -> 4: Create instance of class ZCL_HR_QUALIFICATION
activate 4
4 -> 4: Call method ZCL_HR_OBJECT->CONSTRUCTOR
activate 4
create "Function Group\nRHS0" as 5
4 -> 5: Call FM RH_GET_ACTIVE_WF_PLVAR
activate 5
5 --> 4
deactivate 5
4 --> 4
deactivate 4
4 --> 1
deactivate 4
deactivate 1
@enduml

 

 A slightly less trivial example

The following code does some pretty simple stuff, it finds who is my manager, and finds out what required qualifications my position/job has.

DATA: lo_emp TYPE REF TO zcl_hr_employee,
lt_managers TYPE ztthr_employee_objects,
lt_required_quals TYPE ztthr_qualifications.

TRY.
lo_emp = zcl_hr_employee=>get_employee_by_user_id( sy-uname ).

lt_managers = lo_emp->get_position( )->get_managers_recursive( ).
lt_required_quals = lo_emp->get_position( )->get_required_qualifications( ).

CATCH zcx_hr_no_managing_pos_found  ” No managing position found
zcx_hr_no_holders_found  ” no holders for position found.
zcx_hr_no_position_found    ” no position found
zcx_hr_user_id_not_found.  ” cannot find user id for employee
ENDTRY.

So I thought I’d trace it:

it works out at around 200,000 different routines being called. 62 of those are my code, the rest standard.

run through 1

First of all, I need to schedule a trace for myself…

run through 2

 

run through 3

 

Need to know which session I will be recording. If I left it as “Any” it will start recording this session, not very useful!

run through 4

 

Session 2 it is!

run through 5

run through 6

actually run it now!

and the schedule status changes to executed.

run through 7

 

I now need to delete the scheduled measurement. Despite the intimidating words, this does not delete my measurement, just the scheduling of it.

run through 8

 

now swapping to the “Evaluate” tab in SAT I can see my measurement, and I can click to output to UML

run through 9

 

 

Clicking on the button triggers a bit of a pause whilst the system code chugs away and does loads of stuff it doesn’t need to do…

 

Then

run through 10

Save the data and PlantUML starts converting it immediately:

run through 11

 

and the result:

example

Would probably have been a little bigger if my employee had a job assigned to their position, but you can see how incredibly easy this now makes documenting the functionality I’ve built.

I’m still considering how to make the code publicly available. I’m sure someone else would be happy to post it to CodeExchange, so perhaps I’ll let them.

ABAP Code Naming Conventions

Ok, you can probably guess that I’m not the most conventional person. I probably don’t fit the mould of the stereotypical developer either. I’m certainly not what one would call an introvert.

So please take this with the necessary pitch of salt. (especially if you’re one of the people who writes the code naming conventions that I have to follow from time to time 😉 )A pinch of salt required

<rant>

Why on earth does every SAP project I go to insist on such inane naming standards for the code? The SAP editor is a wonderful IDE (caveat I did not say it was the best IDE) that allows you to see the definition of any variable with a simple double click – so why on earth are you so worried that I should prefix all my local variable definitions with an ‘l’? What on earth potential benefit can this have on the code readability? Perhaps it helps if you’re still one of my nemesis developers who are passing all your variables between methods through the use of global variables and/or singletons. Perhaps one needs to look at a piece of code, see lots of l’s and that gives satisfaction? The use of Hungarian Notation in ABAP code seems to be universal, although never it seems implemented in the same way.

Then when I define a structure, I must prefix it with a “S” just so you can be sure that it isn’t actually a table or a single field, or so help me, a woolly mammoth. When I look in the IDE view of the package I am developing, all of these different things are arranged in a tree so you can easily tell one from the other. Again a single double-click can bring me to the definition if it is ever referred to in a piece of code. Perhaps it might save some time looking at a variable definition to see if it is a table, a structure, object reference or a variable – but if I’m in the code, it should be pretty damn obvious! If I’m appending or inserting into it, it’s a table. If I’m referencing a sub-field of it, it’s a structure. If I’m assigning a value to it it’s a variable, if I’m creating an instance of it, it better be an object reference. There again may be cases of my nemeses developers still using tables with header lines and confusing the heck out of me. But I’m hoping that the code inspector might weed at least that out.

Searching outside of the SAP world the use of Hungarian Notation within code is not universally disliked, but with such a clear list of disadvantages and such luminaries as Uncle “Bob” Martin and Linus Torvalds against it, you’d have to proclaim yourself a pretty die-hard supporter of “doing it the old way” not to just think a little – “is this really useful? Or is it even potentially bad?”.

Then there comes the requirement that every object should reference the area of use it is intended for. Thus the forth and fifth characters of the object name must be “HR” or “PA” or “XX” or whatever. The use of Positional Notation for implicit metadata about a component is, however not something I’ve seen outside of SAP projects except for the COBOL example given in the linked Wikipedia page. At this point when reading the naming convention guide, I casually check if there is any mention of packages and package hierarchies and hope upon hope, package interfaces. When there isn’t, I sigh again and just bite my tongue again. Because SAP has provided a wonderful way of helping us see what use a component is put to – as every component must belong to a package, and that package can (and should) have an application component defined. And to give even more clarity, the package can have a super-package, thus grouping all like component together, whatever types they are and where ever in their object names they have a ridiculous two character code. The package interface can even tell you if the object is safe for use outside of the package. What a great concept!

So instead of spending time thinking about whether the components we are building are truly reusable, and what the scope of that reuse is. We spend hours checking if we have the first n characters of our our objects correct according to the development standard book.

</rant>

One day someone will be silly enough to let me do it my way, I’ll confuse the bejeebers out of all the guys who’ve only been coding ABAP badly for the last 10 year and the project will potentially fail because I’ll spend my entire time looking for enough of a development team that can understand that following a rigid way of doing things isn’t always the best way to do it…. <sigh>