5 Ways to Improve the Readability of Your ABAP Code Part III. - Organizing with Functions


Overview

In the last two blog posts, I have showed you the benefits of using meaningful names and avoiding magic numbers. As I told you, it really does matter how readable your code is.

In the last few days, I was thinking a lot about the WHYs, why many-many developers write their source code with poor readability and transparency:

  • faster development => okay, it can be faster in the first few iterations, but then the development time increases largely, when the lines of the source code hits a certain numbers,
  • hiding information => it's my program! I don't want anybody to understand it! I want to keep that information! It's ok, but you are going to hide that info from yourself also, since a year later you won't understand neither,
  • laziness => I have no explanation :)

Finding self-explanatory, meaningful names, and writing well-organized code takes time, that's true, but believe me, it's going to pay off later.

I have already mentioned you that you should think about your code as a book, it should have

  • a title (for example: program name),
  • table of contents (list of methods, functions, subroutines calls, so on),
  • detailed chapters (implemented methods, functions, subroutines, so on).

Don't forget! We are paddling with our colleagues and the others in the same boat, we form a team, so don't make your colleagues' tasks more difficult, write readable and transparent code that everyone can easily read and understand.

Today, my goal is to show you the benefits of a well-organized code using functions whether with function modules, subroutines, methods, and so on. I'm going to introduce it based on one of my previous sample source code, on the XML processing example. Have fun!


Unorganized Code

Here is the refactored (backward) version of the XML processing example. This version represents the unorganized way of a code, the statements are one after the other, we don't get any additional information about what the code is about.

My problem with this code that I only can guess

  • why the developer uses GUI_UPLOAD,
  • why loops through on an internal table and uses the statement, CONCATENATE,
  • why calling a transformation,
  • why inserting to a database table.

But why should I guess these information, if I am able to express it in a efficient way? It's hard to interpret, I only can guess, I cannot be sure what the code exactly does. It's a time consuming activity, and unnecessary part of the development.

What should we do?

...
START-OF-SELECTION.
  CALL FUNCTION 'GUI_UPLOAD'
    EXPORTING
      filename = 'C:\customers_with_attribute.xml'
    TABLES
      data_tab = xml_content.

  LOOP AT xml_content INTO xml_line.
    CONCATENATE xml_content_flat
                xml_line
           INTO xml_content_flat.
  ENDLOOP.

  CALL TRANSFORMATION zcustomer_st
    SOURCE XML xml_content_flat
    RESULT customers = customers.

  INSERT zcustomer FROM TABLE customers.
...


Organized Code

What if I say that the first few lines of code is responsible for uploading a specific XML file? Why wouldn't I create a simple subroutine, and call it as upload_xml.

The next few lines, the loop is responsible for converting the received internal table (content of the XML file, line by line) into a flat string. That's why, we are going to create another subroutine, and call it as convert_to_flat_string.

Then, the CALL TRANSFORMATION statement is responsible for parsing a flat XML file (XML content in a simple string format) into an ABAP Dictionary object, into an internal table. Let's create another subroutine, and call it as parse_xml.

At last, we perform an insert on the database, that means we want to insert the received customers into the database. That's why, we are going to create one more subroutine, and call it as insert_into_database.

This list of subroutine calls is the table of contents in our book (ABAP program). What do you think? At this stage, you don't care about how these subroutines are implemented, you only want to know the high-level workflow of the program, nothing more. That's the power of organized code, it organizes the code into levels (high-level, detailed-level) to help the readers understanding the code. First you read the list of function calls (table of contents), and then the implementations (chapters) one by one.

...
START-OF-SELECTION.
  PERFORM upload_xml CHANGING xml_content.

  PERFORM convert_to_flat_string USING    xml_content
                                 CHANGING xml_content_flat.

  PERFORM parse_xml USING    xml_content_flat
                    CHANGING customers.

  PERFORM insert_into_database USING customers.
...


Let's check the implementations (chapters). Here, I wrapped all of the logic above in the section, Unorganized Code into the separate subroutines based on the different responsibilities.

The upload_xml subroutine calls the GUI_UPLOAD function module that returns an internal table back with the content of the XML.

I wrapped the loop cycle into the subroutine, convert_to_flat_sting that loops through on the content of the XML, and concatenate the actual line into the flat string, called xml_content_flat.

Then, I put the simple transformation call into the subroutine, called parse_xml that returns back a customers list.

At last, the trivial one, I placed the insertion into the subroutine, called insert_into_database that actually performs the insertion. 

What do you think? Actually, the subroutine definitions forms a block that demarcates the different responsibilities from each other, and as a result we get a more transparent and readable code than before.

...
*&---------------------------------------------------------------------*
FORM upload_xml CHANGING xml_content TYPE string_tt.
*&---------------------------------------------------------------------*
  CALL FUNCTION 'GUI_UPLOAD'
    EXPORTING
      filename = 'C:\customers_with_attribute.xml'
    TABLES
      data_tab = xml_content.
ENDFORM.                    " UPLOAD_XML

*&---------------------------------------------------------------------*
FORM convert_to_flat_string USING    xml_content      TYPE string_tt
                            CHANGING xml_content_flat TYPE string.
*&---------------------------------------------------------------------*
  DATA xml_line LIKE LINE OF xml_content.

  LOOP AT xml_content INTO xml_line.
    CONCATENATE xml_content_flat
                xml_line
           INTO xml_content_flat.
  ENDLOOP.
ENDFORM.                    " CONVERT_TO_FLAT_STRING

*&---------------------------------------------------------------------*
FORM parse_xml USING    xml_content_flat TYPE string
               CHANGING customers        TYPE zcustomer_tt.
*&---------------------------------------------------------------------*
  CALL TRANSFORMATION zcustomer_st
    SOURCE XML xml_content_flat
    RESULT customers = customers.
ENDFORM.                    " PARSE_XML

*&---------------------------------------------------------------------*
FORM insert_into_database USING customers TYPE zcustomer_tt.
*&---------------------------------------------------------------------*
  INSERT zcustomer FROM TABLE customers.
ENDFORM.                    " INSERT_INTO_DATABASE
...


Summary

Functions are very useful, they help me a lot during my developments:

  • they can help you to break down a huge, seemingly unsolvable problem into small, interpretable tasks that you can implement much easier (upload -> convert -> parse -> insert), and it can help you to think in responsibilities,
  • they can help you to organize your code in a way that is easy to read and understand (you can avoid unnecessary comments with meaningful function names),
  • at last constructing generic functions (methods, subroutines, function modules, and so on) you can achieve the benefits of re-usability as well.

Ok, this code above only a simple example, but it demonstrates the basics of well-organized code. It's not a big magic, but can help you much more, than you think.

Now, I haven't covered any OO principles, design patterns, and agile methods neither, because it's another fairy tale :).

I hope you enjoyed it, stay tuned!

blog comments powered by Disqus