
I am not a great programmer, I am just a good programmer with great habits"- Kent Beck .
Think about a fresh doctor; unfortunately, there is a patient who has to suffer.
Think about a fresh advocate; unfortunately, there is a litigent who has to suffer.
Think about a fresh teacher; unfortunately, there are students who have to suffer.
Think about a fresh ABAP developer; unfortunately, there is a customer SAP System that has to suffer.
Experience is gold. It cannot be replaced by any means. There is someone who has to pay the price for your inexperience. I am not expecting anyone who reads this blog to wear into the shoes of a person with a decade of experience immediately. My thoughts are on how to mitigate the aftereffects of code that has been written by a brand new ABAP developer. At least based on my experience, the things I would have known in the beginning of my career. I came up with the below arguments in the light of the very early programs of which I wrote (oof which I am not proud) in my career.
Disclaimer: These points are not for any experienced/expert ABAP developers but only pointers for those who have just stepped into the ABAP world. But if ever the experienced finds this insightful, I am highly honored.
Understand the Process/Functional Story behind a requirement
Picture Courtesy: SAP Functional Consultant Services - ZyGen (zygencenter.com)
In the early part of my career, I made this mistake. Just think about an actor who is acting in a film without knowing the whole story of the film. He cannot portray a character well enough. It is the same when it comes to development in the SAP world. You may be sometimes pampered with a nice functional specification with all the technical fields and tables that you have to use in your program.
SAP development is not all about VBAK-VBELN = VBAP-VBELN. Do not think only from a technical perspective. Then it will be only a list of tables and fields, which have to be combined and calculated based on so-and-so conditions. You have to go through these tables and understand what these fields are. What are their relevances in the business? Are there other fields that have to be taken care of, 'like'status' fields, 'cancelation indicators,' and so on? (Many times this will be missed in the specifications.)
If you are dealing with a sales process, you should run the corresponding transactions, create data, and see the changes it makes on the master tables, related tables, and transaction tables. Try to cancel or reverse a transaction to see what effect it does have on database tables. Watch out for any custom fields in the interested database tables. Watch out for these fields in the transaction code and the enhancement programs developed with these custom fields.
Search on the internet, watch YouTube videos, and try all sorts of things to understand the functional side of your requirement. Last but not least, ask as many questions as possible to your process consultant to understand the whole process scenario behind the requirement.
Always make sure to review your first piece of productive code
Picture Courtesy: Code reviews: the big picture • Beanstalk Guides (beanstalkapp.com)
"Rome was not build in a day",
"Julius Caesar was not William Shakepseare's first work",
"Lionel Messi did not score in his first match for Barcelona".
So will be your first productive code. It may be with lot of flows and gaps. Find someone who is senior and more experienced who is generous enough to review your code. In the worst case scenario, if you have found none in your company , atleast ask random help from SAP experts in professional social networking platforms. Someone may turn out. Trust me it will make a world of difference to the next programs you write. It should not be like , you have written 100+ programs and you realize there were some terrible mistakes you did throughtout .
'Where Used List' is a powerful tool
Even though everyone knows about this tool , I started using this extensively later in my career.You have a good chance of finding good code from your collegues or even standard SAP code based on your requirement. The beauty of it is that, you can almost search every technical object with a 'Where Used List' and you will be gifted with a bunch of results. From function modules to CDS views, domains to dataelements , from searchhelps to database tables , it strech its hands all across.
I use where used list extensively when I want to declare some table types, range types or when i want to know how the input parameters are filled in BAPI's using programs . Using the already availabe table types and range type helps particularly with 'Typing' in method's signature . We are saved from declaring new 'Z' types and thus saves times and in the end less custom objects.
Search around quality inspection tools available
We all start with a header template like above. For me this is of huge responsibility. It is same like you start reading a book knowing about the author. When you write code, you are not writing code for yourself but the generations to come who may maintain your code. I do not want someone read my code and say to themselves 'Who the hell has written this code' and cursing me.It is like a story or poem you are going to write and has to palatable to its readers.
So what all things are around to check the quality of code you have written. The experienced will definitely know the first four and the last two are slowly making its entry into ABAP minds.
More insight about the the latest trends,
ABAP Tools for Clean ABAP | SAP Blogs
Do not forget about Unit Testing
Source: http://www.quickmeme.com/p/3vwox3/page/3
Sometimes unit testing sounds too much and time consuming . But it is a future proof / error proof(to an extend) modern development ideology.
It may come quite as a surprise that ABAP Units are there since SAP Netweaver 2004 release but not quite made it into the ABAP world.
Consider a scenario where two developers called Adam and Eve are working for same company. Adam took over a requirement, that is to calculate the price of a product deducting the rebate amount. He has done all the code accordingly and also wrote beautiful test cases.
REPORT zproductcost_calculate. PARAMETERS: p_prodt TYPE matnr . CLASS ltc_product_price DEFINITION DEFERRED . CLASS lcl_total_product_cost DEFINITION FRIENDS ltc_product_price. PUBLIC SECTION. METHODS: get_base_price IMPORTING iv_product TYPE matnr RETURNING VALUE(rv_base_price) TYPE netwr_ap , get_rebate_price IMPORTING iv_product TYPE matnr RETURNING VALUE(rv_rebate_price) TYPE netwr_ap , get_total_price IMPORTING iv_product TYPE matnr RETURNING VALUE(rv_total_price) TYPE netwr_ap . ENDCLASS. CLASS lcl_total_product_cost IMPLEMENTATION. METHOD get_base_price . SELECT SINGLE price FROM zprice_table INTO @rv_base_price WHERE matnr = @iv_product . ENDMETHOD. METHOD get_rebate_price . SELECT SINGLE rebate_amount FROM zrebate_table INTO @rv_rebate_price WHERE matnr = @iv_product. ENDMETHOD . METHOD get_total_price. SELECT SINGLE price FROM zprice_table INTO @DATA(base_price) WHERE matnr = @iv_product . SELECT SINGLE rebate_amount FROM zrebate_table INTO @DATA(rebate_price) WHERE matnr = @iv_product.. rv_total_price = base_price - rebate_price . ENDMETHOD . ENDCLASS. START-OF-SELECTION . DATA: o_product_price TYPE REF TO lcl_total_product_cost . CREATE OBJECT o_product_price. DATA(base_price) = o_product_price->get_base_price( iv_product = p_prodt ) . DATA(rebate_price) = o_product_price->get_rebate_price( iv_product = p_prodt ) . DATA(total_price) = o_product_price->get_total_price( iv_product = p_prodt ) . WRITE: 'Base Price:' , base_price , 'Rebate Price:' , rebate_price, 'Total Price:' , total_price .
Program Structure
*Disclaimer: You may think in the get_total_price method , the methods get_base_price and get_rebate_price could have been called directly. This is just to frame a scenario to explain the concept.
CLASS ltc_product_price DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT . PRIVATE SECTION . DATA: lto_product_price TYPE REF TO lcl_total_product_cost . METHODS: setup, test_for_get_base_price FOR TESTING , test_for_get_rebate_price FOR TESTING , test_for_get_total_price FOR TESTING , test_for_price_relationship FOR TESTING . ENDCLASS . CLASS ltc_product_price IMPLEMENTATION . METHOD setup . CREATE OBJECT lto_product_price. ENDMETHOD . METHOD test_for_get_base_price . DATA(base_price) = lto_product_price->get_base_price( iv_product = 'TEST_PRODUCT' ). cl_abap_unit_assert=>assert_not_initial( act = base_price msg = 'Product Price cannot be zero' ). ENDMETHOD . METHOD test_for_get_rebate_price . DATA(rebate_price) = lto_product_price->get_rebate_price( iv_product = 'TEST_PRODUCT' ). " Just assuming every product has rebate cl_abap_unit_assert=>assert_not_initial( act = rebate_price msg = 'Product has to be a rebate' ). ENDMETHOD. METHOD test_for_get_total_price . DATA(total_price) = lto_product_price->get_total_price( iv_product = 'TEST_PRODUCT' ). cl_abap_unit_assert=>assert_not_initial( act = total_price msg = 'Product should have a rebate amount' ). ENDMETHOD . METHOD test_for_price_relationship . DATA(base_price) = lto_product_price->get_base_price( iv_product = 'TEST_PRODUCT' ). DATA(rebate_price) = lto_product_price->get_rebate_price( iv_product = 'TEST_PRODUCT' ). DATA(total_price) = lto_product_price->get_total_price( iv_product = 'TEST_PRODUCT' ) . cl_abap_unit_assert=>assert_equals( act = base_price - rebate_price exp = total_price msg = 'Total price should be equal to the rebate price subtracted from base price' ). ENDMETHOD . ENDCLASS .
Test Class
And the test results looked clean and nice.
Unit Test Results
After some months the requirement got changed so that every product should have 5 euro more rebate regardless of the type of product and Eve was given the task.
She went straight to method and did this adjustment,
METHOD get_rebate_price . SELECT SINGLE rebate_amount FROM zrebate_table INTO @fixed_rebate_price WHERE matnr = @iv_product. rv_rebate_price = fixed_rebate_price + 5.00 . ENDMETHOD .
and again she ran the unit tests.
This time she gets an error in unit test framework , saying
'Total price should be equal to the rebate price subtracted from base price'
Failed Unit Test
She realises that it is not only the method get_rebate_price which has to be adjusted but also the method get_total_price.
METHOD get_total_price. SELECT SINGLE price FROM zprice_table INTO @DATA(base_price) WHERE matnr = @iv_product . SELECT SINGLE rebate_amount FROM zrebate_table INTO @DATA(rebate_price) WHERE matnr = @iv_product. rv_total_price = base_price - rebate_price - 5.00 . ENDMETHOD .
Now she again gets all green in her Unit test framework. This is the beauty of unit tests. You are writing code , checking whether it is working as intended, when some one jumps into your program for maintance helping them as well. Plus one of the main highlights of Unit testing is during code refactoring. You are refactoring the code and unit tests assure nothing is broke.
Idea Courtesy: I slightly adjusted the scenario mentioned by 10xcoding nestorlara in his blog(since outside SCN not mentioning) to come up with this unit test use case.
Always stay with the advanced available platforms to develop
If you started in 2000's , your first choice of (and may be only) development tool has to be SE38/SE80. In 2020's it has to be Eclipse. For the Frontend development it has to be Business Application Studio or Visual Studio Code. The new development platforms emerge because something is lacking in the older one , You should always adopt the latest to harvest the full benefits of all the new advancements happening in the ABAP or frontend programming world.
It will be good to get accustomed with the Eclipse mode of ABAP development before you are thrown into the world of CDS views and RAP's where Eclipse is the only way forward.
Always have the mindset to breakdown your code into small pieces
Picture Courtesy: How To Do Open, Axial, & Selective Coding in Grounded Theory — Delve (delvetool.com)
Spaghetti code is bad. Really really bad. Breaking problems into pieces is better and so is coding .
You get a feeling of neatness when you break down code into small methods. If needed, do not get hesitated from creating new classes. That is right way to OO . In the next point I am goind to give a good guiding point for an opensource project to upskill/understand your OO concepts.
Learn a lot from others code
Picture Courtesy: Why do my children need to learn to code? What’s all the fuss? | Life (news24.com)
For this point , I have already written a whole blog few years back.
https://blogs.sap.com/2018/08/30/learn-a-lot-from-others-code/
Plus ,do not forget that you have got a plethora of open source projects for you to sharpen your skills and to contribute. There you learn different coding styles , design patterns, product development skills and what not .
https://dotabap.org/
PS: ABAP Logger, ( https://github.com/ABAP-Logger/ABAP-Logger ) is my favorite. A beautifully written OO program that you can use to further enhance your OO understanding and something which you can use in your everyday programming life.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
3 | |
3 | |
3 | |
2 | |
2 | |
2 | |
2 | |
2 | |
2 | |
2 |