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

How New Debugger Saved my Day !!!

$
0
0

Recently I was working on a custom VOFM routine implementation. My functional counterpart was sitting with me and we had configured the routine by entering the key.

Now it is my job to implement the code. I was able to get the values available in the structure KOMKBV2 inside the routine. But he needed the values from other structures (say LIKP) to implement the custom validation.

 

The functional consultant sitting next to me was very keen now. He wanted to know how to retrieve the internal table / structure values which are not directly available from the userexit / BADI / Customer Exit interface parameters.

 

I need to explain him now

 

So I set a breakpoint in the VOFM routine. We executed the transaction and program stopped at the breakpoint in the routine which I had set earlier.

vofm_2.png

From the debugger, I started to loop back to previous program from the call stack. I showed him how to check the values of the internal tables & structures of the previous program which called the VOFM routine. 

VOFM.png

I told him that we have an option to use

 

ASSIGN ((<program name>)<internal table[]>) to <field symbol of that type>.

 

CONSTANTS : lc_likp TYPE char17 VALUE '(SAPMV50A)xlikp[]'.

FIELD-SYMBOLS:<fs_likp> TYPE STANDARD TABLE.

 

ASSIGN (lc_likp) to <fs_likp>.

 

Phew!!! I was able to read the value which he was interested. But now he started to fire questions at me.

 

“How to find all the internal tables which I can use by this way. How to find that???”

 

I managed to tell him that if a program a loaded and available in context, we can access the global variables of that program by the above method. But it is not advisable to read the data by this way, as SAP has the right to change logic of the program or name of the internal table in the future release. But he was reluctant to accept that.

 

“Okay!! Then give me the list of all programs which are loaded and available in context now. I need to know”

 

Oh God!! Please save me from him. I honestly don’t know, how to get the details of all program which were loaded right now.

 

  1. Idea..!!! I can activate a trace and execute the transaction. Collect all the programs names displaying in the trace log and give it to him. That’s a good idea…!!! But… how do I get the list of internal table names & its value. I cannot directly get those from the trace.

Without a hope, I was going through the options available in the debugger.  I noticed an icon with name “Replace Tool”. I hardly used that. I click on that and I got a pop up. It has many options coupled as a tree.  I expanded the tree “Special Tools”.  I was able to find “Loaded Programs (Global Data)”

replace tool.png

 

I doubled click that and the tool was giving me everything I wanted. “Thank God… You saved me ..!!!“

load_data1.png

It has two tabs Loaded Programs & Global data. From the global data tab, I was able to get the global variables, internal table, work area value. And the best thing was, I was able to search by CTRL + F based on the variable names. What else do I need..!!!

load_data2.png

 

After he left, I did a quick search on this feature in google. I was amazed to find the below two URLs.

 

https://help.sap.com/saphelp_nw73ehp1/helpdata/en/49/1ec3f1f3ee6492e10000000a42189b/content.htm

http://scn.sap.com/community/abap/testing-and-troubleshooting/blog/2011/07/14/news-in-abap-debugger-breakpoints-and-watchpoints-statement-debugging

 

Everything was explained in detail and I had never read / bookmarked it   First thing I did after that was to click on “Follow” and started following the updates on that space.

 

Thanks for your time to stop by and read this blog.

 

Regards,

Karthikeyan


A room with an ABAP CDS view

$
0
0

In Björn Goerke's keynote speech from Barcelona Teched 2015, you may recall that he had crash landed on Mars, and was attempting to escape mars with the help of all of the latest SAP tech available. One of the technologies that we took away from teched, and that Björn used in his keynote was that of the CDS view.

 

But what if Björn had crashed on Mars and was without a Hana DB? what if he hadn't upgraded yet to full blown Hana, but he wanted to prep for such a future eventuality. That is a similar situation to what I find myself in with my current employer. We have crashed landed too, but we are even further out than Mars... and we have no Hana DB, but can we prep in advance for HANA? perhaps by using CDS Views on our current Oracle DB.

 

Well it turns out that the answer is a qualified yes - you can run ABAP CDS views outside of HANA (provided that your ABAP system components are at a high enough level (we are at 740 and past SP8), and that your underlying DB is also at a high enough level (ours is). From Horst Keller's blog (views come in 2 flavours) we learned that CDS views come in 2 different implementations:

 

1) HANA CDS views (you'll never guess but these ones don't work so well on Oracle), can only be edited in Hana Studio.

2) ABAP CDS views - these can be defined and edited in Eclipse and do work on Oracle, and other non SAP DBs too!

 

So then its time to see if the ABAP CDS views can help me in my escape from my own predicament, remember we have crash landed on Enceladas which as you can see is a moon of Saturn, this is the view from my room on Enceladas of my broken buggy:

saturn_rise.jpg

 

To be able to make it back to earth we must repair our rover, and for this we need to order a space suit from Earth, to be delivered by NASAFEDEX.

 

To place the order we must be able to construct a view of three tables in our ABAP system, these tables are MARA, MAKT and MARC, they contain the details of the spacesuit, that we need to get to and repair our rover, which can then call our spaceship to escape the dreaded Enceladas!

 

So without further ado lets jump straight into Eclipse and build the CDS views to get us the hell out of here!

To create an ABAP CDS view I simply login to Eclipse, choose File->new->other and then choose DDL Source from the pulldown list.

 

The ddl source is a new syntax that lets you define in detail your new Core data services view. It is important that the data dictionary name you provide for the view (in red ring below) is not the same name as the ABAP CDS view name (in Green ring below).

 

Here we select our material, the material description, and also some sizing and extra descriptive data. We are then specifying in the where clause that we want all of the descriptions in English (as we have lost our babel fish in the crash landing) and we are only interested in data from site 0114 (thats the closest site to the European space terminal) and that we want extra-large size 005 (as we ate too much Enceladas and Xmas pud!).

For the low down on CDS syntax and features please take a look at Chris's great blog here.

 

cds_view_noparams.jpg

So really the view is defined as a select statement, defining the join conditions (on matnr above), the fields you want returned (matnr, maktx, ernam, mtart, matkl, size1 and werks) and the where clause.

 

Now we need to get the data out of our CDS view and to do this we must write a few lines of ABAP:

 

REPORT zjsp_cdsview_basic.

 

* Our class for ordering our spacesuit

CLASS zcl_jsp_space_clothes DEFINITION FINAL.

 

  PUBLIC SECTION.

 

    TYPES:

      BEGIN OF tp_spacesuits,

        matnr TYPE mara-matnr,

        maktx TYPE makt-maktx,

        ernam TYPE mara-ernam,

        mtart TYPE mara-mtart,

        matkl TYPE mara-matkl,

        size1 TYPE mara-size1,

        werks TYPE marc-werks,

      END OF tp_spacesuits.

 

    TYPES:

      tp_spacesuits_tty TYPE STANDARD TABLE OF tp_spacesuits.

 

* its a factory class, for syntactical convenience (did you know you can create Factory classes easily

* with the CTRL-1 assist options in Eclipse!)

    CLASS-METHODS create

      RETURNING

        VALUE(r_result) TYPE REF TO zcl_jsp_space_clothes.

 

    METHODS:

      main.

 

  PRIVATE SECTION.

    DATA:

 

* This attribute when filled will contain the spacesuit that we can then order

      mt_spacesuits TYPE tp_spacesuits_tty.

 

    METHODS:

 

* Here we define the method that will read our spacesuits from the underlying tables

     cds_read_space_clothes_np

        EXPORTING

         et_spacesuits TYPE tp_spacesuits_tty,

      display.

 

ENDCLASS.

 

CLASS zcl_jsp_space_clothes IMPLEMENTATION.

 

  METHOD main.

* read the space suits

    cds_read_space_clothes_np( ).


* display the results

    display( ).

  ENDMETHOD.

 

  METHOD create.

   CREATE OBJECT r_result.

  ENDMETHOD.

 

* Here we are calling our ABAP CDS View note the view select is not so different from a regular

* open SQL select, one difference is that ABAP variables are passed with @ symbol, there are other syntactical

* differences for more complex selects, but the syntax is very easy to pickup if you are familiar with open SQL.

 

  METHOD cds_read_space_clothes_np.

    SELECT * FROM zlo_mar_cdsvw_2

              INTO TABLE @et_spacesuits.

    mt_spacesuits = et_spacesuits.

  ENDMETHOD.

 

* Here we can display our selected data, which will simultaneously be transmitted to NASAFEDEX,

* thanks to an additional ALV control that NASA have kindly added for us (not covered by this blog)...

  METHOD display.

    cl_salv_table=>factory(

       IMPORTING

         r_salv_table   =  DATA(lv_alvtable)

      CHANGING

        t_table        = mt_spacesuits

 

    ).

 

*      CATCH cx_salv_msg.    "

   lv_alvtable->display( ).

  ENDMETHOD.

 

ENDCLASS.

 

START-OF-SELECTION.

data gv_runmode type char1.

 

 

 

* Instantiate our class and run our main method

 

  zcl_jsp_space_clothes=>create( )->main(  ).

Now its just a matter of executing our CDS view in ABAP on an Oracle DB:

spacesuitselection.jpg

So as you see it is possible to run CDS views from ABAP with an Oracle DB backend - and thus to be able to escape Enceladus.

In fact I think I hear my spaceship landing to come and rescue me!

ship_rescue.jpg

What we can take away from all of this is that CDS views can be used from a non HANA DB, just as long as your DB and ABAP version are at a high enough level.

But why would you do this unless you are marooned in space? well for one thing, you could create CDS views for heavy duty select statements, in preparation for a future migration to a Hana DB.

During Barcelona Teched 2015 I was assured that the CDS views should perform considerably faster than their equivalent SQL statements even on Non Hana DBs, but more about that in my next blog - A kill to an ABAP CDS View...

That's all for today, if you have any comments or views about any of the above please get in touch with me in the comments section below.

Stardict/GoldenDict Dictionaries for ABAP fields and tables

$
0
0

Dear everyone,

 

As functional consultant, I usually work with functional specs.

My task is to review functional specs.

 

Also, my favorite dictionary is Golden Dict, which is a successor of Stardict - a very popular open source dictionary software.

 

So I create 2 dictionary for my need to validate all content in documents.

First dictionary is table definition, which give you table name.

 

Second dictionary is field definition, which give you field name, and some field attributes.

 

When I press "Ctrl+C+C", definition of the highlighted table/field popup.

This utility enable me to work on document without open SAPGui to lookup for field/table definition.


You can see attached file.

 

If you are using the same dictionary software(stardict, golden dict, or any report that support stardict format) I would like to share with you the dictionary files.

Follow below link and download the files.

Microsoft OneDrive - Access files anywhere. Create docs with free Office Online.

FALV -> Fast ALV Grid Object

$
0
0

Finally I've finished to work under FALV. You can find FALV classes in attachment and description under the links. But firstly let's go through few following points:

 

  1. Why I've created FALV although SALV classes are provided by SAP?

    I know SALV classes although I haven't used them often. The main reason was that they don't provide edit mode. So at the end I've always worked with cl_gui_alv_grid class so then whenever users decided that they need one of the field to be editable then I can do it in few seconds/minutes.


  2. But there is a way to make SALV editable!

    Yes, I know the solutions of Naimesh Patel (found here) and Paul Hardy (in his ABAP to the Future book) and some other folks to make SALV editable. But In my own opinion, especially when you're at least on 7.40 with SP5 making SALV editable is not needed as you can fast create ALV Grid which does everything you want. To be clear the big advantage of SALV, to call grid output of table in two, three lines when you goes to the code you'll see it's nothing more than call of REUSE_ALV_GRID_DISPLAY... really old FM, which at the end use CL_GUI_ALV_GRID. And yes I know about new SALV class for HANA, but that is another story...


  3. Direct reasons

    As I used CL_GUI_ALV_GRID so often then I came up with an idea to do some class which will make the creation faster, but I never had time to do it at work. You may know it, because of the time pressure you choose to create report/program/solution in the way you're doing from years ... and then comes another task....and another....

    So I've decided to do it at home.... yeah I'm crazy. But at least some of you can also use it.


  4. Advantages

    • Fast CL_GUI_ALV_GRID creation
    • Replacement of REUSE_ALV_GRID_DISPLAY and REUSE_ALV_GRID_DISPLAY_LVC for a simple editable reports to omit screen creation
    • All events are already handled and with redefinition of method I can faster use it
    • Faster setting of layout and field catalog attributes
    • Easy switch and copy between popup, full screen and container version
    • Easy toolbar handling (in grid and in full screen/popup using Dynamic GUI STATUS & TITLE with ABAP code )
    • One place to handle user commands of full screen/popup call -> event user_command

  5. Prerequisites

    I've worked on this on 7.40 SP8 but this should work also on SP5 as well. Sorry for the users bellow that versions but I'm so used to use new syntax that I couldn't force myself to use old way of coding.

  6. Source code

      Always updated source code in NUGG files and examples of usage will be available on my blog -> abapblog.com/falv . Bellow you can find some example videos with usage of FALV.



I really encourage you to try it and give me your feedback about FALV.


 

 

 

 

 

 

Cheers

Łukasz

System Landscape for Add-On Development

$
0
0

This is the second part of my answer to Christian Drumm's question What System Landscapes Setup to use for Add On Development? - and probably more of an answer to the original question than the first part. At the moment, many authors choose to place obscure references to Trifluoroacetic acid (or TFA for short) in their blogs, but since this post will be about rather fundamental aspects, I'd like to choose a different setting.

 

ABAPDevLandscape-B5-Vorlon.jpg

 

When thinking about software delivery and usage, it is a good idea to start with a rather simple model of provider and consumer. Separating these roles clearly makes it much easier to describe the requirements and expectations of the parties involved. I'm well aware that in the real world, the distinction between provider and consumer isn't necessarily that sharp. However, any intermediate role definition will likely contain aspects of a pure provider as well as a pure consumer - and, as you'll shortly see, complexity has a way of increasing, even with some simplifying assumptions in place. Also note that I'm leaving SAP out of the picture - one might describe SAP as "infrastructure provider", and that role in itself opens up a whole new universe of complexity.

 

So, to answer the question: let's assume we are on the provider side for now - the consumer will have to wait for yet another blog.

 

ABAPDevLandscape-B5-Morden.jpg

Make money, what else? To do so, we need to deliver our solution to the consumer, and that solution contains some ABAP-based software - otherwise, following this would be quite pointless. We're not using the software ourselves, we're just providing it to more or less anonymous customers. (This is actually important: it's a good idea to assume you know nothing about your customer's implementation details, since that will save you from dangerous assumptions with unpleasant consequences.)

 

Many details of the actual system landscape will depend on a number of decisions that are specific to the solution we want to provide. So, before defining the development and delivery process, we need to be able to answer a few questions:

  • What are the dependencies of our solution - thinking in software components? SAP_BASIS certainly, but what else do we need? ERP? HR? CRM? What are the requirements of these dependencies? Which versions of the dependencies will we have to support?
  • Which technologies are we going to use? Will we need to take special provisions for any of these?
  • What kind of release and patch cycle are we planning for? How many concurrent major versions will we have to maintain? (Hint: Choose an odd number below 3 if possible.)
  • What non-technical external factors exist that will have an impact on our release schedule? Will we have to follow legal changes and/or deliver on fixed dates to allow our consumers to meet regulatory deadlines? Will our customers have to update regularly anyway because of legal requirements - and if not, can we convince them to do so anyway or will we have to support ancient patch levels of our software?

 

Obviously, we can't answer these questions in detail for the hypothetical provider we're considering right now, but the implications of each decision should become clear during the course of this discussion.

 

We won't be discussing general good practices of software development like unit testing, integration tests, documentation and the like here. These aspects are of course very relevant to producing a stable, maintainable product, but we'll assume our developers know about that and won't need to be reminded times and times again. However, we need to remember that we need a working environment for many of these tasks, and that includes both the correct versions of our dependencies as well as a usable configuration. How will we need to configure the dependencies before we can start building our own software, and what configurations will we need to test the various ways our customers might use the software? Again, we can't answer that for a hypothetical solution, but you get the idea - there are some rather time-consuming activities lurking in the dark of an unanswered question.

 

For the following discussion, I'll assume that we'll use the Add-On Assembly Kit (AAK) to deliver the ABAP software components. If you're not entirely sure why, you can find my personal view on this topic here. It certainly doesn't hurt to know in detail how the AAK works, but we don't have time for that, so here are the basic ideas you need to understand the following discussion.

  • With the AAK, you deliver software components (think table CVERS, SAP_BASIS). Physically, you'll ship a SAR archive that contains a PAT file which in turn contains the actual package files (starting with SAPK-). If you think of these packages as transports with additional functions on top, that'll do for now.
  • You're free to use transports within the system landscape. At some point, you gather all the stuff you want to deliver in a central location (system) and perform your unit and integration tests (not covered here). Then, you decide what exactly is to be shipped, perform some additional checks and create the package files. This happens using the so-called Software Delivery Composer (SDC) and results in the SAPK files.
  • The package contents are then turned into deliverable PAT files using the Software Delivery Assembler (SDA). In this step, dependencies and other attributes are added to the package files to produce PAT files. The PAT file names consist of the assembling system ID, installation number and a sequential number.
  • The SAR files have to be packaged manually (or using some custom program). These are just archives that can be uploaded and installed more conveniently by the customer.
  • The AAK is able to produce different kinds of packages for different scenarios that our customers might encounter. The most important ones are packages for initial installation (contains the current versions of everything), upgrade (only contains the changes), release upgrades (similar, but including release-specific changes) and patches (bug fixes, no new objects).

 

But enough of the asides - the question still is not answered: What do you want?

 

  • If you're a developer, you'll want to spend as much time as possible working on cool new stuff without that pesky delivery infrastructure getting in the way.
  • If you're responsible for testing and support, you'll want a dedicated system for every supported combination of versions and patches (and probably even separate systems for Unicode and NUC as well) for instant testing capability and full coverage of all possible installation scenarios. You'll want to find the ugly bugs before the software is delivered, and if systems needs to be broken at all - well, better not use the customer's systems.
  • If you're the CEO, you want as few systems as possible. These things don't come for nothing, you know?
  • If you're a responsible CEO, you'll want whatever is required to deliver the quality and performance the customers request - but nothing more than that.

 

And if you're the delivery manager, sitting right in the middle...?

 

ABAPDevLandscape-B5-Zathras.jpg

 

Nononono, not so fast. You're responsible for getting our software to the consumer in one piece and without damaging our (bad) or their (VERY bad!) system, so you'd better step up on the understandings.

 

AAK-based delivery requires at least one delivery system for each SAP_BASIS release supported. We won't exactly need a separate delivery system for each patch level, but if significant changes happen (think 7.40 SP 05), different delivery systems might be required. That is, unless we can either postpone the installation of that patch in our delivery systems until all customers have that patch level installed (e. g. because it's part of some SP stack that contains legal adjustments) or simply raise the system requirements we impose on our customers. Similarly, if different releases or sufficiently differing patch levels of our dependencies (like ERP or CRM) are required, different test and delivery systems might be a good idea - but more about that later. (Remember the initial questions? As you see, it starts to get fuzzy, and we haven't sketched a single system landscape yet.)

 

Now what's a delivery system in this context? It's the source system of the technical installation packages - this is where the SDC stuff happens, and the SAPK package files get exported from here. It's usually a bad idea to deliver from the development system - or rather, to actively develop within the delivery system. If we allowed that, we'd probably have to lock out all the developers during a delivery process - or risk someone carelessly breaking the assembly process. Also, a development system usually contains local test objects, internal tools and more often than not some rather imaginative customizing introduced by the developers to reproduce some strange condition or try out a new feature. We don't want that ending up in our installation package, and we don't want anything in our installation package to accidentally depend on any of that stuff (think of a data element /FOO/BAR that is to be delivered, but still depends on a domain in $TMP).

 

The usual and indeed most simple answer to that is to separate at least the development from the delivery and have different systems for that. A reasonable approach would be to combine the test and delivery environment in one system (but use separate clients for testing - that also allows for different testing environments). Developers develop and release transports as usual, and these transports are imported into the delivery system. Whenever a delivery is required, you'd impose a transport / import freeze on the delivery system, perform the tests and compose the packages, while the developers can keep on coding in their separate development system. This also has the advantage that transports can be used to collect and group the objects that have changed and need to be delivered.

 

When assembling the PAT files during the delivery process, you will have to enter some additional conditions and prerequisites that will be contained in the delivered software and checked during the installation. It goes without saying that anyone can - and given enough time, will - make mistakes, so it's very sensible to double-check these import conditions by performing a test installation. (It's also mandatory for the certification which is in turn mandatory to get the AAK.) We will also want to check various different upgrade paths (will these fancy data migration tools actually work?) and probably provide an estimate on the total installation time. Now obviously, we can't use either the development system or the delivery system for that, since our software component already exists there and we don't want to break anything. No, we need a "vanilla" system that we can use to perform a test import. This had better be a virtualized system so that we can take a snapshot, perform the test installation and then revert to the saved state. Frequently, we will want to perform at least two test installations (fresh installation and upgrade from the latest version), and in some cases, it might be good to have systems with various releases and patch levels available for testing. These systems are usually not customized at all, and no functional testing takes place there - that should have happened before the delivery to keep the number of delivery iterations small. Also, with the number of installation test systems rising, it becomes a pain in the a...natomy to keep them all updated and customized correctly. These systems are simply targets to verify that we've produced an installable package.

 

So now that we have a basic understanding of the systems we need, let's see what that landscape will look like:

 

ABAPDevLandscape-Diagram1.png

 

Now this looks nice and compact, but don't hold your breath - we're not quite finished yet. First off, there's a slightly less-than-obvious problem regarding the maintenance of our solution. Once the delivery of, say, version 3 has been completed and customers are busy installing the new software, the developers in turn will start to work on new features in preparation of version 4. Thus, once transports from D01 to A01 are enabled again, the delivery system won't stay in the state that was used to assemble the delivery for very long. Since the delivery system no longer resembles a hypothetical customer system (and it might even be occasionally broken while development is still ongoing), it is no longer possible to reproduce issues or test fixes with the exact same software that the customer has installed. That's bad, especially if some particularly nasty bug escaped our collective attention during testing. How can we prevent this?

 

The obvious solution would be to not import any transports until right before the delivery date. However, that's generally considered a bad idea, since lots of issues are usually identified by transporting and importing (e. g. missing dependencies, accidentally $TMP'ed objects and other basic errors), so delaying this is not desirable. Also, sometimes one needs to release transports for various reasons, so a queue of transports might pile up. Having to fix broken transports weeks or months after they have been released might throw a spanner right in our delivery schedule. So what's the alternative if we need the capability to continuously support older versions of our product? Yup, another system - or another line of systems. These maintenance systems will usually be copies of the delivery system that are already fully customized for tests. Every time a new version is released, a copy of the delivery system is used to create a new maintenance system, and once a legacy version is no longer supported, the maintenance system is shut down.

 

These maintenance systems also have another use. As the saying goes, after the release is before the release - the development continues, new features are invented and transported, virtual trenches are dug and stuff is prepared to be reworked, refactoring is happening all over the place. The development team is happily hacking away, until - a bug. It needs to be fixed - and fast. However, the objects affected by the bug are already in a different state than the one that was delivered, and they are no longer compatible to the old version. And even if that particular part of the software was not affected, the entire product might not be in a usable and testable state right now. Obviously, we can't use our development system to produce the fix. Again, the maintenance systems saves the day: The developers can implement a fix in the maintenance system and test it there, and we can deliver a patch from that system. Note that to implement the fix, the customer will either have to import the latest patch, or implement the correction manually - there's no note/correction support for 3rd party products that I'm aware of.

 

ABAPDevLandscape-Diagram2.png

 

It should be noted that, under certain circumstances, it is possible to work without maintenance systems. Whether we can use this approach basically depends on stability of our software (or rather the lack thereof) and the time-criticality of the fixes we might need to deliver: If our software stays relatively stable most of the time and/or consumers can tolerate longer wait times, we can trade in development flexibility for system landscape simplicity:

 

ABAPDevLandscape-Diagram3.png

 

As you can see, during active development and testing, no patches can be released, and customers always need to upgrade the entire software to get the latest patches as well as functional upgrades that they might not be interested in at all. While this might be a perfectly reasonable approach for some situations, it might prove utterly useless for other situations.

 

So far, we have only considered one active development stream with occasional fixes to the previous version. Theoretically it would be possible to release version 1.0 and start maintaining it, then start work on improving (not just fixing!) the software producing a line of 1.x upgrades while at the same time starting work on a completely new track, producing version 2.0. This might sound like a good idea, but in practice, it rarely is: The ways to screw up increase exponentially, and it increases development complexity and testing effort a lot - not just for own development and testing personnel, but also for our customers. This approach rarely provides any business advantage for either the provider (that will be us) or the consumer (that will be the ones that will - or won't - be paying us). A true ?REDO FROM START is rarely needed, and from my experience, we'd be best off treating this situation as "we're starting an entirely a new product under a different name that has a different code base and does not depend on the old one". So, no boom.

 

ABAPDevLandscape-B5-Ivanova.jpg

 

Pessimistic though this approach may be, it does have its merits. Because - well, we're still not there yet. So far, we have only considered the versioning and maintenance of our own solution. As we've already stated in the introduction, we'll usually need to provide software for more than one target release. To simplify the situation, let's focus on the SAP_BASIS release, since that's what the AAK requires anyway, although the same scheme might also apply for other dependencies. Again, resolving this situation requires the use of multiple delivery systems and installation test systems, but with a different pitch: We're now trying to produce the very same software (including patches) for different platform versions. Simply multiplying the development systems as well will get the developers to launch pointy objects in your general direction, so that's not an option. So - can't we just centralize the development system? We can, but that leads to another question: What's the baseline?

 

At this point, we need to take a short detour and think about transporting up and down the stream - that is, transporting development objects to a higher or lower target release. Transporting "up" is usually possible and not very problematic - stuff developed on lower releases will usually just work (at least technically) in higher releases. So, a SAP_BASIS 7.02 development system supplying objects to a 7.40 delivery system is usually not a problem. We might therefore choose the lowest target release we need to supply our product for as the baseline. However, this limits developers to relatively old version of the development environment (e. g. it might restrict them from using ADT). While this certainly is not favorable, from my experience, many developers tend to tolerate that if they understand the perils of the other option: Keep the development system on the highest release supported and transport objects downstream. This is not supported officially and liable to break - both technically during the transport process as well as within the coding itself. From a technical perspective, newer releases usually contain more options, larger database tables, more sophisticated tools - and transporting objects made with these new tools that already have some of the new options set and additional fields filled to a lower release that doesn't have these options and fields might have any of a number of undesirable side-effects. As for the coding - imagine a developer using the fancy new operators introduced with 7.40 SP 05 on the development system, only to find out that these won't work on the lower releases. Or imagine someone using a cool new class to create UUIDs, random numbers or some other API that doesn't exist on lower releases. This is not fun at all. SAP actually works that way, developing on the new release and then down-porting functions if necessary, but SAP does have other tools and more sophisticated system landscapes (and a lot more people!) at hand. Smaller development shops don't have that option and are usually better off with up-porting, even if that restricts the toolkit available to developers - so we'll go with that option.

 

Now let's consider the software itself. No product is an island - there are always connections with the platform and surrounding components. The question is - does any of these connected components change across releases in a way that forces us to write our software differently on different releases? If that is not the case, if our software stays the same on all target releases, that's good: we only need one development system, supplying transports to multiple delivery systems. At greatest need, small patches required for individual target releases might even be implemented in the delivery system.

 

ABAPDevLandscape-Diagram4.png

 

However, if this is not possible because the software needs to be adapted substantially depending on the target release, it's a good idea to organize our software to separate release-independent parts from release-dependent ones. In this case, it also pays off to add release-dependent adaption systems between the central development system and the delivery systems.

 

ABAPDevLandscape-Diagram5.png

 

Additionally, in order to allow the developers at least access to some of the newer technologies, it might be an option to place a "cut off" point at some release: On any release below that, consumers get maintenance fixes only, but no new features or other active development happens on the legacy releases. This will allow us to raise the baseline release, at least a little.

 

ABAPDevLandscape-Diagram6.png

 

Finally - we're almost there, hold on - there are two more systems. One that's probably required: As far as I know, you need a Solution Manager installation in order to install and maintain the system landscape. Unfortunately, I know next to nothing about the Solution Manager. What I do know that it might be beneficial to add yet another system to the landscape that is used to centrally assemble the delivery packages (the SSDA step that turns SAPK files into PAT files). There are a number of reasons that might be a good idea:

  • It's very handy to have a single system that knows about all of the packages, e. g. to populate download portals or other delivery software.
  • If delivery systems get added and removed periodically, package detail information might get lost. If that information is kept in a central location, there's no danger of package data becoming unavailable.
  • All PAT file names contain the SID of the system that created the file. For the customer, it's more consistent if there's only one system name appears in the delivered files.
  • Package assembly and attribution is somewhat tricky - you wouldn't want the average developer to mess around with the package attributes.

Also, that system might be used as the TMS domain controller, to provide a central user administration (CUA) landscape or to produce the roles that are then distributed throughout the system landscape.

 

Okay - now that we've collected all of the puzzle pieces, let's put together a system landscape for a single-stream product development. Let's assume that we'll need to apply non-trivial adaptions to the target releases we provide software for, and that we need to maintain and produce patches for the last two versions we released. We'll need to actively support SAP_BASIS releases 7.31 and 7.40 with 7.31 as our baseline, while maintaining the infrastructure to provide patches for out legacy 7.02-based versions. While we're at it, we might already prepare the plans for adding the new 7.50 release to the landscape.

 

ABAPDevLandscape-Diagram7.png

 

Now isn't this nice? 21 systems and counting, not including the SolMan...

 

My key points:

  • You need a clear understanding of your customer's expectations and technical limitations to decide on the best possible strategy and system landscape layout.
  • You also need a competent basis administrator (who is NOT billing by the hour!) and/or someone with combined administration and development skills in-house to maintain and optimize the systems.
  • Trivially, you need funding for the system landscape. As far as I know, SAP will license by development user, not by system, but you need the infrastructure anyway.

As a reward, you get the ability to deliver and maintain ABAP products with high quality standards and reliable, verified delivery processes while keeping customer risk and effort relatively low.

 

As always, careful planning and a lot of thought beforehand is in order:

 

ABAPDevLandscape-B5-GKar.jpg

Output Type driven forms to Application Server

$
0
0

Requirement - The business may need a PDF output of any forms to be available for the legacy systems, So we may end up in copying the standard driver program and addition of logic to save the pdf output in application server.

 

Solution - SAP has already provided a program RSNAST0D to process Generic Output type. Which generates a spool number and from this we can use the function modules CONVERT_OTFSPOOLJOB_2_PDF or CONVERT_ABAPSPOOLJOB_2_PDF based on the Object Type of the spool to get the PDF content and write this content to the file placed in the application server

 

Selection Screen of the program RSNAST0D

 

Based on the selection criteria, user can enter any Application, Output Type to get the list of output available for processing, Select the row and issue the output will generate the spool for you.

 

Using this spool number, further we can make use of the explicit enhancement point to write the additional logic to retrieve the PDF contents using the above mentioned function modules and convert the PDF content to BINARY format.

 

Following screenshot shows the conversion of PDF content to BINARY format and then transferring the data to file.

 

Necessary Actions to reuse the functionality

Since the Implementation of the enhancement spot ES_RSNAST00, triggers all the time when an output is issued using any other transactions. To restrict this you can check whether SY-CPROG is always RSNAST0D or check the SY-TCODE assigned to program RSNAST0D.

 

Note: If there is a requirement to save PDF output to Application server whenever an output type 'XXXX' is issued, then use the static attribute flag of the class to mark as 'TRUE' in the Print program or driver program or the interface and then use this flag to trigger the Implementation of the enhancement spot ES_RSNAST00.

Simple Report Screen Validations - a small 'Gotcha'.....

$
0
0

When you write a report you should as a matter of course validate the input that the user has provided to make sure that the request thay have made is at least sane.

 

This validation generally takes place in the "AT SELECTION-SCREEN ON parameter" event where if the value in the parameter is incorrect in some way and an error message is displayed the relevant field is highlighted and made ready for input again.  The processing of the report is stopped at that point.

 

One of the things to check for is that a parameter is populated and this can be done automatically using the 'OBLIGATORY' clause of the ‘PARAMETERS’ statement,  however,  when the selection screen is interactive,  this in itself can cause problems.

 

An interactive selection screen could for example have a series of radio buttons that diefine different aspects of the report,  and selecting a specific radio button means that a specific parameter should be used.  Rather than keep all these other fields visible I tend to put a user-command function on the radio button and then in the AT SELECTION-SCREEN OUTPUT event hide those fields that are not relevant to the current radio button state.  With the ‘OBLIGATORY’ parameter set on other fields this process is interrupted when a mandatory field is not populated leading to incorrect information or fields being displayed.

 

Also,  I am of the opinion that checks should not happen until the user has made all their entries and have clicked the ‘Online’ button.

Something like this:

 

At Selection-Screen On p_Matnr.
*
   Data: l_Count Type i.
*
   If sy-UComm = c_Ok_Online.
      If p_Matnr Is Initial.
         Message E018.
      Else.
         Select Count(*)
           Into l_Count
           From Mara
          Where Matnr = p_Matnr And
                LvOrm = Space.
         If sy-Subrc <> 0.
            Message E007 With p_Matnr.
         EndIf.
      EndIf.
   EndIf.

 

This checks to see if the material number is populated and that it is valid.  If not an error message is issued.

 

This type of code though has a little ‘Gotcha’.  I don’t know about you,  but If I have to correct an erroneous field,  I make a new entry and then rather than clicking the ‘Online’ button again I hit the ‘Enter’ key.  This then re-validates the fields and processes the report….but hitting the ‘Enter’ key sets sy-ucomm to initial and the validation code is not run.  This means that if I entered an invalid material number again it would not be picked up – as would any other field with an invalid entry.

 

Now you say “But users would always click the online button” in which case the code would always work,  but I would say “Well – there might be others like myself who do otherwise”.

 

The fix is simple – keep a copy of the previous function code and if the current code is initial use that instead:

 

At Selection-Screen On p_Matnr.
*
   Data: l_Count Type i,
         l_UComm Type UiFunc.
*
   If sy-Ucomm Is Not Initial.
      l_UComm = sy-UComm.
   Else.
      l_UComm = g_UComm.
   EndIf.
   If l_UComm = c_Ok_Online.
      If p_Matnr Is Initial.

         g_UComm = sy-UComm.
         Message E018.
      Else.
         Select Count(*)
           Into l_Count
           From Mara
          Where Matnr = p_Matnr And
                LvOrm = Space.
         If sy-Subrc <> 0.
            g_UComm = sy-UComm.

            Message E007 With p_Matnr.
         EndIf.
      EndIf.
   EndIf.

 

Set the value of g_UComm prior to issuing an error message.

Three ABAP Games

$
0
0

Look what I've found.

 

Under the cloak of "Examples of Expression-Oriented Programming" recent versions of the Example Library of the ABAP Keyword Documentation contain three ABAP games.

 

Jaw Breaker

jawbreaker.gif

 

Not too demanding but colorful ...

 

 

Mine Sweeper

minesweeper.gif

 

Time-honored and well known ...

 

 

2048 Game

2048.gif

A recent smart phone game and a real challenge ...

 

 

Wanna play?

 

 

  • If you have a release older than 7.40, you can copy old fashioned 7.00 source code from the appended text file. Maybe you also have to replace the usage of CL_DEMO_INPUT with PARAMETERS then.

 

Only outside working hours, of course.

 

Wanna Contribute?

 

Maybe, the pattern used in these games (usage of CL_ABAP_BROWSER etc.) motivate you to create some other games?


Translation in Adobe forms using JavaScript with different types of allignment

$
0
0

Few days back we found a serious problem regarding Translation of the Labels of all the forms we were working on. The pressure came from the functional. As per there requirement they want to update a table(Constant table) and they want to reflect the changes in the adobe forms. Then things are getting little challenging. One of my senior created an method to fetch all the Translation details for any of the form. We were passing the values through the context of the forms. She created a structure with 200 fields. Among those fields anybody can pass max of 200 fields to a structure for translation. For our forms the number 200 was little high. Anyways after that we follow the below steps and successfully displayed the caption of the fields dynamically as per the system language.

 

 

this.resolveNode("this.caption.value.#text").value = data.Page1.Translations.FIELD_001.rawValue ;

 

The bold one is the field which contains translation and the italic one is the subform in which we wrapped the fields which contains translation.

 

Now the problem begins. Some of the field text needed to be like this as shown below.

trans.png

  

Case A: For this case the caption is needed to be right aligned. The initial spaces may varies for different languages.

  • First calculate the total no of letters may fit in that field A. Say it is 50 char.
  • Then create an global field named 'i' set its value as 50 spaces. Goto Edit->Form Properties->Variables. Click on '+' and set the value as 50 spaces. It may change for other fields.
  • Then write the following code.

var label = 0 ;

var i_val = 0;

var i_len = 0;

var label_len = 0;

var space_len = 0;

var space_app = 0;

label = data.Page1Translations.FIELD_001.rawValue ;

i_val = String(i.value); ...................................................  " For spaces

i_len = i_val.length; ................................................... " Checking the space length

label_len = label.length ; .................................................... " Checking the label length

space_len = Number(i_len) - Number(label_len); .................................................... " finding the no of spaces have to be appended to a field labels

space_app = i_val.substring(1,space_len);............................" actual required spaces

 

  1. this.resolveNode("this.caption.value.#text").value = space_app + label; ..........." Concatenating and displaying the labels..

 

Thus we achieved our requirement. Now I thought how to fulfill the next requirement...

 

Case B: I created another global variable named 'NXT_LINE' and set its value as 'enter'. (That means in the value I pressed only enter.. )

 

Then wrote the same code as before just passed NXT_LINE instead if 'i'. In the output it came like field B only.

 

At last the things are done with the forms. Then I started to write this document. Suddenly senior came and stood behind me and watched what I was writing.

I realized somebody behind.. Heard a little tough voice "Enough blogging something I have regarding MIGO tcode"... 

 

If any improvement is needed in this technique then please don't forget to write. The main implementation of this technique is to display the caption with your required alignment.

Change the color of the cell in the Spreadsheet XXL download

$
0
0

In SAP sample ALV report BCALV_GRID_01, when the output is downloaded into spreadsheet XXL format. Colors appear for the key rows and column headings with default color.

 

In this blog we are going to see how to change those default colors to user defined.

 

Go to transaction SE38, execute the report BCALV_GRID_01. Click on Export --> Spreadsheet --> XXL --> Table --> Microsoft excel.

 

4.jpg

5.jpg

 

5.jpg

 

5.jpg

 

The output below has default colors in the rows and columns as below.

 

5.jpg

 

These colors are defaulted or hard-coded in the system as in the below report.

 

2.JPG

 

The system looks for the user defined colors from table COLORSEXC, if there is no user default then it uses the default color codes 12 and 36.

 

Lets try by maintaining the table COLORSEXC to use the user defined colors.

 

Refer to the below link for the color codes used in excel.

 

Color Palette and the 56 Excel ColorIndex Colors

 

We will use color code 32 and 34.

 

2.JPG

Now execute the report again and download it into XXL format as explained earlier and it downloaded with the user defaults colors maintained in the table.

 

2.JPG

WYSIWYG HTML Editor

$
0
0

I was lately trying to find an HTML WYSIWYG editor for ABAP, but I failed. I though or this was not needed so far, or the solution was not posted anywhere. So I've tried several times and thanks to NICEdit and this tread on SCN I found the way to make HTML WYSIWYG editor for ABAP.

 

My editor use CL_GUI_HTML_VIEWER to display NICEdit in container, and then thanks to POST method I put changes back to SAP. ZCL_HTML_EDITOR class,  raises an event whenever someone click on save button in the editor, so you can easily handle it and then use new HTML for your purposes. Video bellow shows the demo of usage.

 

 

 

NUGG with class and demo program + HTML file with editor can be found here http://abapblog.com/articles/tricks/103-wysiwyg-html-editor-in-abap

 

 

Enjoy!

How to get the new ABAP editor in LSMW

$
0
0

SAP LSM Workbench (LSMW) has for years been a much used tool for data migration into SAP. It is both loved and hated :-) While LSMW has had its last update in 2004 it remains a much used tool in this age of more modern toolsets such as SLTSAP DS and the like.

 

For many frequent and hard core users of LSMW a big nuisance is the old style ABAP editor. This old editor takes up alot of development time, especially in those ABAP-rich LSMW projects.

 

One night, bored and out of beer, I managed to develop a relatively simple enhancement that enables the new ABAP editor for LSMW.

(Mangled code completion context list is thanks to Windows 10 & a 3K screen)


Compare that with what you have been working with for the last decades:

 

 

Features

  • New ABAP editor for all ABAP coding within LSMW (field mappings, events, user defined routines and form routines)
  • Code completion
  • Use of the Pretty printer
  • Use of the ABAP Syntax checker
  • Use of ABAP patterns
  • No Modification required, just a single implicit enhancement spot
  • Fix of a small LSMW bug where the wrong line is highlighted when doing a syntax check in the __GLOBAL DATA__

 

 

Limitations

  • Code completion is not aware of globally defined variables
  • A few, more exotic, editor menu commands are not working and will return 'Function not implemented'
  • The use of Edit-->Find/Replace issues warning and will eventually cause a short dump (but who needs this function eh?)

 

The enhancement

The implementation of the new ABAP editor takes just one single Implicit enhancement spot. No modification or any other unwanted hacking! It has been tested on an ECC 606 system with LSMW version 4.0.0 (2004) and SAP Basis 731/02.
Update: Also tested on a brand new ERP 740 SP12 on a 742 kernel with HANA DB underneath.

 

  1. Create an Implicit enhancement spot (how-to) at the start of Subroutine EDITOR_START of Function group /SAPDMC/LSMW_AUX_080



  2. Paste in the code attached to this post & activate.

  3. Create a user parameter ZLSMW_NEWEDITOR  in SE80 (how-to scroll all the way down). Assign the parameter with value 'X' to each user that wants to use the new editor. All other users will not be affected.

  4. Start LSMW!

 


Give it a try and inform me of any bugs. As stated above not all user commands work. All the important ones do and most of the others I have managed to catch and issue a friendly 'not implemented' message. Ideally I'd like to change the PF-Status of the screen and remove the unwanted commands, but this seems not that easy for now.



Frozen

$
0
0

Frozen


image001.png

The Frozen Hare and the Tortoise

 

One Sentence Summary

 

How companies can find their SAP systems frozen waist deep in the ice, unable to pursue the torrent of new business opportunities rushing by - though in fact that sort of change can make you stronger, not freeze you.

 

image002.png

I Could Have Been Someone

I Could Have Been a Table of Contents

 

·         Three Ways to Keep up with the Joneses

·         Why companies are Scared of those 3 things

·         How to come out stronger from these Scary Situations

 

 

image003.png

 

This Frozen Parrot is Dead

 

As been pointed out time again the pace of change in society – both technological and otherwise - is getting faster and faster and when people ask “when is this going to stop” the answer is “it isn’t”.

 

There are two sides to this coin and it’s a “heads I win, tails you lose” situation. With all this change come new opportunities as well as dangers and if your IT system is “agile” enough then you can bend with the wind and surge ahead of the pack. If you can’t adapt then – as I believe Charles Darwin said in “Origin of the Species” – you will be an ex-parrot, you will cease to be.

 

So can we in SAP world use technology to rise to this challenge? In theory – yes. As was obvious at SAP TECHED this year, SAP are not getting left behind here, the pace of change in the ABAP language alone is breathtaking, and of course there is S/4 HANA whatever in the world that might be.

 

What’s the Problem then?

 

However often to take advantage of new technology often you have to upgrade your SAP system to the latest version. And many companies are just too scared to do this. Or even to keep up to date with support packs.

 

If you can’t upgrade another tactic is to make use of existing technology in your current system that you have not explored yet – like BOPF or BRF+. But many companies are too scared to do that also.

 

All right then, at the very least you can update your custom programs - change or add extra functionality - to adapt to the changed situation. But many companies are too sacred to do that either on the grounds it generally stuffs up existing functionality.

 

The end result is they stay frozen waist deep in the ice, like Satan in Dante’s “Inferno” groaning in despair as they see their competitors rushing headlong into the future, leaving them behind.

 


image004.png

Satan frozen waist deep in the Ice: Not Happy Jan

 

Surely you can’t be serious?

 

I am serious – and stop calling me Shirley. To make matters worse either people don’t acknowledge their own aversion to change, or more often are all too aware of the need for change but cite the perceived difficulty/complexity of making any sort of change to a running SAP system.

 

I have two quotes as examples. The first comes from the CIO of a large bank here in Australia. I cannot remember her exact words but she noted she had two different major ERP systems running her business – one was the “spaceman” system which could spin round on a sixpence at the drop of a hat and the live system could be adapted to any new thing that came along in the blink of an eye. The other was a “caveman” system where you could make minor changes once a quarter if you were really lucky.

 


image005.jpg

Spaceman vs Caveman

 

As I am sure you have guessed SAP ECC was the “caveman” system. Hopefully I don’t think things are really as bad as that, but it does not help that all the Solution Manager presentations coming out of SAP last year kept going on about “with our latest advances you can now make TWO releases of your custom code a year!” as if that was the best thing since sliced bread. Surely you would want to make assorted changes to production once a week and aim for as many major changes as you need as and when you need them?

 

The second quote comes from an SAP “poster child” company, by which I mean a company which takes all the latest technology from SAP the week it comes out, and their management get wheeled out at SAPPHIRE keynotes to say how great SAP is.

 

Here is a quote from an ASUG online article about “Florida Crystal’s Ground-Breaking SAP S/4 HANA Story”.

 

“Florida Crystals Vice President and CIO Don Whittington, a former ASUG Board Member, talked about what he hoped to realise with the move (to S/4 HANA): “But what we’re looking forward to most (with HANA in-memory computing) are benefits we haven’t even dreamed of yet, similar to what we experienced with cloud technology … I imagine SAP solutions running as fast as Excel, and being as easy to use, and as easy to implement”.

 

I have read that quote many times

 

(I checked a month later and it had vanished from the online article I was looking at, though you can still see it here http://www.asugnews.com/article/being-bold-the-benefits-of-pushing-the-edges and here http://www.asugnews.com/article/asug-in-review-2015-s-4hana-reimagines-saps-business-suite )

 

and as far as I can see what he is saying is it would be lovely if SAP was as fast and easy to use as Excel and he imagines that might possibly happen now he is on S/4 HANA, so obviously the prior ECC system was nowhere near as good as Excel.

 

That is a bit of back-handed compliment to SAP, and a whopping great compliment to Microsoft. And this is supposed to be one of SAP’s biggest fans – what in the world are their enemies saying? It’s not difficult to spot which is the caveman product and which is the spaceman product here either.

 

I can imagine all the people who have been saying “get away from spreadsheet hell” all these years hearing the Florida Crystals quote and banging their heads on the ground.

 

Mr Benn to the Rescue

 

One person who can turn from a caveman to a spaceman in an instant is Mr Benn. He goes into the hat shop and – as if by magic – a shopkeeper appears, and gives him a hat to wear and suddenly Mr Benn becomes whatever he wants to be.

 


image006.png

Mr. Benn can change with the wind

 

So how can we be like Mr. Benn? Let us recap the three areas I highlighted earlier than companies are unwilling to change for fear of breaking something – the whole system, use of new SAP technology and custom programs.

 

Upgrades are Scary

The other day, whilst reading about S/4 HANA my former colleague (from the late 90’s) Mark Chalfen wrote that SAP customers had been “spoilt” by how easy upgrades had been until now. I replied that they weren’t as easy as all that, sometimes the whole project takes a year from get-go to completion. He in turn replied – quite correctly – that this is usually down to the extreme complexity of the current system.

 

That is the exact situation I am talking about – a really complex existing solution, and even though the technical bit of an upgrade can now be done on the long weekend you want to know what to test to see if it has stopped working. That is why companies like Panaya and Intellicorp sell tools to analyse the system and guide you as to what to test – although the answer is all too often “everything!”

 

As might be imagined “the business” don’t want you to stop developing for even one week, let alone a month, and suck people out of their days jobs to do regression testing when a simple way to avoid both is not to do an upgrade in the first place.

 

In the past often the only way you could get the upgrade project over the line – and this is a true story I have seen first-hand – is to tell the powers that be that the current version is going out of support and the maintenance fee will go up from 2% to 4% of whatever it is, a huge increase. Then I saw the light bulb go on over the manager’s head and he said “Oh I See! It’s a cost saving– that’s all right then!” After all the traditional view of IT is that is just a great big cost, necessary evil, an albatross round the neck, ALBATROSS! ALBATROSS!, and if you can reduce that cost then great.

 

So companies would upgrade every five years or so because they had no other choice. That was the only way I personally would ever get access (at work) to the latest SAP ABAP tools, things that I had been reading about for years. In Thomas Jung’s book “Next Generation ABAP Development” the lead character Russell finds himself in just such a situation, being on the receiving end of a long delayed upgrade, and jumps for joy.

 

Then of course SAP had to go and pull the rug from under my (and Russel’s) feet, and announce that ECC 6.0 was supported until 2025. That’s still almost ten years away – ten years until I can use ABAP in Eclipse in my day to day work. It’s heart breaking, especially as I spend so much time playing on the latest version of ABAP in my spare time.

 


image007.jpg

2025 – We will all be living on Mars and I can upgrade!

 

Now you might say – “hang on just a minute you most Foolish of Fools, oh Clown Prince of Foolish Fools, how Foolish thou art, what about the enhancement packs that come out every year or so. You can just pop them into your system with no disruption at all”.

 

Now some have said that installing an Enhancement Pack is 95% of the effort of an upgrade, and though SAP swears blind if you put one in all the new stuff is dormant so it will have no effect at all, can you really believe this? I personally think it might just be true, but a lot of companies will not take this on blind faith, and so it is “test everything” time again just like with an upgrade. I stress again it is not the technical bit that takes the time, it is the regression testing.

 

So in some places not only is there no chance of an enhancement pack at all ever in ECC 6.0, as when the next deadline falls it will be time to either leave SAP (not very likely) or move to S/4 HANA.

 

Even worse the exact same argument can be used against support stacks – when presented with the testing effort the question come back “do you have a specific problem or problem(s) the support stack will solve?” The answer is usually you don’t, because if you did, you would have installed one or more OSS notes to solve the specific problem(s).

 

“Nonsense, nonsense!” I hear you cry “Check your facts, oh Stupid One, companies are upgrading all the time!”

 

I am sure this is true to an extent, but I did notice at TECHED in Las Vegas last year there was a great big crowd to hear Karl Kessler talk about the latest ABAP features in the 7.5 release. He asked for a show of hands to see who in the audience was currently on 7.4 and he seemed quite surprised when only about 5% of the audience put their hands up. Internally at SAP they must have been on 7.4 what seemed like forever, so it must be easy to forget that the customers are not there yet. I think that explains the debacle which was the release of the 7.40 GUI. Apparently on a 7.4 system the new GUI worked just fine, and all lower releases it had so many bugs it was Hell on Earth. I was one of the idiots who installed it on the first day.

 

To summarise : a lot of organisations will not upgrade until there is no other choice as they are pretty sure some things are going to break, they do not know what, and would have to expand a vast amount of time and resources to find out what had in fact broken and this all too real possibility is scary.

 

New SAP Technology is Scary

 


image008.png

Come on Dad – it’s obvious how to use this!

 

I keep coming back to this like a broken record but Graham Robinson hit the nail on the head when he did his blog about how many programmers refuse to use new technology and like to stick to function modules and DYNPRO GUI programs and what have you. After all – it works!

 

http://scn.sap.com/community/career-center/blog/2012/10/24/a-call-to-arms-for-abap-developers

 

Round about two years ago I was thinking I might want to use BRF+ to store the complicated rules in a major project we were doing. I had thought about it but since most people did not know BRF+ from a bar of soap that would cause a maintainability problem so I backed off in the end, but I can’t help but wonder what the end result would have been had I done so, as we ended up building a very similar custom framework ourselves.

 

In the same way I spent the whole of last Tuesday morning making sure all my ABAP unit tests were up to date in a gigantic application I had spent literally two years building. I can tell you now I do not have even 10% of the unit tests written I really wanted, I have been building them up when I had the odd spare second over the two years, and now I have at least the “happy path” fully covered and will know instantly if any future changes break the fundamentals.

 

Now I would have liked to spend far more time on this but I am all too aware that in many companies a lot of people – especially management – would consider every instant I spent on such activities a waste of time. Luckily not my CIO (because he’s read my book!) but many people would not have such understanding bosses.

 

The “sad” thing is that doing test driven development with ABAP unit does double the initial development time, and even if that results in 90%+ reduction over the life cycle of the application (because you can change things with impunity, instantly knowing if anything is broken) the first bit is the only thing people consider i.e. the project will not come in on time, the project manager will not get the bonus, and stuff the fact the end result is an unstable application that will haunt the company till the end of time.

 

The funny thing is that in a recent (2014) survey (Oxford Economics: The 2020 Workforce) employees were asked what they were most worried about in their job. You would think in the unstable world we live in that getting made redundant would be top of the list. However “layoffs” came in at number 5 with 18% (you could vote for more than one).

 

http://2020workforce.com/

 

Number one, with 40% was “becoming obsolete”. The logic presumably being if you are laid off then you can get another job, but if you are obsolete you are in danger of being obsolete forever. Probably most people in the survey were thinking of robots taking their jobs, but can you see the relevance to the SAP world? Where you get laid off and in the next job interview the interviewer starts asking you about bizarre things like CDS Views and SADL and JavaScript? And when you say “I’ve got WRITE statement skills, I’ve got People Skills Damn you!” they just look at you blankly.

 


image009.png

Join the Club!

 

So you end up with the ever popular “rock and a hard place” situation. If you are in an environment where no-one else knows how to use a certain new technology (or even that such a thing exists) then even if it is appropriate for a new business challenge it might not be a good idea to use it as you have a maintainability problem, so you would be hurting the organisation as a whole.

 

Conversely, if you don’t use it, then – as really the best way to learn something new is by applying it to real life problems – you are hurting yourself, as the Kodak Bear found out.

 

You could argue the way out of this impasse is to train the whole team in the new whatever it is, but then you run into the “that costs money/time and there is no need as everything can be done using the way we have always done it” which is of course true and not everyone has the time or inclination to learn about new technology in their spare time as a hobby, and if you don’t know what something is all about then it is scary and its use might breaksomething.

 

Changing Custom Programs is Scary

 

“How Now Brown Cow, oh Foolish One, that is just nonsense” I hear you cry “your Foolishness knows no bounds, everyone changes custom programs all the time!” How true that is, and the danger here is all too common scenario where an application gets bigger and bigger and more and more complicated over time until it gets to a stage where it is so complicated that no-one really understands any of it, and a one line change in any part of it will always have ripple effects throughout the whole application, breaking something else – seemingly totally unrelated - without fail. That’s scary.

 

https://en.wikipedia.org/wiki/Software_brittleness

 

Now here is a little story and you have to guess if I am making it up or not. Once upon a time there lived an application that was vitally important to the business. One routine inside it performed a fairly simple function.

 

Over the years assorted new business scenarios came along each requiring a little tweak to the logic. Since the routine was so small it was so easy just to add a new branch to an IF statement construct and just cut and paste the five lines of code into each branch, followed by some code to cater for the particular scenario.

 

Then some more requirements came along, this time applying to every scenario. So the new code was added to every branch of the IF statement, again just a few lines, what does it matter?

 

Over the years this pattern repeated, a new IF branch here, a new chunk of code to be applied to every branch there. After ten years there were multiple branches all with a very large chunk of code in each branch, with some minor differences between the branches.

 

A developer, let’s call him Mr. Banana, was doing a peer review and noticed the same change – for a new business requirement – getting added in assorted different places. He expressed his concern to the programmer who had done the change – let’s call him Mr. Pineapple - that this was not only a pain for Mr. Pineapple as he was doing six times the work he really needed to do, even if it was all “Control C / Control V” stuff, and more importantly what if one day one of the many places the change was needed was forgotten, or even worse if the change ended up getting made in a different way in a different place.

 

The answer was simple – from a technical point of view – abstract the identical code to its own FORM routine or (dare I say it) method. Mr. Pineapple agreed – he saw the problem and said that the routine had grown over time and each time he went to change it he considered doing such refactoring but it was always “rush, rush, rush”. Moreover the program worked perfectly and the new functionality was needed tomorrow morning, a whole bunch of end users were coming in – flying in - to do some acceptance testing.

 

The business analyst Mr. Grapefruit was called in and said “only make the change if the business benefit outweighs the risk”. The problem of course that the business benefit of such refactoring is on the surface non-existent (zero) and the risk of making any change to a program you know that works is greater than zero (it’s so easy to break something) so the non-zero change of breaking the program is obviously bigger than the supposedly zero benefit of making the code “better”.

 

Mr. Banana could see why it was probably not a good idea to jeopardise the testing scheduled for tomorrow but as a general principle quoted from the 1999 book “The Pragmatic Programmer…

 

You might want to explain this principle to the boss by using a medical analogy: think of the code that needs refactoring as a "growth." Removing it requires invasive surgery. You can go in now, and take it out while it is still small. Or, you could wait while it

grows and spreads—but removing it then will be both more expensive and more dangerous. Wait even longer, and you may lose the patient entirely. - Pragmatic Programmer, The: From Journeyman to Master /  Andrew Hunt & David Thomas

 

 

https://pragprog.com/book/tpp/the-pragmatic-programmer

 

 

 

The analyst Mr. Grapefruit said that he could see the concept, but in this case would rather take the risk of dying from a tumour at an unspecified point in the future than face the certainty of being shot by his boss the very next day if the code that worked today broke tomorrow.

 

 

It’s the same deal with the extended syntax check and code inspector. The argument goes that there is no time to deal with sort of nonsense, and anyway the code works so why bother?

 

 

This is a point I have mentioned before, again and again like a broken record, but I just can’t stop myself fixing something sub-optimal (untyped parameter or variable with a meaningless or misleading name, duplicate code or some such ) inside a routine I am working on, following the good old “boy scout rule” as penned by “Uncle Bob”

 

 

http://programmer.97things.oreilly.com/wiki/index.php/The_Boy_Scout_Rule

 

 

That’s not a very common attitude as I understand it – as the slightest change can break something; the usual procedure is to only make a fix after a problem has actually occurred.

 

 

As mentioned above that is analogous to never applying Support Stacks to the system, just applying a single OSS note after you have encountered an actual problem in production.

 

 

Put yet another way – “cure is better than prevention”. You don’t often hear people say that in any other area of life; it’s always the other way around – so why should it be backwards for computer software?

 

 


image010.png

Too Busy to fix Sub-Optimal Code

 

 

The obvious solution to this is to start using ABAP Unit – then you would know the instant your refactoring changes broke anything, but people are too busy for that as well.

 

 

So the duplicate code and unused variables and all their mates will most likely sit there for time immemorial, laughing and singing, due to the fear you will breaksomething by removing them. Therefore, changing such custom code is scary.

 

 

One line Summary of why all this is Scary

 

We don’t want to change anything in case something breaks. Plus we have always done things the current way, using existing technology; and it works fine.

 


image011.png

We’ve always done it this way!

 

Breaking things is sometimes a GOOD Thing

 

A few years ago on the SCN I came across the following blog which I found very interesting indeed:-

 

http://scn.sap.com/community/abap/blog/2013/12/01/antifragile-software

 

This was all about a book by Nicolas Nassim Taleb called “Anti-Fragile : Things that Gain from Disorder”. The book was not about software but the writer of the blog (Vikas Singh) considered that software programming could benefit from the general concepts in the book and I think he is bang on.

 

I finally got round to starting reading the book itself the other day. The author of the book has a word for change which is “volatility” and this means the sort of change that breaks things as a matter of course. Interestingly one such cause of dangerous change is noted as time, which of course can knock down mountains eventually. I think the second law of Thermodynamics says “entropy increases” which means that as time goes on things fall apart faster and faster.

 

In IT world the term for violent change is “disruptive technology” and here “disrupt” also means “break” as in breaking the mould, or breaking the dominance of the technology. So you could say that digital cameras disrupted Kodak’s film technology, no matter how many Muppets they wheeled out to keep promoting it.

 

When confronted with new technology that threatened to break everything about his business Kodak should have said “Who loves ya Baby?” which I understand was his catchphrase. He could have then gone on to play the villain in a Bond movie.

 

In SAP world the “volatility” is the stream of constant change requests to change or add functionality, which is supposed to be addressed by the constant change in the technology available to solve these problems.

 

In the Anti-Fragile book there are three categories of how things respond to change:-

 

·         They are fragile, and they break, like a toaster being hit with a sledgehammer.

·         They are robust and stay unchanged in the face of stress, like those Tardigrade creatures that end up unchanged by the most violent types of change e.g. death. http://www.bbc.com/earth/story/20150313-the-toughest-animals-on-earth

·         They are anti-fragile, and the more they get harmed by change, the stronger they bounce back, like a Hydra growing seven heads when you cut one off whilst doing your seven labours of Hercules, a common requirement in modern day internships, or maybe getting a horrible disease like Scarlet Fever which causes you a lot of pain when you are a child, and then being immune to the disease thereafter.

 

It is common in fiction for the story to start with something really bad happening to the key character, and they are forced to do something in response, and at the end of the story end up in a far better position than if the bad thing had never happened in the first place.

 

You may have seen the film “A Shock to the System” where Michael Caine faces the scary situation of being passed over for a promotion, and so starts murdering everybody in his way a la Richard III until he ends up running the company, and likewise “Wolf” where Jack Nicholson faces of scary situation of being demoted, and so turns into a werewolf and once he starts killing and eating people and generally acting like a savage animal his superiors realise that he is ideal for management and thus he ends up running the company.

 

Charming as these stories are, I don’t think we need to go quite as far in order to turn our three shocking situations – upgrades, new technology and changing custom programs – into events that work for us and not against us i.e. making our computer system “anti-fragile” to such situations.

 

Anti-Fragile on an Upgrade Level

 

On a personal level I love it when the SAP system where I work is upgraded. As I stay up to date via the SCN about all the lovely new goodies in each release, when my system is upgraded I am like a bull in a china shop trying out all the new toys. These days even support stacks add new functionality e.g. the BOPF, so even if there is no upgrade I like it when support stacks go in.

 

However a common perception is that installing a support stack is like hitting your PC with a sledgehammer and hoping it still works afterwards, and doing an upgrade is like hitting your computer with a sledgehammer, then bathing it in a vat of sulphuric acid, then fishing it out and coating it with plastic explosive and throwing it in a live volcano, then throwing a hydrogen bomb down the volcano after it, and hoping the PC still works afterwards.

 

I dropped my mobile phone about a foot the other day, and it is not in a good way now, so I can see how fragile some things are. However I personally believe an SAP upgrade is not quite as dangerous as that, having gone through a fair few.

 

I talked about the negatives earlier, they are so obvious they do not need dwelling on, but I would like to counter that with a few positives.

 

Some would say that you get loads of new functionality, not only tools for us developer types, but for the primary consumers, which is the actual business, if you can remember them. Others might add that you are paying a trillion billion dollars a year on maintenance fees and what you are supposed to be getting out of that is not only the pretend support, but also the “free” upgrades with all the new functions.

 

It’s like paying for some cheese up front, and then never eating the cheese. I use cheese as an example because of that book “Who moved my cheese?” where one of the characters says “I’m not sure I’d want to eat new cheese!” i.e. the cheese he had before was the only sort of cheese he would ever want, even when it was there no longer (out of cheese support).

 

Amazing as it may seem those arguments just don’t seem to work. Here are some more I can think of, which most likely will not work either.

 

Firstly the more often you do something, the better you get at it. That is why when you are travelling to Mars or something for 18 months your muscles start to waste away in the zero gravity as they have no work to do. If you only do an upgrade every seven years you have more or less forgotten what it is like, but when one department I knew did the “annual BW upgrade” (the technology was changing that fast) it was “ho hum, business as usual”.

 

Also, if you leave it ten to twenty support stacks before you install them, the delta change will be a lot greater than if you installed them twice (or even once) a year. You’d still have to do just as much testing, but less things would break because less things would have changed.

 

The same principle applies with upgrades – I knew one petroleum company who were hanging on for dear life to SAP Version 3.0, and the longer they waited, the more new versions came out, and the more difficult it was going to be when the inevitable happened.

 


image012.png

 

Anti-Fragile on a Personal Level

 

Once upon a time there was someone who liked to be told exactly what to do, and was very comfortable with what they knew, what consisted of what they had been taught when they were at a large consulting company.

 

Then, when they were an independent consultant, because all the big consulting companies had gone belly up and made all their SAP consultants redundant, they had to work for companies which wanted SAP experts but would not spend one red cent on training.

 

Mr. Banana told him that the next task was to develop some custom code inside SAP which would talk to some sort of SAP Enterprise Portal application being created by a web developer.

 

“I don’t know anything about the Enterprise Portal” he cried, dismayed, “I have never done anything like that before.”

 

“Oh, you will just have to work it out yourself” said Mr. Banana “I will help – I already managed  to figure a lot of it out by trial and error, and once you get there in the end you will have another thing to add to your CV!”

 

“I don’t want it on my CV” said the consultant “I never want to use that new scary technology ever again!”

 

He’s not in IT now. Last I heard he was a newsreader, most likely a lot happier in life, radical new ways of reading the news don’t come along all that often. Reading the weather is different; there are always new ways of doing that, like bouncing on a trampoline or jumping from island to island on a scale model of the UK.

 

Anyway, the point is, if he had soldiered on with that Enterprise Portal business he would indeed have come out of it with an improved CV. The horrible stressful change of having to learn a brand new technology might have been really painful but he would have come out of it more employable.

 

image013.png

Even older people can learn new technology

 

Anti-Fragile on a Technical Level

 

Traditionally when we have to go and change a program due to change, it usually falls into the “fragile” category and breaks. If it manages to survive the change without breaking anything then we deem the program “robust” and break out the champagne and balloons, throw a wild party and put “Conga-Longa-Max” by Max Bygraves on the office record player, and dance around the room with joy.

 


image014.png

You just can’t go Wronga - Singalongaconga!

 

We have managed to make a change without breaking anything! Surely life does not get any better than that? This is the maximum we can expect from the software lifecycle process; this is self-evident –isn’t it?

 

As mentioned above good old “Uncle Bob” thinks not. His position would be that although you have gotten away with it this time (because there are no pesky kids around) all you have usually managed to do is make the program more fragile with extra conditional logic branches and global variables and the like; as Mr. Scott would say “Captain! It’s all held together with bogies and string – the engines, they canna take it no more!”

 

Instead in the “Boy Scout” quote I alluded to above he (Uncle Bob) suggests it is possible that every change can actually make the program less fragile, and it does not take a ten ton mega-genius with bronchial pneumonia to figure out how. You do not even have to wear a woggle.

 

As we have seen when confronted with a new disease, provided the end result is not actually death, once the immune system has fought the new disease off the immune system thinks to itself “I will be ready for that next time” and if the same disease comes knocking the next year it gets killed before it reaches Bombay i.e. it does not cause any harm at all.

 

“Adaptive (or acquired) immunity creates immunological memory after an initial response to a specific pathogen, leading to an enhanced response to subsequent encounters with that same pathogen. This process of acquired immunity is the basis of vaccination.” – Wikipedia

 

Hence the phrase popularised by The Joker “what does not kill me makes me stranger”.

 

So, pretend for a moment you are the immune system, and the change request you have just successfully completed was the disease. This is not that difficult an analogy as, after all many of the change requests you get from the users / business analysts probably make you physically sick.

 

There are several questions you have to ask your little lymphocyte self about what just happened:-

·         Can it happen again ( answer = YES )

·         What was difficult about how I worked out how to fix the problem?

·         Can I strengthen the defences in some way to be ready for the next time this happens?

 

For the first question the answer is obvious – if it happened once it can happen again. You also need to ask yourself can something similar happen? Let us say your program presumed a one to one relationship between a sales organisation (VKORG) and a company code (BUKRS) and then the organisational structure changed and that assumption went out the window, and your program fell in a heap.

 

You can use table TVKO to get the company code for a sales organisation, rather than using the two elements interchangeably as you may have done before. With that problem out of the way you should then look for similar assumptions e.g. an assumption that there is a one to one relationship between a profit centre and a cost centre, or any other silliness which may work at the moment but could break at any time if the configuration or master data changes.

 

Another example - I have even seen a program which assumed a purchase order number was nine characters long and started with “45”. Most purchase orders in most companies do start with “45” but most are ten characters long and anyway, field EKKO-BSTYP is a better evaluation mechanism to see if something is a purchase order as opposed to a schedule agreement or something.

 

The next point is – of the problem happened in the program at hand, and is down to some sort of faulty assumption or whatever, is that same assumption or problem also in other existing programs but no-one has encountered it yet? Perhaps making a pre-emptive strike here is the go, rather than waiting for the users to find the problem?

 

Even if there is no actual problem but you have found an assumption which can break in the future e.g. one cost centre = one profit centre, would it not be a good idea to prevent that potential problem in every program it could occur? That could, admittedly, be a bit of a hard sell. Immune system cells are lucky – if they find a problem in one part of the body they can travel to every other part of the body ready to guard against that problem, without having to fill in a business case evaluation. This is partly because a single celled organism often cannot pick up a pen to sign the document.

 

Amazingly some people might say that is a silly analogy – they would spit in my face and say a company doing such pre-emptive work in advance of a problem actually occurring just sucks up time and money that could be spent elsewhere. Well, where is the immune system getting its energy from? The Moon? The non-conscious part of the human organism lets the immune system have all the resources it wants as it is wholly focussed on survival, unlike most companies, where politics is the primary driver and the manager who stops the immune system from functioning can jump out of the patient before it dies, and jump into another host, and get more money and prestige as a result (and in the UK a Knighthood).

 

How difficult was the fix?

 

As someone somewhere once said “Can we fix it? Yes we can! Can we fix it? Yes we can!” Generally it is not the end of the world to fix whatever the problem is. However I have found that a fairly large amount of the work involves replicating the problem, and the huge bulk involves locating exactly where things are going wrong, and once you have got to that point fixing matters up is a walk in the park.

 

As can be imagined if the problem is in the area of Scooby Doo it would be good if the routine / method was called “Scooby Doo” but it often seems that when developers name routines / methods they have a temporary attack of mild insanity and call the routine “DOG_DAY_IS_OVER” making the developer trying to fix the problem ask “Scooby Doo - Where are You?”.

 

SAP have a horrible habit of putting routines in includes with names like R54RZSD instead of “release credit block” and a lot of programmers have decided that is “best practice” and followed suit.

 

When I started learning German it made debugging standard SAP programs a lot easier but sad to say a lot of routine names make no sense in either German or English.

 

The point I am trying to make here is that if it takes you half a day to even find the code where the problem is occurring then next year when a similar problem occurs will it still take you half a day to find it again? Human nature is to forget how your own code works, let alone someone else’s.

 

The answer is so obvious I was not even going to say it, but just in case – “give routines/methods/variables a meaningful name”.

 

Stupid and/or joke names are even worse. A new programmer won’t be in on the joke and will have no clue what the silly name represents. This is why a lot of ABAP programmers are often scared of web development – they see a big list of tools you need, all with silly names like GIT, GRUNT, FOSSIL, JENKINS, ANT AND DEC, PINKY PONK, NINKY NONK, IGGLE PIGGLE and UPSY DAISY and cannot guess what the tool does from the name. Not that you could guess what ABAP means, or any of the ever changing forest of SAP acronyms. At least “Service Adaption Definition Language” sounds more grown up than “Ninky Nonk” even if you don’t know what either of them means.

 

In any event, moving to the opposite extreme, the latest SAP programming model – CDS views – is predicated upon being “as close to conceptual thinking as possible”. This is not a new idea, many academics (for example, Spiderman) have created whole new programming languages, to try and have the program read like plain English.

 

Furthermore when you have your code reading like English – again as mentioned in all those programming textbooks, such as “The Code Cleaner” and “Dougal and the Blue Cat” – it will be obvious when it is wrong.

 

IF x > y

Or

IF number_of_hotel_floors > number_of_stars_in_the_sky ….

 

The syntax check will never work out this is an impossible situation, and whilst the variables names are meaningless neither will someone reading the code, but as soon as the variable names mean something any human can see what is going on.

 

http://www.joelonsoftware.com/articles/Wrong.html

 

The above blog was not about ABAP but the idea is the same – if you name everything in human terms it becomes obvious when the code is wrong in the same way a wrongly structured written or spoken sentence is clearly wrong.

 

Another quote from Uncle Bob is “we are authors”. Your code is going to get read by real people, and they view things very differently from a machine. Machines are quite happy with every variable being one letter long.

 

As a – very obscure – analogy, if a man goes into a clothes shop to buy a suit and the assistant says to him “X?” that would most likely puzzle the vast majority of customers.

 

Instead, in the real world, if the clothes shop happened to be located in the UK, the shopkeeper would say something like “I’m Free!” or “Oh! Oh! Suits You Sir! Suits You! Oh! Oh!” Some would say that’s not much better, but that’s what actually happens.

 

This might also explain why most men’s clothes in the UK are bought by women on the man’s behalf but anyway if you can stop messing about for just one second andget back to talking about programmingthe point is that if it has taken me half an hour to track down the routine in a custom program that changes everything and I could not find it because it was called ZCD4356 then after fixing the problem I am also going to change the name of the routine to “CHANGES_EVERYTHING” so next time I go looking for it I can find it.

 

This principle was invented by top programming duo Climie/Fisher (hence the name) and I was only seventeen when I started programming that way. It seems like yesterday.

 

How to strengthen the defences?

 

We just talked – at inordinate length – about how naming things sensibly can make life easier the next time we come back to the program i.e. because we did this renaming the very fact there was a problem with the program in the first place made the end result easier to read, understand and thus maintain.

 

Next we have the situation Mr. Banana and Mr. Grapefruit were arguing about earlier – if you had to make the same change in multiple chunks of identical code then clearly abstracting that code will speed up similar changes in the future, make sure there is no disparity between the way various sections of the program do the same thing, and make the code easier to read to boot.

 

Another fun thing about duplicate code is how it usually arrives – via cut and paste. You copy a section of code dealing with goats, and then change all the variables to do with goats so they now deal with sheep, but miss one, so the program ends up doing something crazy like reading the goat table and putting the value in the sheep variable. Having the duplicate code in its own method where the things that change are passed in and out as parameters goes a long way towards solving that problem.

 

Moving along, the warnings in the extended program check and code inspector are not just there for the fun of it – as just one example removing unused variables is good as it frees up just a tiny bit of memory, but more importantly makes the program easier to read. In the 740 version for ABAP and above those unused variables should be a lot rarer as often you only declare them inline the first time they are used.

 

Moreover ABAP in Eclipse has automated tools to help you with those two examples – abstracting out code and removing unused variables.

 

Another one is an assumption that there will only ever be one material type for widgets and suddenly there are two, so you replace a hard coded value with a range that is read from a customising table.

 

I could go on all day – the point is that every time you fix a hard coded problem, instead of making it worse – longer routines, more conditional logic – you can make it better.

 

image015.png

No Risk = No Progress?

 

Summary

 

SAP sometimes gets the reputation of a “caveman” system, not able to respond to change in an “agile” manner. Where this occurs it cannot be laid at the door of the company SAP but rather the fear that some companies (people) have of encountering pain when something breaks as a result of changing anything other than the bare minimum in the system.

 

This takes (at least) three forms, and in each case you can make the pain work for you, thus making your system more “anti-fragile” i.e. something that benefits from the grief caused by the changes needed to keep up with a world that spins faster and faster each year.

 

One – changes don’t get more painful than an upgrade or even a support stack. However doing such an exercise makes you come out stronger as the more often you do them (a) the better at them you will become and (b) the smaller the delta change will be so the less will break.

 

Two – leaving your comfort zone and learning a new technology seems so painful it can make developers want to run and hide behind the sofa, but you come out of it stronger as you are more employable.

 

Three – constantly cleaning up your custom programs as you are forced to change them due to business requirements is a risk as if such a non-mandatory change breaks something your boss will shoot you with a machine gun and that is painful. However using this technique (cleaning your code, not shooting people with a machine gun) makes your custom programs stronger as they are easier to understand and thus maintain the next time a problem comes along, and moreover they are less likely to break and have that problem in the first place.

 

That’s All Folks

 

Most of the points in this blog I have covered before at some stage, though not combined in this fashion.

 

In my personal situation I am allowed to clean up the custom code to make it more robust as time goes by, but the prospect of an upgrade is many years away, and support stacks are not very likely on the application side.

 

I am would be interested to know – have you managed to persuade the higher ups that an SAP upgrade is a good thing, and as a result it actually happened? If so, what arguments did you find worked?

 

Cheersy Cheers

 

Paul

 

 

Be Nice Now.....

$
0
0

There are some legitimate cases where you may want to wait a short while in your program for something to happen.  One thing I use a wait on is when I have a program running and it encounters a lock.  This is ok when you are displaying a single record - you just tell the user that it's locked.   However,  if you are compiling an editable ALV grid for example you don't want to stop them editing some records because one is locked.

 

What I do is wat a second or so,  and try again.  If the record is still locked I wait a little longer,  before after a certain number of times giving up and continuing on with the next record,  flagging the failed record as not locked.

 

But when you wait are you polite or do you still hog the work process ??

 

Instead of using the 'WAIT' statement use the 'ENQUE_SLEEP function module.  The function module releases the work process for another task to use.  The WAIT does not....

 

Rich

How to Make All Field in Account Assignment To Be Read only in SAP Purchase Requisition

$
0
0

In some of business case of MM ( Material Management ), you need to make all field in commitment item in SAP Change Purchase Requisition ( ME52N ) to be read only based on condition.

You can configure most of field of SAP Purchase Requisition ( ME52N ) to be  input or read only through SPRO Configuration but SPRO have a limit, it can’t  control all field on Commitment Item Tab.

For this case , i will use example : User cannot change commitment Item data  in purchase Requisition ( Preq ) document after that particular Preq document has been released 5 ( EBAN-BANPR )

Basically, SAP Preq ( ME52N ) commitment item field always input-able although all other field read only. but you can control it by creating an enhancement point .

me52n-sap-purchase-requisition

You need to create enhancement point which located in KACB Function Group and LKACBF01 Include program and in feldmodifikation_normal subroutine.

me52n-enhancement-point-sap

You can see on the picture above, I create enhancement-point and put ths code:

 

 

1

 

2

3

4

5

6

7

8

9

10

 

data:ls_eban type eban.

 

 

select single *from eban into ls_eban where banfn=cobl-awkey.

 

ifls_eban-banpr='05'.

   loop at gt_coblf into l_coblf.

     l_coblf-input=0.

     modify gt_coblf from l_coblf TRANSPORTING input.

   endloop.

endif.


Note : You just need to modify data ( L_COBLF-INPUT = 0 ) in internal table GT_COBLF .

Then the result is :

me52n-enhancement-point-sap


How to create a RoadMap in GUI environment

$
0
0

Hi guys,

 

This is my first blog and I found an interesting subject one week ago about RoadMap but in GUI environment, normally Roadmap is used with Web Dynpros.

 

This is the code of my program

 

*---------------------------------------------------------------------*
 * Description                                                                    *
 *--------------------------------------------------------------------*
 * Program      : YTEST_ROADMAP                               *
 * Author          : David Carballido Córdova                   *
 * Date             : 22/08/2013                                              *
 * Comentarios   : Build and show Roadmap             *
 *--------------------------------------------------------------------*
 REPORT ytest_roadmap.
 PARAMETERS: p_steps TYPE i OBLIGATORY.
 *----------------------------------------------------------------------*
 *       CLASS DEFINITION DEFERRED
 *----------------------------------------------------------------------*
 CLASS: lcl_main  DEFINITION DEFERRED,        lcl_event DEFINITION DEFERRED.
 *----------------------------------------------------------------------*
 *       Global Variables
 *----------------------------------------------------------------------*
 DATA: go_main TYPE REF TO lcl_main,       g_state TYPE /use/ugu1_state,       g_text  TYPE char40.
 *----------------------------------------------------------------------*
 *       CLASS lcl_main DEFINITION
 *----------------------------------------------------------------------*
 CLASS lcl_main DEFINITION FINAL.   PUBLIC SECTION.     METHODS: start_road,              state_click IMPORTING i_state_id TYPE /use/ugu1_state,              next_step.   PRIVATE SECTION.     METHODS: init_roadmap.     DATA: go_roadmap TYPE REF TO /use/cl_ugu1_html_roadmap,           go_custom  TYPE REF TO cl_gui_custom_container,           go_event   TYPE REF TO lcl_event.
 ENDCLASS.                    "lcl_main DEFINITION
 *----------------------------------------------------------------------*
 *       CLASS lcl_event DEFINITION
 *----------------------------------------------------------------------*
 CLASS lcl_event DEFINITION FINAL.   PUBLIC SECTION.     METHODS: state_click FOR EVENT evt_state_click                 OF /use/cl_ugu1_html_roadmap                     IMPORTING i_state_id.
 ENDCLASS.                    "lcl_event DEFINITION
 *----------------------------------------------------------------------*
 *       CLASS lcl_main IMPLEMENTATION
 *----------------------------------------------------------------------*
 CLASS lcl_main IMPLEMENTATION.   METHOD start_road.     IF go_custom IS INITIAL.
* Instance Container       CREATE OBJECT go_custom         EXPORTING           container_name              = 'ROADMAP'         EXCEPTIONS           cntl_error                  = 1           cntl_system_error           = 2           create_error                = 3           lifetime_error              = 4           lifetime_dynpro_dynpro_link = 5.       IF sy-subrc = 0.
* Instance Roadmap         CREATE OBJECT go_roadmap           EXPORTING             i_parent            = go_custom             i_application_event = abap_true           EXCEPTIONS             cntl_error          = 1.         IF sy-subrc <> 0.           EXIT.         ENDIF.
* Instance Event Class         CREATE OBJECT go_event.         SET HANDLER go_event->state_click FOR go_roadmap.
 *  Initializing Roadmap         me->init_roadmap( ).
 * Set  Width of Roadmap         go_roadmap->set_state_width( i_width = '40' ).
 * Generate HTML of Roadmap         go_roadmap->render( EXCEPTIONS render_error = 1 ).       ELSE.         EXIT.       ENDIF.     ENDIF.   ENDMETHOD.                    "start_road   METHOD init_roadmap.
 * Local Variables     DATA: l_step TYPE numc2,           l_text TYPE char30.
* Initializing States     go_roadmap->remove_all_states( EXCEPTIONS remove_failure = 1 ).     DO p_steps TIMES.       l_step = sy-index.       CONCATENATE 'Step' l_step INTO l_text SEPARATED BY space.       go_roadmap->add_state(         EXPORTING           i_state_text   = l_text           i_state_type   = /use/cl_ugu1_html_roadmap=>c_state_normal           i_is_clickable = abap_true           i_is_optional  = abap_false         EXCEPTIONS           add_failure    = 1 ).     ENDDO.
 * Activate first state     IF g_state IS INITIAL.       go_roadmap->set_state_type(         EXPORTING           i_state_id     = '1'           i_state_type   = /use/cl_ugu1_html_roadmap=>c_state_active         EXCEPTIONS           invalid_state  = 1           update_failure = 2 ).
 * Send initial text       g_text = go_roadmap->get_state_text( '1' ).     ELSE.       go_roadmap->set_state_type(         EXPORTING           i_state_id     = g_state           i_state_type   = /use/cl_ugu1_html_roadmap=>c_state_active         EXCEPTIONS           invalid_state  = 1           update_failure = 2 ).     ENDIF.   ENDMETHOD.                    "init_roadmap   METHOD state_click.     g_state = i_state_id.
 * Get text of state      g_text = go_roadmap->get_state_text( i_state_id ).
 * Free Objects     go_roadmap->free( ).     go_custom->free( ).
 * Clean Objects     CLEAR: go_roadmap, go_custom.
 * Simulate ENTER to refresh screen     cl_gui_cfw=>set_new_ok_code( '/00' ).   ENDMETHOD.                    "state_click   METHOD next_step.
 * Local Variables     DATA: lt_states TYPE /use/ugu1_t_roadmap_state,           l_state   TYPE /use/ugu1_state.     FIELD-SYMBOLS: <fs_states> TYPE /use/ugu1_s_roadmap_state.
 * Get active state     go_roadmap->get_states_by_type(       EXPORTING         i_state_type = /use/cl_ugu1_html_roadmap=>c_state_active       IMPORTING         et_states = lt_states ).     READ TABLE lt_states ASSIGNING <fs_states> INDEX 1.     IF sy-subrc = 0.       l_state = <fs_states>-state_id + 1.
 * Get residue on parameter selected       l_state = l_state MOD ( p_steps + 1 ).       IF l_state = 0.         l_state = 1.       ENDIF.
 * Set state click       me->state_click( l_state ).     ELSE.       MESSAGE s888(sabapdocu) WITH 'No existe paso activo'.     ENDIF.   ENDMETHOD.                    "next_step
 ENDCLASS.                    "lcl_main IMPLEMENTATION
 *----------------------------------------------------------------------*
 *       CLASS lcl_event IMPLEMENTATION
 *----------------------------------------------------------------------*
 CLASS lcl_event IMPLEMENTATION.   METHOD state_click.     go_main->state_click( i_state_id ).   ENDMETHOD.                    "state_click
 ENDCLASS.                    "lcl_event IMPLEMENTATION
 *----------------------------------------------------------------------*
 *       S T A R T  -  O F  -  S E L E C T I O N
 *----------------------------------------------------------------------*
 START-OF-SELECTION.
 * Instance Main Class   CREATE OBJECT go_main.
 * Show Roadmap   CALL SCREEN 100.
 *&---------------------------------------------------------------------*
 *&      Module  STATUS  OUTPUT
 *&---------------------------------------------------------------------*
 MODULE status OUTPUT.   SET PF-STATUS 'ST_100'.   SET TITLEBAR 'TIT_100'.
 * Show Roadmap   go_main->start_road( ).
 ENDMODULE.                 " status  OUTPUT
 *&---------------------------------------------------------------------*
 *&      Module  user_command  INPUT
 *&---------------------------------------------------------------------*
 MODULE user_command INPUT.   CASE sy-ucomm.     WHEN 'BACK'.       LEAVE TO SCREEN 0.     WHEN 'NEXT'.       go_main->next_step( ).   ENDCASE.
 ENDMODULE.                 " user_command  INPUT

 

Here I attach screen 100 to upload and generate

Dynpro_1.jpg

Dynpro_2.jpg

Then when you execute the program you can select how many steps are going to build, for example I'll select 10

Dynpro_3.jpg

And this is the result

Dynpro_4.jpg

You can click on any step or press "Next Step" button to select the next step, I hope this help you in any development and I welcome your comments

 

PD: Sry for my bad english

 

Regards

David Carballido

ABAP Active Record - An ABAP Perspective

$
0
0

We in ABAP world used to have everything handy. Access some information in any table, SELECT and done. Update? Done. Use some global class, done. It's not even necessary any "require" or "include" command. It's there. Just use it!

However, in my very first days working with SAPUI5 I saw that the life is not so easy outside of ABAP stack. Thinking in how I could make the UI5 developer easy, I started to working in the ABAP Active Record project. It's a open source project project shared in Github to replicate the Active Record that I know from Ruby on Rails. The objective of this project is to provide a way to UI5 devs access SAP tables at ABAP stack in a very easy way.

This blog is to give an ABAP perspective to community. You can find more information on my blog at SAPUI5 community. Please check there how to use and how it works in SAPUI5.

Note: It's already in my future road map to use ABAPGit.

SAP Gateway

It’s only necessary to create one generic service at SAP Gateway that will respond all requests for any table!

There are two entity types: request and result, with their entity sets.

  • request is responsible to receive all information about database operation, like table name, fields to be selected and filter conditions.
  • result is responsible to process all information entered using resquest calls and execute desired operation.


The whole transation is executed using batch processing.var oFlightsTable = oARModel.aarGetEntitySet('SFLIGHT', ["CARRID", "CONNID", "FLDATE", "PRICE"], {carrid: "LH", connid: "2402"});For example, for the aarGetEntitySet method call above, it’s necessary follow requests:

  • first request (POST method) call to pass operation and SAP Table name;
  • 4 request (PUT method) calls to pass all 4 fields to be retrieved;
  • 2 request (PUT method) calls to pass 2 filter conditions and
  • last result (GET method) call to retrieve all information from database selection.

 

It’s necessary 8 requests in total for this example called in the same transaction (batch).

 

Here is the return of result entity set method:

<model>SFLIGHT</model>

<field>CARRID</field>

<value>LH</value>

<model>SFLIGHT</model>

<field>CONNID</field>

<value>2402</value>

<model>SFLIGHT</model>

<field>FLDATE</field>

<value>08/21/1997</value>

...

 

ABAP

In ABAP side, I implement proper methods for very dynamic Open SQL calls. For more information, you check the ABAP methods implementation.

Here is the list of methods implemented in ABAP in order to process database retrieval:

  • REQUESTSET_CREATE_ENTITY

Called in the begginig of all transactions. It’s responsible to define the table name and operation.

  • REQUESTSET_UPDATE_ENTITY

Receive all parameters to build dynamic database operation.

  • RESULTSET_CREATE_ENTITY

Used in aarCreate method (PUT) and execute INSERT SQL command.

  • RESULTSET_DELETE_ENTITY

Used in aarDelete method (DELETE) and execute DELETE SQL command.

  • RESULTSET_GET_ENTITY

Used in aarGetSingleValue method (GET) and execute SELECT SINGLE SQL command.

  • RESULTSET_GET_ENTITYSET

Used in aarGetEntitySet method (GET) and execute SELECT SQL command.

  • RESULTSET_UPDATE_ENTITY

Used in aarUpdate method (PUT) and execute UPDATE SQL command.

Sequence Calls

Just as an example, here is the sequence of calls necessary to retrieve a set of records for SFLIGHT table:var oFlightsTable = oARModel.aarGetEntitySet('SFLIGHT', ["CARRID", "CONNID", "FLDATE", "PRICE"], {carrid: "LH", connid: "2402"});All calls bellow are result of a batch request from SAPUI5.

  1. Call REQUESTSET_CREATE_ENTITY to start the processing and define some parameters.
  2. For each field in the list (i.e. ["CARRID", "CONNID", "FLDATE", "PRICE"]) callsREQUESTSET_UPDATE_ENTITY and store all values in an internal table.
  3. For each property in the object (i.e. {carrid: "LH", connid: "2402"}) callsREQUESTSET_UPDATE_ENTITY and store all filters to be used in WHERE clause in an internal table.
  4. At the end of processing, call RESULTSET_GET_ENTITYSET to execute the dynamic SELECT command and return the entityset with a list of all fields.

Here is the list on parameters internal table for the method call above:

Filter Internal Table

Based on that parameters dynamic select is called like bellow:

* --- all dynamic retrieve

TRY.

  SELECT (it_fields) INTO TABLE <dyn_table> FROM (me->ddic_table) WHERE (it_where).

CATCH cx_root.

  RAISE EXCEPTION TYPE /iwbep/cx_mgw_tech_exception.

ENDTRY.

 

Feedback

I started this project to share my idea and the initial proof of concept. I’m not consider ready to be used in production and improvements are needed. However, in the pure open source spirit, I decided to share my idea and receive feedback from the community.

The Agile ABAPer - 5 Reasons why ABAPers should be Agile - and what you can do about it today.

$
0
0

The Agile ABAPer

5 Reasons why ABAPers should be Agile - and what you can do about it today.


It’s not often a day goes by that I don’t think about how much we all learn (and forget) over the years. Over 20 years after doing a CompSci degree I might have forgotten the detail of the course but I've gradually evolved a hindsight from the graduation-view of “This was all useless, it doesn’t reflect reality” to the current “well that certainly grounded me in the basics but it changes so fast that we have to do all we can just to keep up with reality”. It is the skills learnt, not the facts forgotten which allows us to cope with the pace of change.

The recent hum around digital economy, transformation and lean programming within the world of SAP might not feel like it has any bearing on your day-to-day reality - fixing bugs, delivering projects on time, ensuring down-time is minimized.

 

But it really, really does.

 

Agile programming isn’t something which has only just been thought up. And even when it was still fresh it didn’t just spring out of the ground. No, it evolved from something else (anyone remember JAD/RAD?!). And you can be assured that to will evolve into something else.

 

What you have to keep reminding yourself is that this is not some big scary new methodology; you haven’t missed the boat. Over 20 years ago JAD and RAD, Joint and Rapid Application Development, was the cutting edge of software and systems development. Agile is an evolution, a rethink, but most of all it is a chance to orient yourself.

 

So I thought it would be good to answer a few of your questions without you having to ask and feel embarrassed. Which you shouldn’t ever be, by the way - questions are always good.




  1. Agile will decrease the pain of code rework - Each sprint will contain specific, agreed-upon capsules of work. You know what you have to deliver and you know what the criteria for successful delivery looks like.

  2. Agile ABAPers are happier ABAPers. You will have stronger connections with colleagues because you’ll need to cross-skill with them frequently. Each work item is now so much smaller, you will also be happier - no more weeks stretching ahead working on the same thing day after day.

    You’ll get more job satisfaction because you are now empowered to work directly with with all areas of the business.
    1. In your Code Reviews there will be cross pollination of ideas, you’ll learn new techniques, methods and approaches.
    2. Development teams are happier places too - this cross-pollination drives multi-skilled developers, there is less likely to be that one Rockstar Coder who is never allowed to go on holiday for fear of it all collapsing..


  1. It pays to know - The Agile ABAPer earns more. OK, so I have no evidence to back this up, but we all know that counts for a lot to have a CV or a development plan which describes you as being at the cutting edge of SAP’s technologies.

  2. No more weekends. Before Agile the triangle of Scope, Quality and Schedule was always so inflexible that we all knew weekends would come into play because the only room for maneuver was the schedule. With agile, the flexibility comes from Scope.
    Agile techniques in planning the sprint mean that if when the schedule is decided on, it is you and your peers who decide on what goes in. There are a few techniques to get to the bottom of how long a particular work item will take but Planning Poker will always get people engaged!

  3. Unit Test pain is significantly decreased because you’ll now use automated test techniques.
    1. Extended Program Check
    2. Code Inspector
    3. Coverage Analyzer
    4. ABAP Unit


The are just 4 of the internal tools which SAP include and maybe you didn’t think of them as being part of the Agile ABAPer’s toolkit. These and more can all make you unit testing easier. Yes, you would have to get management buy-in to get Docker or Chef used across the project but if you can explain how it will save time and money then see how fast it will get adopted then!

 

 

 

What you can do about it today!

 

  1. Find and Read 3 blogs on how others are using/implementing agile methodologies and share one of them on Twitter - tag your post #AgileABAPer

  2. Bookmark 3 pages:
    • The Agile Dictionary - http://agiledictionary.com/ - Your one-stop shop for rapidly searching for that term you heard but were unsure of the context.
    • Atlassian Agile - https://www.atlassian.com/agile - Atlassian being the owners of JIRA, the go-to agile work centre for many businesses (and yes, even Basis Technologies, where I work!). Invaluable in making sprint planning, execution and backlog an easier, intuitive part of your day.
    • DevOps.com - http://devops.com/ - Every day a new story, a new viewpoint on the future of DevOps-driven technology. Not SAP specifically, but it doesn’t hurt to expand our horizons right?

  3. Talk to your manager or better still, whoever does your annual review about agile. Get their thoughts, share your own. Get something Agile put on your review objectives.



Please do comment below too - if you have any great blogs or twitter feeds which keep us on the top of our game then the community will all gain from this knowledge share.

A second way to get the new ABAP editor in LSMW

$
0
0

In my previous blog 'How to get the new ABAP editor in LSMW' I described how a single enhancement enables the new ABAP editor in SAP's LSMW. While that solution only takes one implicit enhancement spot, it has a few (minor) limitations. In this next blog I will describe another approach to enabling the new ABAP editor in LSMW. This new solution is slightly more invasive, but gives us much more flexibility.

 

 

The solution

This solution involves an enhancement spot and a new function group with a screen. The big advantage of this solution is that almost all limitations of the first approach are gone. Also you will have full control of the screen and its functions. For this implementation I have added a set of much used LSMW functions directly on the toolbar (as buttons). You are free to add, remove, change those to your liking!

Neweditor2.jpg

 

Features

  • New ABAP editor for all ABAP coding within LSMW (field mappings, events, user defined routines and form routines)
  • Code completion
  • Pretty printer
  • ABAP Syntax checker
  • Use of LSMW-specific inserts (mapping source fields, global variables, global functions)
  • Use of ABAP statement templates
  • Use of (almost) all new-editor features such as Edit buffers, up- and download of source, etc.
  • Automatic use of 72-character version of the new editor, irrespective of your global setting in SE80
    (Read about the limitation & work around in the previous blog)

 

Limitations

  • Code completion is not aware of globally defined variables.
    (It must be possible to also get rid of this limitation, but that is for the community to pick up. look at CL_ABAP_PARSER for starters.)

 

Implementation

By far the easiest way to implement is by using SAPlink. This will install the function group, screen and enhancement spot implementation in one go.

 

The implementation comprises

  • A custom function group ZLSMW_NEW_EDITOR with one function module and one screen
  • An implicit enhancement spot at the start of Subroutine EDITOR_START of Function group /SAPDMC/LSMW_AUX_080
  • (optional) A user parameter to switch the solution on or off per user.

 

I added ample comments in the code, so it is easier to understand what is happening.

 

 

 

Implementation using SAPlink

I will assume you have installed- and are familiar with SAPlink.

 

  • Install the .NUGG file attached to this post. It will upload and install the following components
    • Development package ZLSMW
    • Function group ZLSMW_NEW_EDITOR
    • Implicit enhancement spot ZLSMW_NEW_EDITOR @ Subroutine EDITOR_START of Function group /SAPDMC/LSMW_AUX_080
  • Check and activate the new objects. You might need to assign them explicitly to the new package ZLSMW (as they all end up in your $TMP)
  • Manually create User Parameter ZLSMW_NEWEDITOR (how-to, scroll all the way down) and assign the parameter with value 'X' to each user that wants to use the new editor. All other users will not be affected.
  • Done! Start LSMW and check out the new features!

 

 

Manual implementation

Alternatively you can implement it manually;

 

  • Package ZLSMW
    Create a development package ZLSMW. Save and activate.

  • Function group ZLSMW_NEW_EDITOR
    Create function group ZLSMW_NEW_EDITOR and assign it to the newly created package ZLSMW

  • Function module ZCALL_ABAP_EDITOR

    In the new function group create function module ZCALL_ABAP_EDITOR with the following interface
    IMPORTING
      REFERENCE(IV_EDITMODE) TYPE  CHAR4
    CHANGING
      REFERENCE(CT_SOURCE) TYPE  RSWSOURCET

    For the implementation paste in the FM code from the attached text file code2.txt and save.

  • Include LZLSMW_NEW_EDITORTOP
    Create a new include called LZLSMW_NEW_EDITORTOP in the function group and paste in the include code from the attached text file code2.txt. The include holds both the global variables, form routines and PAI/PBO Modules. I know, it is not as it should be done, but it limits the number of includes ;-) If the new PAI and PBO modules etc do not appear in the SE80 tree you need to rebuild the object list. You do this by right clicking on the function group name in the SE80 tree on the left, then go to Other Functions --> Rebuild Object List.

  • Screen 3000
    Create a new screen 3000. Add a custom container called EDITOR over the full size of the canvas and save. In the screens flow logic uncomment the PAI and PBO modules MODULE STATUS_3000 and MODULE USER_COMMAND_3000.

  • Pf-status EDITOR
    Copy pf-status EDITOR from function group /SAPDMC/LSMW_AUX_080 to your new function group. Name it also EDITOR. Next you need to remove a few items from the menu bar. Remove the items in yellow:


    Change the toolbar functions such that it resembles below screenshot.


    Optionally you can change the function keys to your liking.

  • Enhancement spot
    Create an Implicit enhancement spot (how-to) at the start of Subroutine EDITOR_START of Function group /SAPDMC/LSMW_AUX_080. Paste in the enhancement code from file code2.txt attached to this post & activate.


  • User Parameter
    Create a user parameter ZLSMW_NEWEDITOR  in SE80 (how-to scroll all the way down). Assign the parameter with value 'X' to each user that wants to use the new editor. All other users will not be affected. This is optional. If you want all users to use the new editor, omit this step and remove the check in the enhancement spot implementation.

  • Done! Activate all and start LSMW.

 

Enjoy! Please let me know of any bugs or shortcomings.
Feel free to add to or enhance this solution. Particularly the small limitation in the code completion might be a useful addition.

Fanning the Flames: Prefixing Variable/Attribute Names

$
0
0

Trigger Warning: This blog will probably annoy a number of people. It's been lurking in the back of my mind for some time now, originally inspired by Ralf Wenzel's article Hungarian beginner's course - a polemic scripture against Hungarian Notation. Among others, I wouldn't be too surprised to receive critical comments from Matthew Billingham in particular - but then again, maybe not. As Tolkien has put it a long time ago, "So many strange things have chanced that to learn the praise of a fair lady under the loving strokes of a Dwarf's axe will seem no great wonder." I figured I might as well give it a try, even though it might spoily my birthday festivities.

 

To cut to the point: I use prefixes for variables and parameters myself, and I encourage people to use a consistent prefix system throughout their code. In my experience, a sensible naming scheme for variables does help developing and maintaining ABAP code. I don't for a moment believe that I will convince anyone who doesn't want to accept that, but I do believe that in this discussion, there are a number of arguments that are too easily forgotten or cast aside. I'm well aware of the fact that this subject is guaranteed to trigger a lively - hum - discussion, so I will try to keep the tone a bit more formal and a little less emotional than Ralf did in his post. (To be fair - his trigger warning is in the title as well as the introduction.)

 

Perhaps, first and foremost - what is the prefix system I use? It boils down to a combination of one or two letters, an underscore and a sensible name for the variable. I'll focus on the assembly of the prefix here, since that's what the 'hungarian notation' discussion is about - whether you want to name your variables according to the dictionary structures or rather have some 'english' name is another discussion.

 

The first letter designates the origin or scope of the variable of parameter:

 

  • class members:
    • g = instance attribute
    • s = static attribute
  • methods and (where applicable) function modules:
    • l = local variable
    • i = importing parameter
    • e = exporting parameter
    • c = changing parameter
    • r = returning parameter
  • programs, function groups
    • g = global variable
    • p = PARAMETERS (report only)

 

The second letter distinguishes between the data types:

  • (none) - elementary data type
  • s = structure
  • t = internal table
  • r = reference

 

For WebDynpro coding, I use a slightly different notation - basically because I'm too lazy to to through the generated code and adapt it all:

  • v = elementary data type (WebDynpro coding since that's the default in the generated code)
  • o = object reference (WebDynpro)
  • r = data reference

 

Exceptions and inconsistencies I haven't overcome yet:

  • so_ = SELECT-OPTIONS
  • co_ = constants
  • no prefix for public read-only attributes of persistence classes
  • no prefix for constants in "enum interfaces" that only contain constants
  • TABLES - hello, dynpros! - for structures EXCLUSIVELY, NEVER for transparent tables, same name as the structure

 

So we get, for example

  • gt_foo in a class - that would be an instance attribute that is an internal table
  • ls_bar - a structured local variable
  • ir_baz - an importing reference parameter

For FIELD-SYMBOLS, I tend to use the same notation, so you'll see stuff like <ls_foo> or <lr_bar> in my code. Since I tend to avoid global FIELD-SYMBOLS, I could omit the 'l', but decided to keep it for simplicity of the ruleset.

 

To sum it up: nothing too special here. I don't claim to have invented this prefix system, only adopted and adapted it slightly - although it's so generic that probably hundreds of developers around the world use either this system or something very similar. It's slightly more verbose than the scheme presented by Kai Meder in ABAP Modern Code Conventions, but I believe that the differences do justify an extra character.

 

Before discussion the advantages and disadvantages in detail, I would like to point out a simple and important fact that appears to be overlooked in many discussions: There is no perfect life. There is just life. We have to make do with what we have, and while we can (and should!) always aspire to refine our skills and improve ourselves as well as our environment, there are shortcomings, deficiencies and historically-explainable-but-nonetheless-ugly-kludges that we just have to deal with. Dreaming of a world without global variables, methods no longer than (insert number here) lines of code and pure object orientation may be an enjoyable pastime, but it doesn't get the job done. The world is out there, and it contains loooooong methods (many of which started out fairly short and grew through years of maintenance by many hands and a lack of refactoring), insanely complex systems and a weird mix of object-oriented and procedural programming, so we have to deal with stuff like that on a daily basis.

 

We also have to deal with another important fact: Humans make errors. Even the most intelligent and experienced developer will eventually produce a bug (other blog authors and moderators excepted, of course). Since a naming convention is of no use whatsoever to the maching, it has to be optimized to support the human in front of the machine. Ideally, it should aid in understanding the code that is already present and prevent coding errors wherever possible - or at least make them more obvious. So let's take a look at some common mistakes and how the naming conventions above aid in preventing or at least spotting these.

 

Let's start with a common controversy - why use prefixes for local and global variables at all? There are really two arguments that make me recommend using the prefixes 'g' and 'l' respectively, despite many notable voices arguing against their use. First off - shadowingand name masking. These concepts exist in many programming languages, and I have yet to find a real-world application that does not involve a decent amount of sadism towards the poor souls who have to maintain the code afterwards. From my experience, wherever you see variable shadowing actually happening outside of a programming class, something has usually gone south when refactoring or maintaining the code. Variable shadowing produces particularly nasty bugs that can easily take hours or even days to hunt down. Spliting the namespace into distinct partitions for global and local variables neatly solves that problem - if all class attributes start with 'g' (or 's') and all method-internal variables start with 'l', shadowing won't ever be a problem. Other languages cope by adding compiler warnings and smart IDE extensions to help the developer spot variables shadowing each other, which is just another workaround for the same problem, and one we don't have yet (the last time I checked, even the splendid ATC didn't warn about shadowed variables).

 

The second argument for "scope prefixes" I'd like to present is related to the counter-argument "variables are always local, and who get's to say what's called global in an object-orientated aplication anyway?" It certainly isn't easy to answer the latter question, but it helps to approach the issue from a different angle: When I change the contents of that foo thingy over there - then what is the scope (or lifetime, if you prefer) of that change?Am I only affecting the execution context of the method I'm currently in, and whatever I change gets discarded when the method is processed anyway - or am I permanently changing the state of the current instance, or even the entire class? You may want to call these changes "local" and "global", for want of a better name. Of course, this can be easily determined with a simple double-click, but it's much easier to write and maintain code if you've got that information embedded in the identifier. If you use this consistently, especially as an entry-level programmer, you will find that after a time, using something prefixed with 'g' will start to feel slightly awkward - should this really be global, do I need this anywhere else, can't I just make this a local variable? - whereas accessing something prefixed with 's' outside of some specially designated factory methods will set of alarm bells at once just by reading it. I've seen many bugs that ultimately could be traced back to an accidental modification of an attribute value (often after an improperly executed refactoring operation), and again, these bugs are really hard to find because they usually only surface much later in the application, and even then only under particular circumstances.

 

Now for the data type designator - what's the point in distinguishing between elementary fields, structures, tables and references? Convenience, mostly, but there are a few cases where these prefixes really can help you spot problems. ABAP has a history of peculiar conversion rules, and the one I'm after here is the conversion between flat structures and single fields. Let's assume you're coding a data object for some translateable entity (something with a separate language-dependent table that contains the translateable parts of the object), and you're keeping the text in an atribute named description. Some day you note that you've forgotten to add an accessor method for that, so you write a getter that returns a STRING, something as simple as r_result = description. Clean and obvious - until you notice that your application displays '100DEFoobar' instead of 'Foobar'. Whoops. Looks like description wasn't only the text, but you decided to store the entire text table entry instead (which makes perfect sense, especially if you've got multiple translateable fields). If you had named that attribute gs_description, you would have noted that immediately and prevented that mistake. Now this is an easy example, but I've seen this error happen to experienced developers in large applications, and again, it takes time and patience to hunt down that unwanted client number in the outbound message stream.

 

With internal tables, this kind of conversion error will not occur, but there's another quirk in the ABAP syntax that virtually every newbie has to master. Consider the following two examples:

 

DATA: sflight TYPE TABLE OF sflight.

 

" somehow, magically, fill that table with some values

 

LOOP AT sflight ASSIGNING FIELD-SYMBOL(<sflight>).

  " some condition, don't care, whatever...

  DELETE TABLE sflight FROM <sflight>.

ENDLOOP.

 

as opposed to

 

DATA: sflight TYPE TABLE OF sflight.

 

" somehow, magically, fill that table with some values

 

LOOP AT sflight ASSIGNING FIELD-SYMBOL(<sflight>).

  " some condition, don't care, whatever...

  DELETE sflight FROM <sflight>.

ENDLOOP.

 

Now granted, that's taking it to the limits, but the experienced ones among you will know how inventive the inexperienced among you can get when introduced to ABAP. I might have turned that into another trapdoor article, but just to reiterate: the first example will modify the internal table while the second example will actually kill selected contents of the database table. The issue here isn't only that this will be dangerous for the application data - bugs like these are usually so catastrophic in their results that they tend to be found early on - but that it is much harder to determine the intent of the developer and pinpoint the bug. Now let's compare this to a prefixed version:

 

DATA: lt_sflight TYPE TABLE OF sflight.

 

" somehow, magically, fill that table with some values

 

LOOP AT lt_sflight ASSIGNING FIELD-SYMBOL(<ls_sflight>).


  DELETE TABLE lt_sflight FROM <ls_sflight>. " OK - we're modifying the local table

                                             " contents here


  DELETE TABLE sflight FROM <ls_sflight>.    " syntax error: The field "SFLIGHT" is

                                             " unknown, but there is a field with

                                             " the similar name "LT_SFLIGHT".


  DELETE lt_sflight FROM <ls_sflight>.       " ATC complains about "Non-numeric index

                                             " access on internal table"

                                             " and suggests correct variant above.


  DELETE sflight FROM <ls_sflight>.          " OK - changing the database contents


ENDLOOP.

 

Also, after a while, typing LOOP AT lt_ followed by Ctrl+Space becomes a habit, and the code completion will present only the local tables - without robbing you of the flexibility to simply type LOOP AT<Ctrl+Space> and still have access to the full list of options.

 

All things considered, prefixes for variable names aren't as bad as some articles make them. Prefixes are a workaround, a compromise between what we have, what we can get, what we need and most importantly what we don't want. If you've ever ran into any of the bugs I mentioned above, either in your own code or someone else's, you know what I'm talking about. If you haven't (yet?), still please consider the junior members of your team and the people who succeed you and have to maintain your code. Someone may be very grateful for those few extra characters that really take no time either typing or reading.

Viewing all 943 articles
Browse latest View live