First-hand knowledge. Reading Sample Modularization involves placing specific sequences of ABAP statements in a module, instead of placing all the statements in a single main program. In this sample chapter, you will learn to modularize your program using object-oriented programming, with classes, global classes, function modules and subroutines. “Making Programs Modular” Contents Index The Author Brian O‘Neill Getting Started with ABAP 451 Pages, 2016, $49.95/€49.95 ISBN 978-1-4932-1242-2 www.sap-press.com/3869 © 2016 by Rheinwerk Publishing, Inc. This reading sample may be distributed free of charge. In no way must the file be altered, or individual pages be removed. The use for any commercial purpose other than promoting the book is strictly prohibited. Making Programs Modular So far, this book has covered a number of technical methods that allow you to do specific things using ABAP programs. You discovered different ways to process data, read data from a database, and work with data in working memory. In this chapter, we will discuss how to organize, or modularize, your program using object-oriented pro- gramming to complete all of these tasks. We will cover modulariza- tion using classes, global classes, function modules and subroutines. Modularization involves placing specific sequences of ABAP state- What is ments in a module, instead of placing all the statements in a single modularization? main program. There are two very important reasons that you need to modularize your program instead of having just one long program that executes from the beginning to the end. First, you want to write programs that are easy for other programmers to read and under- stand. Second, you want to be able to reuse common functions mul- tiple times in a single program or across multiple programs and avoid redundancy. In addition, modularization has the added benefit of making ABAP programs easier to support and enhance after they have been written. Separation of Concerns Separation of concerns is a principal used to separate a program into different layers, each with its own function. Imagine an ABAP pro- gram that was created to report on some data from the database. You could break that program into three different parts, one part to read the data from the database, another part to process the data, and a third part to display the results, as shown conceptually in Figure 6.1. 217 Making Programs Modular Separation of Concerns 6 6 In order to avoid writing procedural nightmare programs, use the Why use separation REPORT ZABAP_PROGRAM separation of concerns principal to keep each unit focused on per- of concerns? forming only one function, and name each unit based on the function that it performs. This makes it much easier to understand the pro- gram, fix it, and enhance it. Remember that you may write the pro- READ DATA FROM DATABASE gram once, but someone else may have to fix or change it, possibly years later! Therefore, after using the plan in Figure 6.1, if users returned to you and said that they wanted additional data from the READ DATA PROCESS DATA PROCESS DATA database, you would know exactly what unit to change, and if they DISPLAY DATA wanted the ability to refresh the data, you would know that you can add the ability to call the read data from the database after displaying the data. If you had just one long program, it would be harder to find DISPLAY DATA out exactly where you need to make changes, and you definitely would not be able to reuse any particular unit; the program would all be one long unit. Figure 6.1 Using Seperation of Concerns to Break a Program into Single-Function Of course, each person’s interpretation of a unit focused on perform- Units ing only one function might be different. That’s where this concept can become more of an art than a science. If the units are made too When you break your program into these three different sections, small, it can be confusing because there are so many; if they are made you then have one place to make changes to any of those functions. too large, it can be confusing because there’s so much code in a single unit. Remember that you’re both writing a program and trying to Procedural programs Back in the ancient days of computing, people would write long pro- make it easy for the next person to fix and enhance. grams using punch cards that had to be executed from the beginning to the end and probably scheduled to run at a certain time. Today, Figure 6.2 expands on the original conceptual drawing in Figure 6.1 Naming different applications are used by people in real time, which means that you to demonstrate breaking up and naming units for each function that units need to change your application to meet the user’s sometimes crazy they perform. This example demonstrates a program that gets a list of expectations. Programs designed to run from the beginning to end possible flights based on a search, calculates the price of the flight are called procedural programs. options, and displays the results to the user. Each unit completes one function, and each unit has a descriptive name. If a person said that In a typical ABAP journey, it’s normal to see an old program written there was an issue with the price being calculated, you would know in a procedural format—and then you’ll hear from a user that the pro- exactly what unit of code he or she was talking about. gram is supposed to process data in some way that isn’t working. You’ll have to go through the long process of reading the program and debugging to figure out where the data is changed, only to find that the data is read and changed all over the place. 218 219 Making Programs Modular Introduction to Object-Oriented Programming 6 6 oriented ABAP). The fact is that there is no ABAP versus OO-ABAP: just ABAP with good developers and bad developers. GET_AVAILABLE_FLIGHTS REPORT ZABAP_PROGRAM If you have written object-oriented programs in other languages, you will find that there are a few ABAP quirks, but all of the concepts that you have seen in other languages will apply in ABAP as well. READ DATA FROM DATABASE GET_CUSTOMER_DATA What Is an Object? A programming object is designed around the idea of objects in the READ DATA PROCESS DATA PROCESS DATA CALCULATE_TOTAL_PRICE real world. A good introductory conceptual example is that of a car. DISPLAY DATA A car has attributes that describe its current state, such as fuel level and current speed, and attributes that describe the object, such as DISPLAY DATA DISPLAY_RESULTS manufacturer and model. There are also a few methods that describe how we interact with the car, such as accelerate, decelerate, and refuel. Figure 6.3 shows a conceptual drawing of this car object. Figure 6.2 Seperation of Concerns with Named Code Units Attributes Methods Changing units Just because you created certain units of code when the application ofcode was created doesn’t mean that you can’t add more. It’s common to Accelerate have to add additional functionality in a single unit of code, in which case you should determine if the additional functionality might need to be in its own functional unit of code. If each unit is expected to per- Fuel: 100 form one function, ask yourself if the new code is really completing Speed: 0 Decelerate Manufacturer: Toyota that same function or if it’s its own unit. Also, anytime the new code Model: Tundra is something that could be reused, then it should be in its own unit. Once your code is completed and working, it is always good practice to go back and see what kind of improvements you can make to your Refuel code and find any code that is repeated and could be modularized. Now that you understand the concept of Separation of Concerns, we Figure 6.3 The Car Object will cover how to utilize it using object-oriented programming. Each of the object’s methods is a functional unit designed to complete Introduction to Object-Oriented Programming one task. Each attribute of the object is a variable that all of the meth- ods have access to. The pseudocode in Listing 6.1 shows what the OOP The recommended method for modularizing ABAP programs is to use code in the accelerate method could look like. object-oriented programming. There are some people in the ABAP community who are unsure about object-oriented programming and have even posed the idea that there is ABAP and OO-ABAP (object- 220 221 Making Programs Modular Structuring Classes 6 6 METHOD ACCELERATE. one object that holds all of the logic for your program. Each method SPEED = SPEED + 5. will represent a single function, as discussed in the section on the sep- ENDMETHOD. aration of concerns principle. Looking back at Figure 6.2, each differ- Listing 6.1 Pseudocode of Accelerate Method ent unit could be represented as a method in a flight finder class, as shown in Figure 6.5. Classes Now, say that the example in Figure 6.3 specifically refers to a Toyota Tundra, but you want to create additional objects for different types Methods of cars. This is where classes come in. Each object is actually an instan- tiation of a class, and you can have multiple objects of the same class. Attributes GET_AVAILABLE_FLIGHTS Again think back to the real-life example of a car; the Toyota Tundra is a type of car, and all cars can accelerate, decelerate, and refuel, but GET_CUSTOMER_DATA this particular car is going at a certain speed and has a certain fuel level. When creating objects, all of the code is stored in the class, but you can create multiple objects that use that code, and each will have CALCULATE_TOTAL_PRICE its own set of attributes to describe it, as shown conceptually in Fig- ure 6.4. You can think of the class in this example as a mold, whereas DISPLAY_RESULTS the objects are those items created from that mold. Car Class Figure 6.5 Flight Finder Class Concept Fuel: Speed: Brand: Each class method can be created with the ability to take and return Passing data to Manfuctaurer: data. For example, when creating the method for calculating the total methods price in Figure 6.5, you could pass a value containing the results from the get available flights method. Structuring Classes Now that you understand some of the concepts of object-oriented programming, you can begin to learn how to create classes and Car Object 1 Car Object 2 Fuel: 100 Fuel: 10 objects in ABAP. If the object-oriented concepts do not make sense Speed: 10 Speed: 0 Brand: Toyota Brand: Nissan yet, perhaps seeing the actual code in action will help. We’ll first Manufacturer: Tundra Manufacturer: Sentra cover how to create a local class within a program and then how to create a global class that can be used across multiple programs. Figure 6.4 Relationship between Class and Object Implementation vs. Definition Modularizing with Object-Oriented Programming In ABAP, every class requires a definition and an implementation. Just because you are using object-oriented programming doesn’t The definition lists the different attributes and methods of a class, mean you have to use it to build multiple objects. You could also have 222 223 Making Programs Modular Structuring Classes 6 6 whereas the implementation contains the actual code for all of the CLASS lcl_car IMPLEMENTATION. ENDCLASS. methods. The definition must come before the implementation and Listing 6.3 Creating an Object from a Class must also come before an object is created from the class. The class is defined by using the CLASS keyword, followed by the name of the Public and Private Sections class and then either DEFINITION or IMPLEMENTATION depending on what you are declaring. The example in Listing 6.2 contains the defi- Before adding attributes and methods to the class definition, you will nition of a class with no attributes or methods. Prefix the class name need to decide whether those attributes and methods should be pub- with lcl to indicate that it’s a local class, meaning that it’s being cre- lic, private, or protected. ated inside of an ABAP Program. Since we are demonstrating local Public attributes and methods can be used within the class or outside Public classes, you can insert the code in this section into any ABAP program of the class, from the main program, or even from another class. for testing. Since both the definition and implementation are con- tained within a CLASS and ENDCLASS keyword, they do not need to be Private attributes and methods can only be used from within the class Private next to each other when being defined. itself, meaning that another class or the main program is unable to read the attributes or call the methods that are listed as private. CLASS lcl_car DEFINITION. ENDCLASS. Protected attributes and methods can only be used from within the Protected CLASS lcl_car IMPLEMENTATION. ENDCLASS. class itself, just like the private attributes and methods. The difference with protected attributes and methods is that they can be inherited Listing 6.2 Definition and Implementation of a Class from a subclass, unlike a private attribute or class. We will revisit pro- Creating Objects tected attributes and methods when we cover inheritance later in the chapter. Now that you’ve created a basic class, you can create objects of that class. Remember that a class is like a design, and you can build multi- The public and private sections are defined in the class implementa- ple objects using that design. tion using the PUBLIC SECTION and PRIVATE SECTION keywords. Listing 6.4 adds those sections to the class definition. Object variables There are two parts to creating an object. The first part is to define the object variable. This is just like creating variables, which we intro- CLASS lcl_car DEFINITION. duced in Chapter 2, except that you will use TYPE REF TO instead of PUBLIC SECTION. PRIVATE SECTION. just TYPE to indicate the class to be used when creating the object. The ENDCLASS. example in Listing 6.3 uses the prefix o_ to indicate an object. ClASS lcl_car IMPLEMENTATION. ENDCLASS. For objects, you then use the command CREATE OBJECT followed by Listing 6.4 Adding the Public and Private Sections to the Class Definition the object variable to instantiate the object, as shown in Listing 6.3 Just like creating your own data types using the TYPES command, the Next, you can add attributes to public or private sections, by creating Attributes class definition must come before creating an object using that class. variables, just like the ones discussed in Chapter 2. The variables CLASS lcl_car DEFINITION. must be defined after a section to determine whether they’re public ENDCLASS. or private. DATA: o_car TYPE REF TO lcl_car. These attributes will be available globally to all of your methods; if CREATE OBJECT o_car. they’re public, they’ll also be available globally outside of your 224 225 Making Programs Modular Structuring Classes 6 6 methods. Listing 6.5 adds public attributes for fuel, speed, brand, ENDCLASS. ClASS lcl_car IMPLEMENTATION. and manufacturer and a private attribute for the current gear. METHOD accelerate. ENDMETHOD. Read Only attributes Public attributes can also be given a READ-ONLY property, which will METHOD decelerate. make them readable outside of the class and changeable only from ENDMETHOD. within the class. In Listing 6.5, the attribute d_manufacturer is set to METHOD refuel. be read-only. ENDMETHOD. ENDCLASS. CLASS lcl_car DEFINITION. Listing 6.6 Adding Public Classes to the Car Class PUBLIC SECTION. DATA: d_fuel TYPE i, d_speed TYPE i, Now, you can add code to the methods. The code will go in the class Implementation d_brand TYPE string, implementation section, and each method will share all of the attri- d_manufacturer TYPE string READ-ONLY. butes declared in the definition. Listing 6.7 adds some programming PRIVATE SECTION. logic to each of the methods, and you can see that they are all able to DATA: d_gear TYPE i. ENDCLASS. access the class attributes. ClASS lcl_car IMPLEMENTATION. ENDCLASS. You can also declare variables within methods, such as ld_max in the Local variables Listing 6.5 Adding Public and Private Attributes to the Car Class REFUEL method shown in Figure 6.11. These variables are considered local variables since they will not be visible or usable outside of the Class Methods methods in which they’re declared. For that reason, they are prefixed with a ld_ meaning local data variable, instead of d_, meaning global Definition Methods are the place to store all of your code, in single units of work data variable. designed to complete one function. Each method should have a name describing the action that it will complete. First, you have to define CLASS lcl_car DEFINITION. the method using the keyword METHODS in the class definition, and PUBLIC SECTION. DATA: d_fuel TYPE i, then write the method’s code in the class implementation in between d_speed TYPE i, the words METHOD and ENDMETHOD. Listing 6.6 expands on the car d_brand TYPE string, example to add the definition and an empty implementation for the d_manufacturer TYPE string. accelerate, decelerate, and refuel methods. When adding methods, METHODS: accelerate, decelerate, you will get a syntax error if the method is not defined in both the refuel. definition and implementation of the class. PRIVATE SECTION. DATA: d_gear TYPE i. CLASS lcl_car DEFINITION. ENDCLASS. PUBLIC SECTION. ClASS lcl_car IMPLEMENTATION. DATA: d_fuel TYPE i, METHOD accelerate. d_speed TYPE i, d_speed = d_speed + 5. d_brand TYPE string, d_fuel = d_fuel – 5. d_manufacturer TYPE string. ENDMETHOD. METHODS: accelerate, METHOD decelerate. decelerate, d_speed = d_speed – 5. refuel. d_fuel = d_fuel – 2. PRIVATE SECTION. ENDMETHOD. DATA: d_gear TYPE i. METHOD refuel. 226 227 Making Programs Modular Structuring Classes 6 6 DATA: ld_max TYPE I VALUE 100. ENDMETHOD. d_fuel = ld_max. METHOD refuel. ENDMETHOD. DATA: d_max TYPE i VALUE 100. ENDCLASS. d_fuel = 100. ENDMETHOD. Listing 6.7 Adding Logic to Methods in the Car Class ENDCLASS. Listing 6.8 How to Call a Method in an Object Calling methods Now that you’ve defined some methods which contain some code, you can define an object, create it, and call the methods contained in Now you can set a breakpoint within the method and execute the pro- Methods in the the object. To call an object’s method, you enter the object name fol- gram and you will see the execution stack will show where the execution stack lowed by an arrow (->), then the method name, and then the open method was called from. If you are using Eclipse, the stack should and close parentheses (()), with any parameters in between the look like what we see in Figure 6.6. The accelerate method is listed parentheses. Table 6.1 shows how a method is called via an example and before that is START-OF-SELECTION, which is the ABAP event that using the car object created earlier in this section. starts executing our code. Object->method_name(parameters) o_car->accelerate() Table 6.1 How to Call a Method The code for calling methods has to be included after the object has been defined and created, but it can come before the definition of the Figure 6.6 Execution Stack in Eclipse object, as shown in Listing 6.8. CLASS lcl_car DEFINITION. Now, we can select the start-of-selection item in the stack to see PUBLIC SECTION. the line of code where the accelerate method was called as shown in DATA: d_fuel TYPE i, Figure 6.7. d_speed TYPE i, d_brand TYPE string, d_manufacturer TYPE string. METHODS: accelerate, decelerate, Figure 6.7 Eclipse Showing Where the Start-Of-Selection Stack refuel. PRIVATE SECTION. DATA: d_gear TYPE i. We can do the same thing from the SAP GUI debugger, when your ENDCLASS. breakpoint inside of the accelerate method is hit, you will notice the DATA: o_car TYPE REF TO lcl_car. CREATE OBJECT o_car. ABAP and Screen Stack section will appear as shown in Figure 6.8. o_car->accelerate( ). ClASS lcl_car IMPLEMENTATION. METHOD accelerate. d_speed = d_speed + 5. d_fuel = d_fuel – 5. ENDMETHOD. METHOD decelerate. d_speed = d_speed – 5. d_fuel = d_fuel – 2. Figure 6.8 ABAP and Screen Stack in SAP GUI 228 229 Making Programs Modular Structuring Classes 6 6 We can then click the START-OF-SELECTION item and the debugger CLASS lcl_car DEFINITION. PUBLIC SECTION. will bring up the section of code that called our accelerate method as DATA: d_fuel TYPE i, shown in Figure 6.9. d_speed TYPE i, d_brand TYPE string, d_manufacturer TYPE string. METHODS: accelerate IMPORTING ip_accel_rate TYPE i, decelerate, refuel. PRIVATE SECTION. DATA: d_gear TYPE i. Figure 6.9 SAP GUI Debugger Execution Stack ENDCLASS. DATA: o_car TYPE REF TO lcl_car. Importing, Returning, Exporting, and Changing CREATE OBJECT o_car. o_car->accelerate( 5 ). When using your car class, users do not want to accelerate at a rate of ClASS lcl_car IMPLEMENTATION. 5; they want to specify the amount of acceleration to occur, which METHOD accelerate. makes sense. There are a few ways to pass data to and from methods, d_speed = d_speed + ip_accel_rate. d_fuel = d_fuel – 5. as described in Table 6.2. ENDMETHOD. METHOD decelerate. Importing A copy of one or more variables is passed to the method. d_speed = d_speed – 5. d_fuel = d_fuel – 2. Returning The actual variable is returned by the method. Returning can ENDMETHOD. only be used to return one variable. METHOD refuel. Exporting A copy of one or more variables are returned from the d_fuel = 100. method. ENDMETHOD. ENDCLASS. Changing The actual variable is passed to the method, and any changes to that variable will change the original. (Also known as Listing 6.9 Adding the Ability to Import Variables in Methods passing by reference.) Next, you can change the method to check if the fuel is at zero; if it is, Returning Table 6.2 Ways to Pass Data to and from a Method then the car will not accelerate. When you call the method, you want to know if it worked or not, so return a Boolean parameter that will Importing You can change the accelerate method to import a variable to indi- be true if the method worked and false if it did not. The Boolean cate the amount of speed that you want to increase by. This is handled parameter is defined in the class definition using the RETURNING key- in Listing 6.9 by adding the IMPORTING command followed by a vari- word followed by VALUE and the variable name within parentheses, as able definition for the variable that will be copied in to the method shown in Listing 6.10, with the prefix rp indicating a returning and used to set the rate of acceleration for the car object. After adding parameter. the IMPORTING variable in the definition, that variable can now be accessed in the method implementation. The prefix ip here indicates Because the returning parameter is a Boolean, also create the Boolean an IMPORTING parameter. variable d_is_success in the main program and set it to the result of the method call in Listing 6.10, meaning that d_is_success will be set Now that you’ve defined the IMPORTING parameter, you also can pass to the value of rp_is_success after calling the accelerate method. the value for that parameter within the parentheses when calling the method, as shown in Listing 6.9. 230 231 Making Programs Modular Structuring Classes 6 6 CLASS lcl_car DEFINITION. CREATE OBJECT o_car. PUBLIC SECTION. IF o_car->accelerate(5) = abap_true. DATA: d_fuel TYPE i, WRITE: ‘It worked!’. d_speed TYPE i, ENDIF. d_brand TYPE string, … d_manufacturer TYPE string. Listing 6.11 Using the Returning Parameter as Part of an IF Statement METHODS: accelerate IMPORTING ip_accel_rate TYPE i RETURNING VALUE(rp_is_success) TYPE bool, If you want to import multiple parameters, you can do so by includ- Import multiple decelerate, ing the additional parameters after the IMPORTING command in the parameters refuel. class definition. When you list multiple variables, you will also need PRIVATE SECTION. DATA: d_gear TYPE i. to specify which variable you are passing within the parentheses, as ENDCLASS. shown in Listing 6.12. DATA: o_car TYPE REF TO lcl_car, d_is_success TYPE bool. CLASS lcl_car DEFINITION. CREATE OBJECT o_car. PUBLIC SECTION. d_is_succcess = o_car->accelerate(5). DATA: d_fuel TYPE i, ClASS lcl_car IMPLEMENTATION. d_speed TYPE I, METHOD accelerate. d_brand TYPE string, IF d_fuel – 5 > 0. d_manufacturer TYPE string. d_speed = d_speed + ip_accel_rate. METHODS: accelerate IMPORTING ip_accel_rate TYPE i d_fuel = d_fuel – 5. ip_other_param TYPE i rp_is_success = abap_true. RETURNING VALUE(rp_is_success) ELSE. TYPE bool, rp_is_success = abap_false. decelerate, ENDIF. refuel. ENDMETHOD. PRIVATE SECTION. METHOD decelerate. DATA: d_gear TYPE i. d_speed = d_speed – 5. ENDCLASS. d_fuel = d_fuel – 2. DATA: o_car TYPE REF TO lcl_car, ENDMETHOD. d_is_success TYPE bool. METHOD refuel. CREATE OBJECT o_car. d_fuel = 100. d_is_succcess = o_car->accelerate( ip_accel_rate = 5 ENDMETHOD. ip_other_param = 1 ). ENDCLASS. ClASS lcl_car IMPLEMENTATION. .. Listing 6.10 Class Including Returning Parameter ENDCLASS. Listing 6.12 Adding Multiple IMPORTING Parameters Method chaining The returned variable can also be used in line with other ABAP key- words using method chaining, which was added to the ABAP language You can also mark parameters as optional by adding OPTIONAL after Optional parameters in ABAP 7.02. For example, you can call the accelerate method from the parameter’s definition, which means that the parameter will have Listing 6.10 from within an IF statement and use the returning an initial value when the method runs if a value is not entered for that parameter as part of the IF statement, as shown in Listing 6.11. parameter. If there are multiple importing parameters but only one is … not marked as optional, you can pass only the required parameter DATA: o_car TYPE REF TO lcl_car, without identifying the parameter names, as shown in Listing 6.13. d_is_success TYPE bool. 232 233
Description: