You are on page 1of 56

ABAP Code Refactoring

Techniques

Applies to:
All SAP Systems supporting object oriented programming. For more information, visit the ABAP homepage.

Summary
This tutorial explains the Code Refactoring Techniques based on example programs written in ABAP Objects

Author: Sukru Ilkel Birakoglu


Company: SAP LABS France
Created on: 06 July 2009

Author Bio
Sukru Ilkel Birakoglu is working as Senior Support Consultant in SAP Labs France. He is
developing in field of ECATT Test Tools at the moment.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 1
ABAP Code Refactoring Techniques

Table of Contents
1. Consolidate Duplicate Conditional Fragments ...............................................................................................3
2. Preserve whole object for method calls..........................................................................................................4
3. Decompose Conditional..................................................................................................................................8
4. Extract Method..............................................................................................................................................11
5. Introduce Explaining Variable.......................................................................................................................19
6. Split Temporary Variable ..............................................................................................................................22
7. Self Encapsulate Attributes of a Class .........................................................................................................23
8. Replace Literals and Numbers in Code with Constants ...............................................................................27
9. Replace Type Codes with Subclasses .........................................................................................................29
10. Introduce Null Object ..................................................................................................................................35
11. Separate Query and Modifier Methods.......................................................................................................42
12. Parameterize Method .................................................................................................................................45
13. Pull up Field in the Class Hierarchy............................................................................................................49
14. Pull up Method in the Class Hierarchy .......................................................................................................53
Copyright...........................................................................................................................................................56

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 2
ABAP Code Refactoring Techniques

1. Consolidate Duplicate Conditional Fragments


Explanation: If the same code fragment is used in all branches of a conditional expression then move it
outside the expression
Motivation:
• The code fragment which is executed in every branch of a conditional expression causes confusion
since it is normally not dependent on any condition
• Repetitive code means extra code to maintain if it is not encapsulated properly
Example Code Fragment:
Code Before Code Refactoring
*&---------------------------------------------------------------------*
*& Report ZSB_DUPL_COND_FRAGMENTS
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zsb_dupl_cond_fragments.

DATA : gv_price TYPE i VALUE 150,


gv_discount TYPE p DECIMALS 2.

IF gv_price > 100.


gv_discount = gv_price * '0.2'.
WRITE gv_discount. "=>Duplicate Code
ELSE.
gv_discount = gv_price * '0.1'.
WRITE gv_discount. "=>Duplicate Code
ENDIF.

Code After Code Refactoring


REPORT zsb_dupl_cond_fragments_rf.

DATA : gv_price TYPE i VALUE 150,


gv_discount TYPE p DECIMALS 2.

IF gv_price > 100.


gv_discount = gv_price * '0.2'.
ELSE.
gv_discount = gv_price * '0.1'.
ENDIF.

WRITE gv_discount.

In this refactoring, the common code fragment WRITE gv_discount. is moved outside the conditional
expression.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 3
ABAP Code Refactoring Techniques

2. Preserve whole object for method calls


Explanation: If you are using many attributes of an object instance as parameters of a method call you can
pass the whole object as a parameter instead of the attributes
Motivation:
• Increases the readability of clients calling the method with many parameters
• Simplifies the signature of the called method
Steps of Refactoring:
• Find out the method(s) to which many attributes of an object instance is being passed as parameter
• Delete these parameters from the signature of the method and add a new reference parameter
which references to the class of object instance holding the attributes
• In the body of the method replace the references to old parameters with references to the attributes
of the object instance passed as parameter
Example Code Fragment:
Code Before Code Refactoring
*&---------------------------------------------------------------------*
*& Report ZSB_PRESERVE_WHOLE_OBJECT
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zsb_preserve_whole_object.

*----------------------------------------------------------------------*
* CLASS lcl_order DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_order DEFINITION.
PUBLIC SECTION.
METHODS : constructor
IMPORTING
iv_id TYPE char5
iv_material_id TYPE char10
iv_quantity TYPE i
iv_unit TYPE char3
iv_unit_price TYPE i.

DATA : mv_id TYPE char5 READ-ONLY,


mv_material_id TYPE char10 READ-ONLY,
mv_quantity TYPE i READ-ONLY,
mv_unit TYPE char3 READ-ONLY,
mv_unit_price TYPE i.

ENDCLASS. "lcl_order DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_order_collector DEFINITION
*----------------------------------------------------------------------*
*

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 4
ABAP Code Refactoring Techniques

*----------------------------------------------------------------------*
CLASS lcl_order_collector DEFINITION.
PUBLIC SECTION.
CLASS-METHODS : write_total_order_price
IMPORTING
iv_id TYPE char5
iv_material_id TYPE char10
iv_quantity TYPE i
iv_unit TYPE char3
iv_unit_price TYPE i.

ENDCLASS. "lcl_order_collector DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_order IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_order IMPLEMENTATION.
METHOD constructor.
mv_id = iv_id.
mv_material_id = iv_material_id.
mv_unit = iv_unit.
mv_unit_price = iv_unit_price.
mv_quantity = iv_quantity.
ENDMETHOD. "constructor
ENDCLASS. "lcl_order IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS lcl_order_collector IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_order_collector IMPLEMENTATION.
METHOD write_total_order_price.

DATA : lv_total_order_price TYPE i.

lv_total_order_price = iv_quantity * iv_unit_price.


WRITE:/ 'The total price of order ', iv_id, ' for material ', iv_material_id,
' is ', lv_total_order_price.

ENDMETHOD. "write_total_order_price
ENDCLASS. "lcl_order_collector IMPLEMENTATION

DATA : go_order TYPE REF TO lcl_order.

START-OF-SELECTION.

CREATE OBJECT go_order


EXPORTING
iv_id = '001'
iv_material_id = 'MAT_A'
iv_quantity = '10'
iv_unit = 'EA'
iv_unit_price = 7.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 5
ABAP Code Refactoring Techniques

lcl_order_collector=>write_total_order_price(
EXPORTING
iv_id = go_order->mv_id
iv_material_id = go_order->mv_material_id
iv_quantity = go_order->mv_quantity
iv_unit = go_order->mv_unit
iv_unit_price = go_order->mv_unit_price ).

CodeAfter Code Refactoring


*&---------------------------------------------------------------------*
*& Report ZSB_PRESERVE_WHOLE_OBJECT_RF
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT ZSB_PRESERVE_WHOLE_OBJECT_RF.
*----------------------------------------------------------------------*
* CLASS lcl_order DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_order DEFINITION.
PUBLIC SECTION.
METHODS : constructor
IMPORTING
iv_id TYPE char5
iv_material_id TYPE char10
iv_quantity TYPE i
iv_unit TYPE char3
iv_unit_price TYPE i.

DATA : mv_id TYPE char5 READ-ONLY,


mv_material_id TYPE char10 READ-ONLY,
mv_quantity TYPE i READ-ONLY,
mv_unit TYPE char3 READ-ONLY,
mv_unit_price TYPE i.

ENDCLASS. "lcl_order DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_order_collector DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_order_collector DEFINITION.
PUBLIC SECTION.
CLASS-METHODS : write_total_order_price
IMPORTING
io_order type ref to lcl_order.

ENDCLASS. "lcl_order_collector DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_order IMPLEMENTATION

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 6
ABAP Code Refactoring Techniques

*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_order IMPLEMENTATION.
METHOD constructor.
mv_id = iv_id.
mv_material_id = iv_material_id.
mv_unit = iv_unit.
mv_unit_price = iv_unit_price.
mv_quantity = iv_quantity.
ENDMETHOD. "constructor
ENDCLASS. "lcl_order IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS lcl_order_collector IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_order_collector IMPLEMENTATION.
METHOD write_total_order_price.

DATA : lv_total_order_price TYPE i.


lv_total_order_price = io_order->mv_quantity * io_order->mv_unit_price .
WRITE:/ 'The total price of order ', io_order->mv_id, '
for material ', io_order->mv_material_id,
' is ', lv_total_order_price.

ENDMETHOD. "write_total_order_price
ENDCLASS. "lcl_order_collector IMPLEMENTATION

DATA : go_order TYPE REF TO lcl_order.

START-OF-SELECTION.

CREATE OBJECT go_order


EXPORTING
iv_id = '001'
iv_material_id = 'MAT_A'
iv_quantity = '10'
iv_unit = 'EA'
iv_unit_price = 7.

lcl_order_collector=>write_total_order_price(
EXPORTING
io_order = go_order ).

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 7
ABAP Code Refactoring Techniques

3. Decompose Conditional
Explanation: If complicated operations are executed on each branch of a conditional statement,
encapsulate these operations in separate methods
Motivation:
• Increases the readability and maintainablity of the code
• Groups complicated operations in separate logical units
• Keeps the code from deep if..else statements which makes the code error prone
Steps of Refactoring:
• Find out the conditional expressions in your code which have many complicated operations in each
branch
• Create one or more methods which encapsulate these operations
Example Code Fragment:
Code Before Code Refactoring
*&---------------------------------------------------------------------*
*& Report ZSB_DECOMPOSE_CONDITIONAL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zsb_decompose_conditional.

CONSTANTS : gc_person TYPE i VALUE '1',


gc_company TYPE i VALUE '2'.

DATA : gv_customer_1 TYPE i VALUE '1',


gv_product_price TYPE i VALUE '10',
gv_reduction TYPE p DECIMALS 2.

IF gv_customer_1 EQ gc_person.
IF gv_product_price > 8.
gv_reduction = gv_product_price * '0.1'.
ELSE.
gv_reduction = gv_product_price * '0.05'.
ENDIF.
ELSEIF gv_customer_1 EQ gc_company.
IF gv_product_price > 6.
gv_reduction = gv_product_price * '0.2'.
ELSE.
gv_reduction = gv_product_price * '0.15'.
ENDIF.
ENDIF.

WRITE / gv_reduction.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 8
ABAP Code Refactoring Techniques

Code After Code Refactoring


*&---------------------------------------------------------------------*
*& Report ZSB_DECOMPOSE_CONDITIONAL_RF
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zsb_decompose_conditional.

types : gty_decimal type p decimals 2.

CONSTANTS : gc_person TYPE i VALUE '1',


gc_company TYPE i VALUE '2'.

DATA : gv_customer_1 TYPE i VALUE '1',


gv_product_price TYPE i VALUE '10',
gv_reduction TYPE p DECIMALS 2.

*----------------------------------------------------------------------*
* CLASS lcl_reduction_calculator DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_reduction_calculator DEFINITION.
PUBLIC SECTION.
CLASS-METHODS : get_person_reduction
IMPORTING
iv_product_price TYPE i
RETURNING value(rv_reduction)
TYPE gty_decimal,

get_company_reduction
IMPORTING
iv_product_price TYPE i
RETURNING value(rv_reduction)
TYPE gty_decimal.

ENDCLASS. "lcl_reduction_calculator DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_reduction_calculator IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_reduction_calculator IMPLEMENTATION.
METHOD get_person_reduction.
IF iv_product_price > 8.
rv_reduction = iv_product_price * '0.1'.
ELSE.
rv_reduction = iv_product_price * '0.05'.
ENDIF.
ENDMETHOD. "get_person_reduction

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 9
ABAP Code Refactoring Techniques

METHOD get_company_reduction.
IF iv_product_price > 6.
rv_reduction = iv_product_price * '0.2'.
ELSE.
rv_reduction = iv_product_price * '0.15'.
ENDIF.
ENDMETHOD. "get_company_reduction
ENDCLASS. "lcl_reduction_calculator IMPLEMENTATION

START-OF-SELECTION.

IF gv_customer_1 EQ gc_person.
gv_reduction = lcl_reduction_calculator=>get_person_reduction(
gv_product_price ).
ELSEIF gv_customer_1 EQ gc_company.
gv_reduction = lcl_reduction_calculator=>get_person_reduction(
gv_product_price ).
ENDIF.

WRITE / gv_reduction.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 10
ABAP Code Refactoring Techniques

4. Extract Method
Explanation : If the code in the body of a method is too long, you use too many local variables in the
method and you have long comments for certain code fragments in the code, turn that fragment of code into
its own method
Motivation:
• Increases the readability of higher level and client methods using this code.
• The code fragment turned into a method can be reused
• Code fragments which are turned into a method can be overridden in a subclass if overriding is
foreseen for this fragment of code
Steps of Refactoring:
• Find out the code fragments which can be encapsulated into new methods
• Create ea new method with an explanatory name and copy the code fragment into the body of the
newly created method
• The parameters and local variables of the new method consist of the local variables referenced in
the old code fragment. Create the parameters and the local variables of the new method based on
this information.
Example Code Fragment:
Code Before Code Refactoring
REPORT zsb_extract_method.

*----------------------------------------------------------------------*
* CLASS lcl_bank DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_bank DEFINITION.
PUBLIC SECTION.

TYPES : ty_interest TYPE p LENGTH 8 DECIMALS 3.


CLASS-METHODS : calculate_interest
IMPORTING
iv_capital_amount TYPE i
iv_interest_rate TYPE i
iv_no_of_months TYPE i
RETURNING value(rv_interest_amount) TYPE ty_interest.

ENDCLASS. "lcl_bank DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_bank IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_bank IMPLEMENTATION.
METHOD calculate_interest.

DATA : lv_last_capital TYPE ty_interest,


lv_interest_in_percent TYPE ty_interest,
lv_interest_amount TYPE ty_interest.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 11
ABAP Code Refactoring Techniques

*Write header information


WRITE / 'Calculating interest'.
ULINE.
WRITE: / 'Capital Amount:', iv_capital_amount.
WRITE: / 'Interest Rate in Percent:', iv_interest_rate.
WRITE: / 'Number of months :', iv_no_of_months.

*Calculate Interest Rate


lv_interest_in_percent = iv_interest_rate / 100.
lv_last_capital = iv_capital_amount.
DO iv_no_of_months TIMES.
lv_interest_amount = lv_last_capital * lv_interest_in_percent.
lv_last_capital = lv_last_capital + lv_interest_amount.
add lv_interest_amount to rv_interest_amount.
ENDDO.

*Write footer information


ULINE.
WRITE :/ 'Interest amount is calculated for:', sy-uname.
WRITE :/ 'Calculated interest amount :', rv_interest_amount.

ENDMETHOD. "calculate_interest
ENDCLASS. "lcl_bank IMPLEMENTATION

START-OF-SELECTION.

DATA : gv_interest_amount TYPE lcl_bank=>ty_interest.

gv_interest_amount = lcl_bank=>calculate_interest(
iv_capital_amount = 100
iv_interest_rate = 5
iv_no_of_months = 4
).

Code After Code Refactoring


REPORT zsb_extract_method.

*----------------------------------------------------------------------*
* CLASS lcl_bank DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_bank DEFINITION.
PUBLIC SECTION.

TYPES : ty_interest TYPE p LENGTH 8 DECIMALS 3.


CLASS-METHODS : calculate_interest
IMPORTING
iv_capital_amount TYPE i
iv_interest_rate TYPE i
iv_no_of_months TYPE i
RETURNING value(rv_interest_amount) TYPE

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 12
ABAP Code Refactoring Techniques

ty_interest.

PRIVATE SECTION.
CLASS-METHODS write_header
IMPORTING
iv_capital_amount TYPE i
iv_interest_rate TYPE i
iv_no_of_months TYPE i
.

CLASS-METHODS calculate_interest_amount
IMPORTING
iv_capital_amount TYPE i
iv_interest_rate TYPE i
iv_no_of_months TYPE i
CHANGING
cv_interest_amount TYPE ty_interest
.

CLASS-METHODS write_footer
IMPORTING
iv_interest_amount TYPE ty_interest.
ENDCLASS. "lcl_bank DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_bank IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_bank IMPLEMENTATION.

METHOD write_footer.
ULINE.
WRITE :/ 'Interest amount is calculated for:', sy-uname.
WRITE :/ 'Calculated interest amount :', iv_interest_amount.
ENDMETHOD. "write_footer

METHOD write_header .
WRITE / 'Calculating interest'.
ULINE.
WRITE: / 'Capital Amount:', iv_capital_amount.
WRITE: / 'Interest Rate in Percent:', iv_interest_rate.
WRITE: / 'Number of months :', iv_no_of_months.
ENDMETHOD. "write_header

METHOD calculate_interest_amount .
DATA lv_interest_amount TYPE ty_interest .
DATA lv_interest_in_percent TYPE ty_interest .
DATA lv_last_capital TYPE ty_interest .

lv_interest_in_percent = iv_interest_rate / 100.

lv_last_capital = iv_capital_amount.
DO iv_no_of_months TIMES.
lv_interest_amount = lv_last_capital * lv_interest_in_percent.
lv_last_capital = lv_last_capital + lv_interest_amount.
ADD lv_interest_amount TO cv_interest_amount.
ENDDO.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 13
ABAP Code Refactoring Techniques

ENDMETHOD. "calculate_interest_amount
METHOD calculate_interest.

DATA : lv_last_capital TYPE ty_interest,


lv_interest_in_percent TYPE ty_interest,
lv_interest_amount TYPE ty_interest.

*Write header information


write_header(
EXPORTING
iv_capital_amount = iv_capital_amount
iv_interest_rate = iv_interest_rate
iv_no_of_months = iv_no_of_months
).

*Calculate Interest Rate


calculate_interest_amount(
EXPORTING
iv_capital_amount = iv_capital_amount
iv_interest_rate = iv_interest_rate
iv_no_of_months = iv_no_of_months
CHANGING
cv_interest_amount = rv_interest_amount
).

*Write footer information


write_footer(
EXPORTING
iv_interest_amount = rv_interest_amount
).

ENDMETHOD. "calculate_interest
ENDCLASS. "lcl_bank IMPLEMENTATION

START-OF-SELECTION.

DATA : gv_interest_amount TYPE lcl_bank=>ty_interest.

gv_interest_amount = lcl_bank=>calculate_interest(
iv_capital_amount = 100
iv_interest_rate = 5
iv_no_of_months = 4
).

Explanation of Refactoring Done in Code


The method CALCULATE_INTEREST of class LCL_BANK consists of three main block which write the
header data, calculates the interest amount and write the footer data. These three code fragments were
extracted into their own methods for better readablity of code.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 14
ABAP Code Refactoring Techniques

ABAP Workbench Support for this Refactoring:


Step 1: Select the code fragment you want to turn out into a new method, and follow the path Refactoring-
>Extract Source

Step 2: The refactoring wizard appears on the screen. Press continue button on the first screen of the
wizard

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 15
ABAP Code Refactoring Techniques

Step 3: In the next screen of the refactoring assistant , enter the name of the method which will be added to
the class and have the code fragment we selected as its body. You can also select the visibility area of the
class to which the method will be added

Step 4: Check the data on the screen and press the Continue button to finish the code refactoring

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 16
ABAP Code Refactoring Techniques

The new method WRITE_HEADER is added to the private section of class LCL_BANK by the refactoring
assistant as below

The code fragment in the method CALCULATE_INTEREST which is selected for extraction is replaced by
the call of new method WRITE_HEADER

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 17
ABAP Code Refactoring Techniques

Step 5: After you create methods for all code fragments you want to extract some local variables of the
method CALCULATE_INTEREST becomes obsolete. These obsolete variables can aslo be deleted
automatically using the refactoring assistant. Right click the mouse button in the body of the method of
which useless local variables and follow the path Refactoring->Delete Unused Data Declarations.

As a result, the local variables lv_last_capital, lv_interest_in_percent and lv_interest_amount are deleted in
method CALCULATE_INTEREST.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 18
ABAP Code Refactoring Techniques

5. Introduce Explaining Variable


Explanation: If you have a complicated expression as a part of a conditonal expression or computation put
the results of this expression in a temporary variable which explains the purpose and semantic of the
expression
Motivation:
• Increases the readability of complex expressions
• Simplifies the conditional expressions
• Breaks down long computations into understandable and manageable units
Steps of Refactoring:
• Declare a new variable for assigning the value of the result of the complex expression and replace all
occurrences of the complex expression with the new variable
• Compile your code and run your ABAP Units
Example Code Fragment:
Code Before Code Refactoring
REPORT zsb_introduce_variable.

*----------------------------------------------------------------------*
* CLASS lcl_price_calculator DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_price_calculator DEFINITION.
PUBLIC SECTION.
CLASS-METHODS : calculate_total_price
IMPORTING
iv_product_name TYPE string
iv_no_of_products TYPE i
iv_customer_type TYPE string
EXPORTING
ev_total_price TYPE p.

CONSTANTS : BEGIN OF c_product_name,


computer TYPE string VALUE 'COMPUTER',
book TYPE string VALUE 'BOOK',
END OF c_product_name,

BEGIN OF c_customer_type,
frequent TYPE string VALUE 'FREQUENT',
rare TYPE string VALUE 'RARE',
first_time TYPE string VALUE 'FIRST_TIME',
normal TYPE string VALUE 'NORMAL',
END OF c_customer_type.

ENDCLASS. "lcl_price_calculator DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_price_calculator IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 19
ABAP Code Refactoring Techniques

CLASS lcl_price_calculator IMPLEMENTATION.


METHOD calculate_total_price.

IF iv_product_name = c_product_name-computer AND


iv_customer_type = c_customer_type-first_time AND
iv_no_of_products > 1.

ev_total_price = 1100 * iv_no_of_products - ( 5 * iv_no_of_products ).

ELSEIF iv_product_name = c_product_name-computer AND


iv_no_of_products > 10.

ev_total_price = 1100 - ( 5 * iv_no_of_products ) - 200 .

ELSEIF iv_product_name = c_product_name-book AND


iv_no_of_products < 200.

ev_total_price = 15 * iv_no_of_products + 2 * iv_no_of_products.

ENDIF.
ENDMETHOD. "calculate_total_price
ENDCLASS. "lcl_price_calculator IMPLEMENTATION

Code After Code Refactoring


REPORT zsb_introduce_variable.
*----------------------------------------------------------------------*
* CLASS lcl_price_calculator DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_price_calculator DEFINITION.
PUBLIC SECTION.
CLASS-METHODS : calculate_total_price
IMPORTING
iv_product_name TYPE string
iv_no_of_products TYPE i
iv_customer_type TYPE string
EXPORTING
ev_total_price TYPE p.

CONSTANTS : BEGIN OF c_product_name,


computer TYPE string VALUE 'COMPUTER',
book TYPE string VALUE 'BOOK',
END OF c_product_name,

BEGIN OF c_customer_type,
frequent TYPE string VALUE 'FREQUENT',
rare TYPE string VALUE 'RARE',
first_time TYPE string VALUE 'FIRST_TIME',
normal TYPE string VALUE 'NORMAL',
END OF c_customer_type.

ENDCLASS. "lcl_price_calculator DEFINITION

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 20
ABAP Code Refactoring Techniques

*----------------------------------------------------------------------*
* CLASS lcl_price_calculator IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_price_calculator IMPLEMENTATION.
METHOD calculate_total_price.

DATA : lv_is_risky_sell TYPE abap_bool,


lv_is_big_sell TYPE abap_bool,
lv_is_ordinary_sell TYPE abap_bool,
lv_base_price TYPE i,
lv_discount TYPE i,
lv_delivery_costs type i.
lv_is_risky_sell = boolc( iv_product_name = c_product_name-computer AND
iv_customer_type = c_customer_type-first_time AND
iv_no_of_products > 1 ).

lv_is_big_sell = boolc( iv_product_name = c_product_name-computer AND


iv_no_of_products > 10 ).

lv_is_ordinary_sell = boolc( iv_product_name = c_product_name-book AND


iv_no_of_products < 200 ).

IF lv_is_risky_sell = abap_true.

lv_base_price = 1100 * iv_no_of_products.


lv_discount = 5 * iv_no_of_products.

ev_total_price = lv_base_price - lv_discount.

ELSEIF lv_is_big_sell = abap_true.

lv_base_price = 1100 * iv_no_of_products + 200.


lv_discount = 5 * iv_no_of_products.
ev_total_price = lv_base_price - lv_discount.

ELSEIF lv_is_ordinary_sell = abap_true.

lv_base_price = 15 * iv_no_of_products.
lv_delivery_costs = 2 * iv_no_of_products.
ev_total_price = lv_base_price + lv_delivery_costs.

ENDIF.
ENDMETHOD. "calculate_total_price
ENDCLASS.

Explanation of Refactoring Done in Code:


The method CALCULATE_TOTAL_PRICE of class LCL_PRICE_CALCULATOR is used for calculating the
total price of an order given by a customer. As it can be easily understood from the code, the total price of
the order depends on the order size and customer type. The different combinations of order size and
customer type were expressed in complicated conditional statements. These complicated conditional
expressions were assigned to temporary variables which explain the semantic meaning of the conditional
expression. The price calculation was also separated into to parts, which are base price and discount
amount, this makes also the code easier to understand and maintain.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 21
ABAP Code Refactoring Techniques

6. Split Temporary Variable


Explanation: If you have a temporary local variable to which values are assigned in different contexts and
this variable is not a collecting variable or loop variable, make a separate temporary variable for each
assignment
Motivation:
• Assigning different responsibilities to the same temporary variable confuses the reader of the code .
Using separate temporary variables for different responsibilities remedies this problem
• Initialization problems which occur because of using the same temporary variable in different
contexts can result in bugs
Steps of Refactoring:
• Declare a new variable for each use of a temporary variable which occurs in different contexts of
code and has another semantic meaning in each context
• Replace the occurrences of the temporary variable with the new variables
• Compile your code and run your ABAP Units
Example Code Fragment:
Code Before Code Refactoring
REPORT zsb_split_variable.

DATA : lv_temp TYPE i,


lv_no_of_units TYPE i VALUE 10,
lv_unit_price TYPE i VALUE 2,
lv_no_of_workers TYPE i VALUE '40',
lv_worker_salary TYPE i VALUE '800'.

lv_temp = lv_no_of_units * lv_unit_price.


WRITE / lv_temp.

lv_temp = lv_no_of_workers * lv_worker_salary.


WRITE / lv_temp.

Code After Code Refactoring


REPORT zsb_split_variable.

DATA : lv_total_price TYPE i,


lv_total_salary TYPE i,
lv_no_of_units TYPE i VALUE 10,
lv_unit_price TYPE i VALUE 2,
lv_no_of_workers TYPE i VALUE '40',
lv_worker_salary TYPE i VALUE '800'.

lv_total_price = lv_no_of_units * lv_unit_price.


WRITE / lv_total_price.

lv_total_salary = lv_no_of_workers * lv_worker_salary.


WRITE / lv_total_salary.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 22
ABAP Code Refactoring Techniques

Explanation of Refactoring Done in Code:


In the first report, the temporary variable lv_temp is used for assigning the total value of an order given and
the total salary of workers in the company. Since the name lv_temp does not have any meaning and occurs
in two different contexts with two totally different meanings, it can be diffocult for the reader of the code to
understand the meaning of this variable. In the second report, this temporary variable is replaced with two
variables with names lv_total_price and lv_total_salary and this change makes this fragment of code clearer.

7. Self Encapsulate Attributes of a Class

Explanation: If you are accessing the attributes of a class inside and outside of the class directly and it
results in coupling between different code fragments, you can encapsulate the attributes in setter and getter
methods
Motivation:
• Hides the details of accessing or initialization of attributes
• Decouples client from the server with respect to the usage of attributes
• Allows subclasses of the server class to override the initialization or reading strategy of attributes
Steps of Refactoring:
• Create Setter and Getter methods for the attributes of the class
• Find all references to the attributes of the class and replace them with setter or getter method calls
• Change the visibility of your attributes to protected / private according to your needs
• Compile your code and run your ABAP Units

Code Before Code Refactoring


&---------------------------------------------------------------------*
*& Report ZSB_REFACT_ENCAPSULATE_ATTR
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zsb_refact_encapsulate_attr.

*----------------------------------------------------------------------*
* CLASS lcl_customer DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_customer DEFINITION.
PUBLIC SECTION.

TYPES : ty_cust_id TYPE n LENGTH 10.

CONSTANTS : c_customer_person TYPE i VALUE 1,


c_customer_company TYPE i VALUE 1.

DATA : mv_id TYPE n LENGTH 10,


mv_type TYPE i,
mv_adress TYPE string,

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 23
ABAP Code Refactoring Techniques

mv_name TYPE string,


mv_surname TYPE string.

METHODS : constructor
IMPORTING iv_id TYPE ty_cust_id
iv_type TYPE i
iv_name TYPE string OPTIONAL
iv_surname TYPE string OPTIONAL
iv_adress TYPE string.

ENDCLASS. "lcl_customer DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_customer IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_customer IMPLEMENTATION.

METHOD constructor.
mv_id = iv_id.
mv_type = iv_type.
mv_adress = iv_adress.
mv_name = iv_name.
mv_surname = iv_surname.
ENDMETHOD. "constructor

ENDCLASS. "lcl_customer IMPLEMENTATION

DATA : lo_customer TYPE REF TO lcl_customer.

START-OF-SELECTION.

CREATE OBJECT lo_customer


EXPORTING
iv_id =1
iv_type = lcl_customer=>c_customer_person
iv_name = 'John'
iv_surname = 'Doe'
iv_adress = 'Sesame Street, 10'.

WRITE lo_customer->mv_name.
WRITE lo_customer->mv_surname.
lo_customer->mv_adress = 'Sesame Street, 11'.

Code After Code Refactoring


*&---------------------------------------------------------------------*
*& Report ZSB_REFACT_ENCAPS_ATTR
*&
*&---------------------------------------------------------------------*
*&

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 24
ABAP Code Refactoring Techniques

*&
*&---------------------------------------------------------------------*

REPORT zsb_refact_encaps_attr.

*----------------------------------------------------------------------*
* CLASS lcl_customer DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_customer DEFINITION.
PUBLIC SECTION.

TYPES : ty_cust_id TYPE n LENGTH 10.

CONSTANTS : c_customer_person TYPE i VALUE 1,


c_customer_company TYPE i VALUE 1.

DATA : mv_id TYPE n LENGTH 10,


mv_type TYPE i,
mv_adress TYPE string,
mv_name TYPE string,
mv_surname TYPE string.

METHODS : constructor
IMPORTING iv_id TYPE ty_cust_id
iv_type TYPE i
iv_name TYPE string OPTIONAL
iv_surname TYPE string OPTIONAL
iv_adress TYPE string,

set_type IMPORTING iv_type TYPE i,


set_name IMPORTING iv_name TYPE string,
set_surname IMPORTING iv_surname TYPE string,
set_adress IMPORTING iv_adress TYPE string,

get_type RETURNING value(rv_type) TYPE i,


get_name RETURNING value(rv_name) TYPE string,
get_surname RETURNING value(rv_surname) TYPE string,
get_adress RETURNING value(rv_adress) TYPE string.

ENDCLASS. "lcl_customer DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_customer IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_customer IMPLEMENTATION.

METHOD constructor.
mv_id = iv_id.
set_type( iv_type ).
set_adress( iv_adress ).
set_name( iv_name ).
set_surname( iv_surname ).

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 25
ABAP Code Refactoring Techniques

ENDMETHOD. "constructor

METHOD set_type.
mv_type = iv_type.
ENDMETHOD. "set_type

METHOD set_name.
mv_name = iv_name.
ENDMETHOD. "set_name

METHOD set_surname.
mv_surname = iv_surname.
ENDMETHOD. "set_surname

METHOD set_adress.
mv_adress = iv_adress.
ENDMETHOD. "set_adress

METHOD get_type.
rv_type = mv_type.
ENDMETHOD. "get_type

METHOD get_name.
rv_name = mv_name.
ENDMETHOD. "get_name

METHOD get_surname.
rv_surname = mv_surname.
ENDMETHOD. "get_surname

METHOD get_adress.
rv_adress = mv_adress.
ENDMETHOD. "get_adress
ENDCLASS. "lcl_customer IMPLEMENTATION

DATA : lo_customer TYPE REF TO lcl_customer,


lv_name TYPE string.

START-OF-SELECTION.

CREATE OBJECT lo_customer


EXPORTING
iv_id = 1
iv_type = lcl_customer=>c_customer_person
iv_name = 'John'
iv_surname = 'Doe'
iv_adress = 'Sesame Street, 10'.

lv_name = lo_customer->get_name( ).
WRITE lv_name.
lo_customer->set_adress( 'Sesame Street, 11' ).

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 26
ABAP Code Refactoring Techniques

8. Replace Literals and Numbers in Code with Constants


Explanation: If you are using numbers and constants in your code with a specific meaning , you can create
constants named after these meanings and replace the literals and numbers in your code with these
constants
Motivation:
• Constants help to figure out the meaning of numbers and literals in code
• Makes it easier to make changes if you need to change the value of these numbers or literals in your
code. You have to change the value only at the constant definition
Steps of Refactoring:
• Declare a constant and set it the value of the literal / number used in code
• Find all occurrences of the number / literal in code and replace them with the constant
• Compile your code and run your ABAP Units

Code Before Code Refactoring


*&---------------------------------------------------------------------*
*& Report ZSB_REPLACE_LITERALS
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zsb_replace_literals.

DATA : lv_unit_price TYPE i,


lv_number_of_units_sold TYPE i,
lv_customer_type TYPE c LENGTH 1,
lv_total_price TYPE i.

lv_customer_type = 'P'.
lv_number_of_units_sold = 20.

IF lv_customer_type EQ 'P'.
lv_unit_price = 10.
ELSEIF lv_customer_type EQ 'C'.
lv_unit_price = 9.
ELSEIF lv_customer_type EQ 'U'.
lv_unit_price = 6.
ENDIF.

lv_total_price = lv_unit_price * lv_number_of_units_sold.

IF lv_customer_type EQ 'P'.
WRITE :/ 'The total price for a person is ', lv_total_price.
ELSEIF lv_customer_type EQ 'C'.
WRITE :/ 'The total price for a company is', lv_total_price.
ELSEIF lv_customer_type EQ 'U'.
WRITE :/ 'The total price for a university is', lv_total_price.
ENDIF.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 27
ABAP Code Refactoring Techniques

Code After Code Refactoring


*&---------------------------------------------------------------------*
*& Report ZSB_REPLACE_LITERALS
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zsb_replace_literals.

CONSTANTS : c_customer_person TYPE c LENGTH 1 VALUE 'P',


c_customer_company TYPE c LENGTH 1 VALUE 'C',
c_customer_university TYPE c LENGTH 1 VALUE 'U'.

DATA : lv_unit_price TYPE i,


lv_number_of_units_sold TYPE i,
lv_customer_type TYPE c LENGTH 1,
lv_total_price TYPE i.

lv_customer_type = c_customer_person.
lv_number_of_units_sold = 20.

IF lv_customer_type EQ c_customer_person.
lv_unit_price = 10.
ELSEIF lv_customer_type EQ c_customer_company.
lv_unit_price = 9.
ELSEIF lv_customer_type EQ c_customer_university.
lv_unit_price = 6.
ENDIF.

lv_total_price = lv_unit_price * lv_number_of_units_sold.

IF lv_customer_type EQ c_customer_person.
WRITE :/ 'The total price for a person is ', lv_total_price.
ELSEIF lv_customer_type EQ c_customer_company.
WRITE :/ 'The total price for a company is', lv_total_price.
ELSEIF lv_customer_type EQ c_customer_university.
WRITE :/ 'The total price for a university is', lv_total_price.
ENDIF.

Explanation of Refactoring Done in Code:


The unit price of a product sold depends on the type of customer buying it. In the first report, the type of
customers are represented by literals P, C and U for Person, Company and University. In the second report,
constants are defined at the beginning of the report to represent customer types. By doing this change in
code, we make our program more readable and the constants we have created give us more information
about the semantic meaning of the literals used in code. Another advantage is that, we can change the
constant value at one place in code and it would take affect on whole program in one go.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 28
ABAP Code Refactoring Techniques

9. Replace Type Codes with Subclasses


Explanation: If you have an immutable type code which affects the behavior of a class, you can replace the
type code with subclasses
Motivation:
• Type codes result in many case-endcase or if-endif statements in code which makes it difficult to
handle and maintain
• Encapsulating the different behavior in different classes makes the code easier to extend
Steps of Refactoring:
• For each value of a type code create a separate subclass
• Move the related code for each type code into the corresponding subclass
• Remove the type code field from the superclass

• Example Code Fragment:

In the example application, the types of vehicles will be first handled using a type code and then by using
subclasses.

Code Before Code Refactoring


*&---------------------------------------------------------------------*
*& Report ZSB_REPLACE_TYPE_CODE
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zsb_replace_type_code.

*----------------------------------------------------------------------*
* CLASS lcl_vehicle DEFINITION
*----------------------------------------------------------------------*
*

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 29
ABAP Code Refactoring Techniques

*----------------------------------------------------------------------*
CLASS lcl_vehicle DEFINITION.
PUBLIC SECTION.
CONSTANTS : c_car TYPE i VALUE 1,
c_truck TYPE i VALUE 2,
c_bus TYPE i VALUE 3.

METHODS : constructor
IMPORTING iv_vehicle_type TYPE i,

get_vehicle_name
RETURNING value(rv_vehicle_name) TYPE string,

get_maximum_velocity
RETURNING value(rv_maximum_velocity) TYPE i.

PRIVATE SECTION.
DATA : mv_vehicle_type TYPE i.
ENDCLASS. "lcl_vehicle DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_vehicle IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_vehicle IMPLEMENTATION.

METHOD constructor.
mv_vehicle_type = iv_vehicle_type.
ENDMETHOD. "constructor

METHOD get_vehicle_name.
CASE mv_vehicle_type.
WHEN c_car.
rv_vehicle_name = 'Car'.
WHEN c_bus.
rv_vehicle_name = 'Bus'.
WHEN c_truck.
rv_vehicle_name = 'Truck'.
ENDCASE.
ENDMETHOD. "get_vehicle_name

METHOD get_maximum_velocity.
CASE mv_vehicle_type.
WHEN c_car.
rv_maximum_velocity = 200.
WHEN c_bus.
rv_maximum_velocity = 180.
WHEN c_truck.
rv_maximum_velocity = 120.
ENDCASE.

ENDMETHOD. "get_maximum_velocity
ENDCLASS. "lcl_vehicle DEFINITION

DATA : go_vehicle_1 TYPE REF TO lcl_vehicle,


go_vehicle_2 TYPE REF TO lcl_vehicle,
gv_vehicle_name TYPE string.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 30
ABAP Code Refactoring Techniques

START-OF-SELECTION.
CREATE OBJECT go_vehicle_1
EXPORTING
iv_vehicle_type = lcl_vehicle=>c_car.

CREATE OBJECT go_vehicle_2


EXPORTING
iv_vehicle_type = lcl_vehicle=>c_truck.

gv_vehicle_name = go_vehicle_1->get_vehicle_name( ).
WRITE / gv_vehicle_name.

gv_vehicle_name = go_vehicle_2->get_vehicle_name( ).
WRITE / gv_vehicle_name.
Code After Code Refactoring
*&---------------------------------------------------------------------*
*& Report ZSB_REPLACE_TYPE_CODE_AFTER
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zsb_replace_type_code_after.

*----------------------------------------------------------------------*
* CLASS lcl_vehicle DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_vehicle DEFINITION ABSTRACT.
PUBLIC SECTION.

CONSTANTS: c_car TYPE i VALUE 1,


c_bus TYPE i VALUE 2,
c_truck TYPE i VALUE 3.

METHODS :
get_vehicle_name ABSTRACT
RETURNING value(rv_vehicle_name) TYPE string,

get_maximum_velocity ABSTRACT
RETURNING value(rv_maximum_velocity) TYPE i,

get_type ABSTRACT
RETURNING value(rv_vehicle_type) TYPE i.

CLASS-METHODS : create_vehicle
IMPORTING iv_vehicle_type TYPE i
RETURNING value(rv_vehicle) TYPE REF TO lcl_vehicle.
PRIVATE SECTION.
DATA : mv_vehicle_type TYPE i.
ENDCLASS. "lcl_vehicle DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_car DEFINITION

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 31
ABAP Code Refactoring Techniques

*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_car DEFINITION INHERITING FROM lcl_vehicle.
PUBLIC SECTION.
METHODS : get_maximum_velocity REDEFINITION,
get_type REDEFINITION,
get_vehicle_name REDEFINITION.

ENDCLASS. "lcl_car DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_truck DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_truck DEFINITION INHERITING FROM lcl_vehicle.
PUBLIC SECTION.
METHODS : get_maximum_velocity REDEFINITION,
get_type REDEFINITION,
get_vehicle_name REDEFINITION.

ENDCLASS. "lcl_truck DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_bus DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_bus DEFINITION INHERITING FROM lcl_vehicle.
PUBLIC SECTION.
METHODS : get_maximum_velocity REDEFINITION,
get_type REDEFINITION,
get_vehicle_name REDEFINITION.

ENDCLASS. "lcl_bus DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_vehicle IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_vehicle IMPLEMENTATION.
METHOD create_vehicle.
CASE iv_vehicle_type.
WHEN c_car.
CREATE OBJECT rv_vehicle TYPE lcl_car.
WHEN c_bus.
CREATE OBJECT rv_vehicle TYPE lcl_bus.
WHEN c_truck.
CREATE OBJECT rv_vehicle TYPE lcl_truck.
ENDCASE.
ENDMETHOD. "constructor

ENDCLASS. "lcl_vehicle DEFINITION

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 32
ABAP Code Refactoring Techniques

*----------------------------------------------------------------------*
* CLASS lcl_car DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_car IMPLEMENTATION.
METHOD get_vehicle_name.
rv_vehicle_name = 'Car'.
ENDMETHOD. "get_vehicle_name

METHOD get_maximum_velocity.
rv_maximum_velocity = 200.
ENDMETHOD. "get_maximum_velocity

METHOD get_type.
rv_vehicle_type = c_car.
ENDMETHOD. "get_type
ENDCLASS. "lcl_car DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_bus DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_bus IMPLEMENTATION.
METHOD get_vehicle_name.
rv_vehicle_name = 'Bus'.
ENDMETHOD. "get_vehicle_name

METHOD get_maximum_velocity.
rv_maximum_velocity = 180.
ENDMETHOD. "get_maximum_velocity

METHOD get_type.
rv_vehicle_type = c_bus.
ENDMETHOD. "get_type
ENDCLASS. "lcl_bus DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_truck DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_truck IMPLEMENTATION.
METHOD get_vehicle_name.
rv_vehicle_name = 'Truck'.
ENDMETHOD. "get_vehicle_name

METHOD get_maximum_velocity.
rv_maximum_velocity = 120.
ENDMETHOD. "get_maximum_velocity

METHOD get_type.
rv_vehicle_type = c_truck.
ENDMETHOD. "get_type
ENDCLASS. "lcl_truck DEFINITION

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 33
ABAP Code Refactoring Techniques

DATA : go_vehicle_1 TYPE REF TO lcl_vehicle,


go_vehicle_2 TYPE REF TO lcl_vehicle,
gv_vehicle_name TYPE string.

START-OF-SELECTION.

lcl_vehicle=>create_vehicle(
EXPORTING
iv_vehicle_type = lcl_vehicle=>c_car
RECEIVING
rv_vehicle = go_vehicle_1 ).

lcl_vehicle=>create_vehicle(
EXPORTING
iv_vehicle_type = lcl_vehicle=>c_truck
RECEIVING
rv_vehicle = go_vehicle_2 ).

gv_vehicle_name = go_vehicle_1->get_vehicle_name( ).
WRITE / gv_vehicle_name.

gv_vehicle_name = go_vehicle_2->get_vehicle_name( ).
WRITE / gv_vehicle_name.
Explanation of Refactoring Done in Code:
In the first report, there is only once class representing all kinds of vehicles and in the code of this class the
different behaviour for each kind of vehicle is separated using case-endcase or if –else..if statements. In the
second report, a factory method is added to the top level abstract vehicle class which instantiates instances
of different vehicle types, in the refactored code each vehicle type is represented by a subclass of the
vehicle class.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 34
ABAP Code Refactoring Techniques

10. Introduce Null Object


Explanation: If you have repeated checks for null values in the code, you can replace the null values with
null objects.
Motivation:
• Repeated checks for null values in code result in too many if..else blocks and makes code difficult to
understand
• The code belonging to null values is scattered in code and not encapsulated
Steps of Refactoring:
• Create null value classes as subclasses of original class
• Find out all places in code which can give out a null value and replace them so that they give out a
null object instance
• Remove the condition checks for null values and delegate the calls to the null object instance

• Example Code Fragment:


In this example , the information about inhabitant of a flat will be fetched. If the flat is not rented, there will
also be no information about the inhabitant of the flat.

Code Before Code Refactoring


*&---------------------------------------------------------------------*
*& Report ZSB_INTRODUCE_NULL_OBJECT
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zsb_introduce_null_object.

*----------------------------------------------------------------------*
* CLASS lcl_person DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_person DEFINITION DEFERRED.
*----------------------------------------------------------------------*
* CLASS lcl_flat DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_flat DEFINITION.
PUBLIC SECTION.
METHODS : constructor
IMPORTING io_inhabitant TYPE REF TO lcl_person
iv_city TYPE string
iv_country TYPE string,

get_inhabitant
RETURNING value(ro_inhabitant) TYPE REF TO lcl_person.

PRIVATE SECTION.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 35
ABAP Code Refactoring Techniques

DATA : mo_inhabitant TYPE REF TO lcl_person,


mv_city TYPE string,
mv_country TYPE string.
ENDCLASS. "lcl_flat DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_person DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_person DEFINITION.
PUBLIC SECTION.
METHODS : get_name
RETURNING value(rv_name) TYPE string,

get_surname
RETURNING value(rv_surname) TYPE string,

get_age
RETURNING value(rv_age) TYPE i,

constructor
IMPORTING
iv_name TYPE string
iv_surname TYPE string
iv_age TYPE i.

PRIVATE SECTION.
DATA : mv_name TYPE string,
mv_surname TYPE string,
mv_age TYPE i.

ENDCLASS. "lcl_person DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_person IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_person IMPLEMENTATION.
METHOD get_name.
rv_name = mv_name.
ENDMETHOD. "get_name

METHOD get_surname.
rv_surname = mv_surname.
ENDMETHOD. "get_surname

METHOD get_age.
rv_age = mv_age.
ENDMETHOD. "get_age

METHOD constructor.
mv_age = iv_age.
mv_surname = iv_surname.
mv_name = iv_name.
ENDMETHOD. "constructor

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 36
ABAP Code Refactoring Techniques

ENDCLASS. "lcl_person IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS lcl_flat IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_flat IMPLEMENTATION.

METHOD constructor.
mo_inhabitant = io_inhabitant.
mv_city = iv_city.
mv_country = iv_country.
ENDMETHOD. "constructor

METHOD get_inhabitant.
ro_inhabitant = mo_inhabitant.
ENDMETHOD. "get_inhabitant

ENDCLASS. "lcl_flat IMPLEMENTATION

DATA : lo_flat TYPE REF TO lcl_flat,


lo_inhabitant TYPE REF TO lcl_person,
lo_inhabitant_test TYPE REF TO lcl_person,
lv_name TYPE string,
lv_surname TYPE string,
lv_age TYPE i.

START-OF-SELECTION.

CREATE OBJECT lo_inhabitant


EXPORTING
iv_age = 30
iv_name = 'John'
iv_surname = 'Doe'.

CREATE OBJECT lo_flat


EXPORTING
io_inhabitant = lo_inhabitant
iv_city = 'Istanbul'
iv_country = 'Turkey'.

lo_inhabitant_test = lo_flat->get_inhabitant( ).

IF lo_inhabitant_test IS NOT INITIAL.


lv_name = lo_inhabitant_test->get_name( ).
WRITE / lv_name.
ELSE.
WRITE / 'No name'.
ENDIF.

IF lo_inhabitant_test IS NOT INITIAL.


lv_surname = lo_inhabitant_test->get_surname( ).
WRITE / lv_surname.
ELSE.
WRITE / 'No surname'.
ENDIF.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 37
ABAP Code Refactoring Techniques

IF lo_inhabitant_test IS NOT INITIAL.


lv_age = lo_inhabitant_test->get_age( ).
WRITE / lv_age.
ELSE.
WRITE / 'No age'.
ENDIF.

Code After Code Refactoring


&-----------------------------------------------------------------------*
*& Report ZSB_INTRODUCE_NULL_OBJECT_REFC
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zsb_introduce_null_object_refc.

*----------------------------------------------------------------------*
* CLASS lcl_person DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_person DEFINITION DEFERRED.
*----------------------------------------------------------------------*
* CLASS lcl_flat DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_flat DEFINITION.
PUBLIC SECTION.
METHODS : constructor
IMPORTING io_inhabitant TYPE REF TO lcl_person
iv_city TYPE string
iv_country TYPE string,

get_inhabitant
RETURNING value(ro_inhabitant) TYPE REF TO lcl_person.

PRIVATE SECTION.
DATA : mo_inhabitant TYPE REF TO lcl_person,
mv_city TYPE string,
mv_country TYPE string.
ENDCLASS. "lcl_flat DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_person DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_person DEFINITION.
PUBLIC SECTION.
METHODS : get_name
RETURNING value(rv_name) TYPE string,

get_surname
RETURNING value(rv_surname) TYPE string,

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 38
ABAP Code Refactoring Techniques

get_age
RETURNING value(rv_age) TYPE i,

constructor
IMPORTING
iv_name TYPE string
iv_surname TYPE string
iv_age TYPE i.

PRIVATE SECTION.
DATA : mv_name TYPE string,
mv_surname TYPE string,
mv_age TYPE i.

ENDCLASS. "lcl_person DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_null_person DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_null_person DEFINITION INHERITING FROM lcl_person.
PUBLIC SECTION.
METHODS : get_name REDEFINITION,

get_surname
REDEFINITION,

get_age
REDEFINITION,

constructor.

ENDCLASS. "lcl_null_person DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_person IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_person IMPLEMENTATION.
METHOD get_name.
rv_name = mv_name.
ENDMETHOD. "get_name

METHOD get_surname.
rv_surname = mv_surname.
ENDMETHOD. "get_surname

METHOD get_age.
rv_age = mv_age.
ENDMETHOD. "get_age

METHOD constructor.
mv_age = iv_age.
mv_surname = iv_surname.
mv_name = iv_name.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 39
ABAP Code Refactoring Techniques

ENDMETHOD. "constructor

ENDCLASS. "lcl_person IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS lcl_flat IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_flat IMPLEMENTATION.

METHOD constructor.
mo_inhabitant = io_inhabitant.
mv_city = iv_city.
mv_country = iv_country.
ENDMETHOD. "constructor

METHOD get_inhabitant.
ro_inhabitant = mo_inhabitant.
ENDMETHOD. "get_inhabitant

ENDCLASS. "lcl_flat IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS lcl_null_person DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_null_person IMPLEMENTATION.
METHOD get_name.
rv_name = 'No name'.
ENDMETHOD. "get_name

METHOD get_surname.
rv_surname = 'No Surname'.

ENDMETHOD. "get_surname

METHOD get_age.
rv_age = 0.
ENDMETHOD. "get_age

METHOD constructor.
super->constructor( EXPORTING iv_name = space
iv_surname = space
iv_age = space
).
ENDMETHOD. "constructor
ENDCLASS. "lcl_null_person DEFINITION

DATA : lo_flat TYPE REF TO lcl_flat,


lo_inhabitant TYPE REF TO lcl_null_person,
lo_inhabitant_test TYPE REF TO lcl_person,
lv_name TYPE string,

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 40
ABAP Code Refactoring Techniques

lv_surname TYPE string,


lv_age TYPE i.

START-OF-SELECTION.

CREATE OBJECT lo_inhabitant.

CREATE OBJECT lo_flat


EXPORTING
io_inhabitant = lo_inhabitant
iv_city = 'Istanbul'
iv_country = 'Turkey'.

lo_inhabitant_test = lo_flat->get_inhabitant( ).

lv_name = lo_inhabitant_test->get_name( ).
WRITE / lv_name.

lv_surname = lo_inhabitant_test->get_surname( ).
WRITE / lv_surname.

lv_age = lo_inhabitant_test->get_age( ).
WRITE / lv_age.

Explanation of Refactoring Done in Code:


In the first report, an instance of a flat instance is created and the person who is living in this flat is passed to
this class as an instance of the person class. In the application part of the report, the person instance
representing the inhabitant of this flat is received and the details of this person as name, surname and age
are written to the screen. If there is noone living in the flat, the person instance is a null instance and we
dedect this case with the help of an if..else statement in the application code. If the person instance is null,
then we write the texts ‘No name’, ‘No Surname’ etc. on the screen. In the second report , we create a
sublass of the person subclass which represents the null reference behaviour of person and encapsulates
the values of name, surname and age for null person. In this way, we eliminate the if..else statements in
code and receive the values of name, surname and age of the person regardless of it is a null reference or
not.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 41
ABAP Code Refactoring Techniques

11. Separate Query and Modifier Methods


Explanation: If you have a method that returns a value and also changes the values of other variables of
the object create two methods one for the accessor and one for the modifier part of the old method
Motivation:
• If a query method has no side effects you can call it as many times as you want without any
problems
• The code which returns a value and changes the values of other variables can be very easily source
of bugs and it would be difficult to maintain because of different roles the same method can have
Steps of Refactoring:
• Create a new method which has just the query part of the original method as its body
• Create another method which has the data changing part of the original method as its body
• Replace the calls in client application to the old method with the new query method
• Compile your code and run your ABAP Unit tests

Example Code Fragment:


In this example , a method of the customer class returns the total debt of customer object and adds the
amount of order given as input to the total debt of customer

Code Before Code Refactoring

*&---------------------------------------------------------------------*
*& Report ZSB_SEPARATE_QUERY_FROM_MODIF
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zsb_separate_query_from_modif.

*----------------------------------------------------------------------*
* CLASS lcl_customer DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_customer DEFINITION.
PUBLIC SECTION.
METHODS : add_order_and_get_debt
IMPORTING iv_order_amount TYPE i
RETURNING value(rv_debt) TYPE i.

PRIVATE SECTION.
DATA : mv_debt TYPE i VALUE '1000',
mv_open_order_amount TYPE i VALUE '100'.

ENDCLASS. "lcl_flat DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_customer IMPLEMENTATION

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 42
ABAP Code Refactoring Techniques

*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_customer IMPLEMENTATION.
METHOD add_order_and_get_debt.
ADD iv_order_amount TO mv_open_order_amount.
ADD iv_order_amount TO mv_debt.
rv_debt = mv_debt.
ENDMETHOD. "add_order_and_get_debt
ENDCLASS. "lcl_flat DEFINITION

START-OF-SELECTION.

DATA : lo_customer TYPE REF TO lcl_customer,


lv_debt TYPE i.

CREATE OBJECT lo_customer.


lo_customer->add_order_and_get_debt(
EXPORTING
iv_order_amount = 50
RECEIVING
rv_debt = lv_debt ).

WRITE / lv_debt.

Code After Code Refactoring


*&---------------------------------------------------------------------*
*& Report ZSB_SEPARATE_QUERY_FROM_MODIF
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zsb_separate_query_modif_ref.

*----------------------------------------------------------------------*
* CLASS lcl_customer DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_customer DEFINITION.
PUBLIC SECTION.
METHODS : get_debt
RETURNING value(rv_debt) TYPE i,

add_order_amount
IMPORTING iv_order_amount TYPE i.

PRIVATE SECTION.
DATA : mv_debt TYPE i VALUE '1000',
mv_open_order_amount TYPE i VALUE '100'.

ENDCLASS. "lcl_flat DEFINITION

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 43
ABAP Code Refactoring Techniques

*----------------------------------------------------------------------*
* CLASS lcl_customer IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_customer IMPLEMENTATION.
METHOD get_debt.
rv_debt = mv_debt.
ENDMETHOD. "add_order_and_get_debt

METHOD add_order_amount.
ADD iv_order_amount TO mv_open_order_amount.
ADD iv_order_amount TO mv_debt.
ENDMETHOD. "add_order_amount
ENDCLASS. "lcl_flat DEFINITION

START-OF-SELECTION.

DATA : lo_customer TYPE REF TO lcl_customer,


lv_debt TYPE i.

CREATE OBJECT lo_customer.


lo_customer->add_order_amount(
EXPORTING
iv_order_amount = 50 ).

lv_debt = lo_customer->get_debt( ).
WRITE / lv_debt.

Explanation of Refactoring Done in Code:


In the first report, the customer class has a method with name add_order_and_get_debt which adds the
amount of last order given by a customer to his total open order amount and to this total debts and returns
the amount of his total debts to the caller. In the second report, the customer class has two methods which
separately adds the order amount and returns the total debt of a customer.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 44
ABAP Code Refactoring Techniques

12. Parameterize Method


Explanation: If you have several methods which do similar operations with different values in the message
body you can create one method which uses a method parameter for different values
Motivation:
• You can decrease the number of methods in the class
• You can decrease the usage of duplicate code and reduce maintenance efforts
Steps of Refactoring:
• Create a new parameterized method which can be substituted for each repetitive method
• Replace the old method calls in client application to the old methods with the new parameterized
method
• Compile your code and run your ABAP Unit tests

Example Code Fragment:


In this example , the price of a product is being increased by a given percent.
Code Before Code Refactoring
*&---------------------------------------------------------------------*
*& Report ZSB_PARAMETERIZE_METHOD
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zsb_parameterize_method.

TYPES : ty_price TYPE p DECIMALS 2.

*----------------------------------------------------------------------*
* CLASS lcl_product DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_product DEFINITION.
PUBLIC SECTION.
METHODS : constructor
IMPORTING iv_name TYPE string
iv_price TYPE p,

get_price
RETURNING value(rv_price) TYPE ty_price,

increase_price_10_percent,

increase_price_20_percent.

PRIVATE SECTION.
DATA : mv_price TYPE ty_price,
mv_name TYPE string.

ENDCLASS. "lcl_product DEFINITION

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 45
ABAP Code Refactoring Techniques

*----------------------------------------------------------------------*
* CLASS lcl_product IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_product IMPLEMENTATION.
METHOD constructor.
mv_price = iv_price.
mv_name = iv_name.
ENDMETHOD. "constructor

METHOD get_price.
rv_price = mv_price.
ENDMETHOD. "get_price

METHOD increase_price_10_percent.
mv_price = mv_price * '1.1'.
ENDMETHOD. "increase_price_10_percent

METHOD increase_price_20_percent.
mv_price = mv_price * '1.2'.
ENDMETHOD. "increase_price_20_percent
ENDCLASS. "lcl_product IMPLEMENTATION

DATA : lo_product_1 TYPE REF TO lcl_product,


lv_price TYPE ty_price.

START-OF-SELECTION.

CREATE OBJECT lo_product_1


EXPORTING
iv_name = 'Computer'
iv_price = 1000.

lo_product_1->increase_price_10_percent( ).
lv_price = lo_product_1->get_price( ).
WRITE / lv_price.

lo_product_1->increase_price_20_percent( ).
lv_price = lo_product_1->get_price( ).
WRITE / lv_price.

Code After Code Refactoring


*&---------------------------------------------------------------------*
*& Report ZSB_PARAMETERIZE_METHOD_REF
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zsb_parameterize_method_ref.
*&---------------------------------------------------------------------*
*& Report ZSB_PARAMETERIZE_METHOD

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 46
ABAP Code Refactoring Techniques

*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

TYPES : ty_price TYPE p DECIMALS 2,


ty_increase_rate TYPE p DECIMALS 1.

*----------------------------------------------------------------------*
* CLASS lcl_product DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_product DEFINITION.
PUBLIC SECTION.
METHODS : constructor
IMPORTING iv_name TYPE string
iv_price TYPE p,

get_price
RETURNING value(rv_price) TYPE ty_price,

increase_price
IMPORTING iv_increase_rate TYPE ty_increase_rate.

PRIVATE SECTION.
DATA : mv_price TYPE ty_price,
mv_name TYPE string.

ENDCLASS. "lcl_product DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_product IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_product IMPLEMENTATION.
METHOD constructor.
mv_price = iv_price.
mv_name = iv_name.
ENDMETHOD. "constructor

METHOD get_price.
rv_price = mv_price.
ENDMETHOD. "get_price

METHOD increase_price.
mv_price = mv_price * ( 1 + iv_increase_rate ).
ENDMETHOD. "increase_price_10_percent

ENDCLASS. "lcl_product IMPLEMENTATION

DATA : lo_product_1 TYPE REF TO lcl_product,


lv_price TYPE ty_price.

START-OF-SELECTION.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 47
ABAP Code Refactoring Techniques

CREATE OBJECT lo_product_1


EXPORTING
iv_name = 'Computer'
iv_price = 1000.

lo_product_1->increase_price( '0.1' ).
lv_price = lo_product_1->get_price( ).
WRITE / lv_price.

lo_product_1->increase_price( '0.2' ).
lv_price = lo_product_1->get_price( ).
WRITE / lv_price.

Explanation of Refactoring Done in Code:


In the first report, the increase rate is part of the method body and in the second report the method which
increases the product price receives the increase rate as an input parameter.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 48
ABAP Code Refactoring Techniques

13. Pull up Field in the Class Hierarchy


Explanation: If you have more than one subclasses of a class which have the same field, move the field to
the superclass
Motivation:
• Prevents usage of different fields for the same purpose in subclasses
Example Code Fragment:
Since the refactoring is simple, no example code is given. In the example given below in the ABAP
Workbench Support part of this refactoring, we have a class named ZCL_VEHICLE which is the superclass
of classess ZCL_BUS and ZCL_TRUCK. Both subclasses ZCL_BUS and ZCL_TRUCK have member
attribute MV_SPEED which shows the current speed of a Bus or Truck instance. Since this member
attribute has the same type and semantic meaning in both of the subclasses of ZCL_VEHICLE, we can
move this member attribute to the superclass.

ABAP Workbench Support for this Refactoring:


Step 1: Open the class ZCL_TRUCK using transaction SE24 and activate ‘ATTRIBUTES’ tab.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 49
ABAP Code Refactoring Techniques

Step 2: Start the Refactoring Assistant following the menu item Utilities->Refactoring Assistant

Step 3: Select the attribute MV_SPEED and drag and drop it to the class ZCL_VEHICLE in the Refactoring
Assistant. You will have the following screen showing you that the member variable MV_SPEED is moved to
the superclass ZCL_VEHICLE. You have to activate the class ZCL_VEHICLE.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 50
ABAP Code Refactoring Techniques

Step 4: Check the syntax of the class ZCL_BUS in the transaction SE24 . You will have the syntax error
showing that the variable MV_SPEED is already defined since we moved it to the superclass of the class
ZCL_BUS.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 51
ABAP Code Refactoring Techniques

Step 5: Delete the attribute MV_SPEED from the attributes list of class ZCL_BUS and activate the class.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 52
ABAP Code Refactoring Techniques

14. Pull up Method in the Class Hierarchy


Explanation: If you have more than one subclasses of a class which have methods with identical results,
move these methods to the superclass
Motivation:
• Prevents to have duplicate code and duplicate maintenance in different methods
• Prevents usage of different methods for the same purpose in subclasses
Example Code Fragment:
Since the refactoring is simple, no example code is given. In the example given below in the ABAP
Workbench Support part of this refactoring, we have a class named ZCL_VEHICLE which is the superclass
of classess ZCL_BUS and ZCL_TRUCK. Both subclasses ZCL_BUS and ZCL_TRUCK have a method
named GET_NAME which returns the name of vehicle(Truck, Bus). Member attribute MV_NAME which
shows the name of a vehicle is an attribute of the verhicle class. Since the GET_NAME method is same for
both of these subclasses, we can move it to the superclass ZCL_VEHICLE.

ABAP Workbench Support for this Refactoring:


Step 1: Open the class ZCL_TRUCK using transaction SE24 and activate ‘METHODS’ tab.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 53
ABAP Code Refactoring Techniques

Step 2: Start the Refactoring Assistant following the menu item Utilities->Refactoring Assistant

Step 3:: Select the method GET_NAME and drag and drop it to the class ZCL_VEHICLE in the Refactoring
Assistant. You will have the following screen showing you that the instance method GET_NAME is moved to
the superclass ZCL_VEHICLE. You have to activate the class ZCL_VEHICLE.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 54
ABAP Code Refactoring Techniques

Step 4: Check the syntax of the class ZCL_BUS in the transaction SE24 . You will have the syntax error
showing that the method GET_NAME is already defined since we moved it to the superclass of the class
ZCL_BUS.

Step 5: Delete the method GET_NAME from the attributes list of class ZCL_BUS and activate the class.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 55
ABAP Code Refactoring Techniques

Copyright
© Copyright 2009 SAP AG. All rights reserved.
No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission of SAP AG.
The information contained herein may be changed without prior notice.
Some software products marketed by SAP AG and its distributors contain proprietary software components of other software vendors.
Microsoft, Windows, Excel, Outlook, and PowerPoint are registered trademarks of Microsoft Corporation.
IBM, DB2, DB2 Universal Database, System i, System i5, System p, System p5, System x, System z, System z10, System z9, z10, z9,
iSeries, pSeries, xSeries, zSeries, eServer, z/VM, z/OS, i5/OS, S/390, OS/390, OS/400, AS/400, S/390 Parallel Enterprise Server,
PowerVM, Power Architecture, POWER6+, POWER6, POWER5+, POWER5, POWER, OpenPower, PowerPC, BatchPipes,
BladeCenter, System Storage, GPFS, HACMP, RETAIN, DB2 Connect, RACF, Redbooks, OS/2, Parallel Sysplex, MVS/ESA, AIX,
Intelligent Miner, WebSphere, Netfinity, Tivoli and Informix are trademarks or registered trademarks of IBM Corporation.
Linux is the registered trademark of Linus Torvalds in the U.S. and other countries.
Adobe, the Adobe logo, Acrobat, PostScript, and Reader are either trademarks or registered trademarks of Adobe Systems
Incorporated in the United States and/or other countries.
Oracle is a registered trademark of Oracle Corporation.
UNIX, X/Open, OSF/1, and Motif are registered trademarks of the Open Group.
Citrix, ICA, Program Neighborhood, MetaFrame, WinFrame, VideoFrame, and MultiWin are trademarks or registered trademarks of
Citrix Systems, Inc.
HTML, XML, XHTML and W3C are trademarks or registered trademarks of W3C®, World Wide Web Consortium, Massachusetts
Institute of Technology.
Java is a registered trademark of Sun Microsystems, Inc.
JavaScript is a registered trademark of Sun Microsystems, Inc., used under license for technology invented and implemented by
Netscape.
SAP, R/3, SAP NetWeaver, Duet, PartnerEdge, ByDesign, SAP Business ByDesign, and other SAP products and services mentioned
herein as well as their respective logos are trademarks or registered trademarks of SAP AG in Germany and other countries.
Business Objects and the Business Objects logo, BusinessObjects, Crystal Reports, Crystal Decisions, Web Intelligence, Xcelsius, and
other Business Objects products and services mentioned herein as well as their respective logos are trademarks or registered
trademarks of Business Objects S.A. in the United States and in other countries. Business Objects is an SAP company.
All other product and service names mentioned are the trademarks of their respective companies. Data contained in this document
serves informational purposes only. National product specifications may vary.
These materials are subject to change without notice. These materials are provided by SAP AG and its affiliated companies ("SAP
Group") for informational purposes only, without representation or warranty of any kind, and SAP Group shall not be liable for errors or
omissions with respect to the materials. The only warranties for SAP Group products and services are those that are set forth in the
express warranty statements accompanying such products and services, if any. Nothing herein should be construed as constituting an
additional warranty.

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com


© 2009 SAP AG 56

You might also like