code refactoring

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

Upload: jaspalkumar1981

Post on 23-Nov-2014

110 views

Category:

Documents


7 download

TRANSCRIPT

Page 1: Code Refactoring

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

Page 2: Code Refactoring

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

Page 3: Code Refactoring

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

Page 4: Code Refactoring

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

Page 5: Code Refactoring

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

Page 6: Code Refactoring

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

Page 7: Code Refactoring

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

Page 8: Code Refactoring

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

Page 9: Code Refactoring

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

Page 10: Code Refactoring

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

Page 11: Code Refactoring

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

Page 12: Code Refactoring

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

Page 13: Code Refactoring

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

Page 14: Code Refactoring

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

Page 15: Code Refactoring

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

Page 16: Code Refactoring

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

Page 17: Code Refactoring

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

Page 18: Code Refactoring

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

Page 19: Code Refactoring

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

Page 20: Code Refactoring

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

Page 21: Code Refactoring

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

Page 22: Code Refactoring

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

Page 23: Code Refactoring

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

Page 24: Code Refactoring

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

Page 25: Code Refactoring

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

Page 26: Code Refactoring

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

Page 27: Code Refactoring

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

Page 28: Code Refactoring

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

Page 29: Code Refactoring

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

Page 30: Code Refactoring

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

Page 31: Code Refactoring

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

Page 32: Code Refactoring

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

Page 33: Code Refactoring

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

Page 34: Code Refactoring

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

Page 35: Code Refactoring

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

Page 36: Code Refactoring

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

Page 37: Code Refactoring

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

Page 38: Code Refactoring

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

Page 39: Code Refactoring

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

Page 40: Code Refactoring

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

Page 41: Code Refactoring

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

Page 42: Code Refactoring

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

Page 43: Code Refactoring

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

Page 44: Code Refactoring

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

Page 45: Code Refactoring

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

Page 46: Code Refactoring

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

Page 47: Code Refactoring

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

Page 48: Code Refactoring

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

Page 49: Code Refactoring

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

Page 50: Code Refactoring

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

Page 51: Code Refactoring

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

Page 52: Code Refactoring

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

Page 53: Code Refactoring

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

Page 54: Code Refactoring

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

Page 55: Code Refactoring

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

Page 56: Code Refactoring

ABAP Code Refactoring Techniques

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BOC - boc.sap.com © 2009 SAP AG 56

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.