Patterns in ABAP
Patterns in ABAP
Igor Barbaric
Contents 1 Introduction
1.1 1.2 1.3 1.4
.................................................. 5 5 6 6
open Method ............................................ get_sub_objects Method .......................... menu_request Method ............................. menu_select Method ................................ 4.5 Class lcl_application .................................. Denition .................................................. o_tree Attribute ........................................ t_active_objects Attribute ........................ constructor Method ................................. run_application Method ........................... on_double_click Method .......................... on_expand_no_children Method ............. on_menu_request Method ....................... on_menu_select Method .......................... 4.6 Summary ...................................................
....................................
20 21 21 21 21 22 22 22 23 23 25 25 25 26 26 27 27 27 30 31 31 31 31 31 32 32 32 32 35 35 36 36
What are Design Patterns? ....................... Communication in Patterns ...................... Design Patterns in Software Design ......... Success story: The Project and its By-product ................................................ Bad Application ........................................ Starting with Design Patterns ...................
7 7 7 7 8 8 8 8 9 9 9 11 15 15 15 17 19 19 19 20 20 20 20 20
1.5 1.6
Conventions in this Book ......................... Prerequisites ............................................. Basics of Object-Oriented Software Design ........................................ Experience in ABAP Programming ........... Reading UML Diagrams ............................
1.7
Denition .................................................. Case-Study Problem: Vendor-Specic User-Dened Text on Purchase Order ...... Class lcl_mod_facade ................................ Denition .................................................. constructor Method ................................. lif_tree_object~open Method ..................
.............................. ...............................
Denition .................................................. Case-Study Problem: Instantiating Application Only Once ............................. Summary ...................................................
..................................
5.4
Class lcl_st_text_facade ............................ Denition .................................................. s_thead Attribute ...................................... container Attribute ................................... textedit Attribute ...................................... constructor Method ................................. on_toolbar_func_sel Method ................... save Method ............................................. free Method ..............................................
Denition .................................................. Case-Study Problem: Application with a Command Tree ...................................... The Adapter in the Demo Application ..... Interface lif_interface ................................ Denition .................................................. Types ......................................................... node Attribute ..........................................
5.5
Summary ...................................................
www.sap-press.com
Contents
............................
37 37 38 39 39 39 40 44 46 47 47 48 48 49 50 50 50 51 51 52 52 53 53 53 54 54 54 57 59 59 60 60 60 61 61 62
Denition .................................................. Case-Study Problem: Organizing Flights by Date ..................................................... Class lcl_mod_composite ......................... Denition .................................................. Attributes .................................................. constructor Method ................................. lif_tree_object~get_sub_objects Method .....................................................
63 63 64 66 66 66 67 67 67 68 68 68 68 68 68 68 68 69 70 71 71 71 71 72 72 72 72 73 73 73 74 74 75 75 75 75 75 76 76 77 77
6.4
Summary ...................................................
..............................
Denition .................................................. Confusion About Whats Preceding and Whats Succeeding ............................
7.2
Case-Study Problem: Lookup Data for Internal Tables ..................................... Reusability ................................................
7.3
Class lcl_itab_dec ...................................... Denition .................................................. prec_decorator Attribute .......................... dt_ref Attribute ......................................... tt_fname_mappings Attribute .................. constructor Method ................................. refresh_data Method ................................ get_elds Method .....................................
7.4
Class lcl_itab_dec_vendor ......................... Denition .................................................. t_lfa1 Attribute ......................................... constructor Method ................................. refresh_data Method ............................... get_elds Method .....................................
7.5
Class lcl_itab_dec_st_text ......................... Denition .................................................. Attributes .................................................. constructor Method ................................. get_elds Method .....................................
Other Decorators in the Application ........ Implementation of the Decorator Pattern in the Application ..................................... Summary ...................................................
Contents
initialize Method ....................................... on_clicked Method ................................... refresh_display Method ............................ free Method .............................................. 8.8 Summary ...................................................
........................................................
77 77 77 80 80 83 85
9 Summary Index
................................................................
www.sap-press.com
5.1
Denition
What a waste of time! You have four people expending their time on learning and then developing four different applications to do more or less the same thing. You will waste a lot of time and money, only to end up with a mess that youll have to maintain. Figure 5.1 depicts this result. No good team leader would let this happen. Youd be better off choosing the most appropriate person and assigning him or her the task of creating an intermediate application, and then an ABAP class that serves as a faade for other ABAPers to interface with the machine. This way, only one person would have to learn everything about the machine, and he or she would provide a straightforward and easy-to-use interface for others. This result is shown in Figure 5.2. If improvements or corrections were needed, it would be in only one place. This way you would save lots of developer days initially and probably even more when it comes to maintenance.
According to the gang of four, Faade is intended to provide a unied interface to a set of interfaces in a subsystem. Faade denes a higher-level interface that makes the subsystem easier to use1. This means that we want to provide an interface to some other system. Some possible reasons:
We want to translate an interface of a system to the one that a particular group of developers will nd easier to use. For example, if your ABAPers dont know how to build a tool to access an external MS SQL database, one of them can create the tool and provide an ABAP class that interfaces the tool for others.
For example, lets say that you are a leader of an ABAPdevelopment team of four developers. They all have to build different functionalities that communicate with a machine in your companys factory. The machine produceslet us sayinjected plastic parts, and it works with the intranet via some interface. The ABAPers cant communicate with the machine unless they create some kind of intermediate application. You can stay aside, not interfere, and let them resolve their problems in whichever way they can. Each of them will create his or her application to interface with the machine. In order to do that each one will all have to learn a lot about the machine and its interface, which is probably complicated, and build an application using a tool other than ABAP that he or she is most familiar with.
1 Gamma, Helm, Johnson, Vlissides: Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley, 1995.
www.sap-press.com
27
SAP Web AS
ABAP application1 ABAP application2 ABAP application3 ABAP application4
SAP system
subsystem VB app
Intermediate applications
Engine starter
Engine stopper
Production log
Status flags
Temperature controller
Pressure controller
Machine interface
Machine
SAP Web AS
ABAP application 1 ABAP application 2 ABAP application 3 ABAP application 4
SAP system
Intermediate application
Engine starter
Engine stopper
Production log
Status flags
Temperature controller
Pressure controller
Machine interface
Machine
28
The logical solution for this is to include a standard text element in a SmartForm. You can include any standard text in a SmartForm by using a special node. The text name can be provided statically or dynamically. Since our requirement presupposes different text for each vendor, the text name should be composed dynamically by following naming conventions specially set for this purpose. For example, you can name the standard text: ZPO_VEN_ <vendor_code>. Then it would be easy to include a code node in a SmartForm with a simple ABAP statement: CONCATENATE 'ZPO_VEN_' lfa1-lifnr INTO v_vendor_text_name. And when you include a standard text node with name created dynamically as &V_VENDOR_TEXT_NAME& , you can be sure that this text will contain a remark exactly for the particular vendor. Or can you? Well, the SmartForm part is clear. This is how they work; its consistent and exible. But how can we make sure that users will know what to do? We can instruct the user to go to the standard SAP transactionSO01 for maintaining standard texts and edit texts with carefully determined name as ZPO_VEN_ followed by a vendor code. If users could follow these simple rules, that approach would work ne. But if we analyze this process more carefully, we realize its a pretty tough requirement for an average user. There are lots of things to remember, and to do:
Figure 5.3 and Figure 5.4 show how the standard transactions for maintaining standard texts appear.
Technical knowledge is required from users. They must know how to use the standard transaction for editing texts.
Figure 5.4 Transaction SO01Editing Text
The text name is composed by a user manually. This makes the system intolerant of typing errors: If a single character is mistaken ( for example, one leading zero in vendor code is omitted, or underscore in PO_VEN_ prex ), the text will be saved with no warnings, but it wont appear at the purchase order because it will be a completely different text than the one expected by the purchase order. The user will get confused and wont have idea of what happened. He or she will come to you ( or someone of your staff ) to complain, and youll tell him/her for the 10th time to be careful with the text name. Is this a bad user or a bad application? This is initially the simplest solution for the developer, since theres nothing to do except to modify the SmartForm a little. However, since user input errors are very likely to happen without appropriate message, it annoys users and intensies interaction between users and developers ( or administrators ). Even in the best case ( if we assume no typos ), it puts an unacceptable load to users and consumes too much of their time. This is by far the worst solution. We should create something better. For example, we could put navigation to the SO01 transaction somewhere in the program by using
www.sap-press.com
29
CALL TRANSACATION 'SO01' AND SKIP FIRST SCREEN WITH... while providing the text name automatically and even skipping the initial screen. This would be much better, but still not good enough. The standard transaction is still too technical and offers too many formatting options that are not needed for this purpose. Besides, when returning to the main program, one cannot skip the initial screen. This may not be a major annoyance for users, but its still at least one click too many. By putting a Faade between the ABAP Objects world and the standard texts repository in SAP, we could make it extremely simple and straightforward for both users and developers, with no possibility of errors. We can use a text-editing control that pops up automatically, so that the users never have to know the text name. They would navigate to text by selecting a line and pressing an Edit button ( as show in Figure 5.5 ). Moreover, if we create it as a dictionary class, we can use it not only for this particular purpose, but in other applications too, whenever standard text editing is required. This would be a faade between ABAP objects and SAP standard objects that are not object-oriented. In the demo application, we will maintain a dictionary table ZDPS_FACADE with only one eld: LIFNRvendor code. It will be maintained as any other object at the tree, by using an ALV grid control. The display structure which denes the grids output table will have two more read-only elds: vendor name ( lled by the Decorator described in Section 7.4 ) and text, which will be rst 100 characters of the standard text ( another Decorator, described in Section 7.5 ). The ALV grid will have a special button which will open the selected text in a new editable control. This time it will be hosted by a dialog box rather than by a docking container.
Figure 5.6 The New Standard Text Editor
mentation of the generic table maintenance model, particularly maintaining the ZDPS_FACADE table. The class is very simple. It has a constructor for initiation, and the tree interface method open redened. It is specic, becauseas opposed to all other objects this one has to use a special version of the ALV grid class and therefore needs a special controller LCL_CON_ALV_ FACADE. The specialty is one custom Edit button ( )
The control ( as shown in Figure 5.6 ) will have one texteditor eld and just two buttons ( apart from the controls standard toolbar ): Save and Close. The only formatting would be line breaks, simply implemented by user pressing the Enter key.
on the ALV grid toolbar that initializes editing standard texts in a special textedit control. Denition CLASS lcl_mod_facade DEFINITION INHERITING FROM lcl_mod. PUBLIC SECTION. METHODS: constructor, lif_tree_object~open REDEFINITION. ENDCLASS. constructor Method The constructor denes the name of the dictionary table to be maintained and the name of the dictionary structure which will be used for displaying data. The basic node attributes are set and the chain of Decorators is created ( read more on Decorators in Chapter 7 ). METHOD constructor. DATA: o_dec_vendor TYPE REF TO lcl_itab_dec_vendor, o_dec_st_text TYPE REF TO lcl_itab_dec_st_text. FIELD-SYMBOLS: <outtab> TYPE STANDARD TABLE. CALL METHOD super->constructor( i_tabname 'ZDPD_FACADE' i_disp_struc_name = 'ZDPD_FACADE_DS' i_title * node attributes me->lif_tree_object~node-node_key 'FACADE'. me->lif_tree_object~node-text 'Facade'(fac). * create chain of decorators ASSIGN me->dt_outtab->* TO <outtab>. CREATE OBJECT: o_dec_vendor EXPORTING it_ref <outtab>, o_dec_st_text = = = = =
EXPORTING i_prec_dec = o_dec_vendor, me->dec_final EXPORTING i_prec_dec = o_dec_st_text. ENDMETHOD. lif_tree_object~open Method The only reason we redened this method was to match the model with the different controller. METHOD lif_tree_object~open. CALL METHOD me->init_controller('LCL_CON_ALV_FACADE' ). ENDMETHOD.
'Facade'(fac) ).
www.sap-press.com
31
textedit TYPE REF TO cl_gui_textedit. METHODS: on_toolbar_func_sel FOR EVENT function_selected OF cl_gui_toolbar IMPORTING fcode sender, save, free. ENDCLASS. As you can see, the class consists of three attributes and four methods. s_thead Attribute This is a structure of type THEAD, and it represents the key values for accessing standard texts. The function modules READ_TEXT and SAVE_TEXT have parameters of the very same type. container Attribute This is a dialog-box container for the textedit control to open in. The only reason for the container to be an attribute ( rather than a methods local variable ) is to enable its destruction by the free method. textedit Attribute This is a standard textedit control. The same explanation applies regarding destruction as for container. constructor Method Since this class has no other purpose except to let users edit standard text, I didnt think that we needed a special method to open a user interface. The text editor can be opened directly in the constructor. First we must create the main container. For a change, lets make it a dialog box rather than a docking container. The text editor looks good in it. CREATE OBJECT me->container EXPORTING top left height width = 50 = 200 = 150 = 500
Actually, we need two containers: one for the text editor and another for the toolbar. The simple splitter accomplishes that, and we create it within the dialog box that we have just created. CREATE OBJECT o_splitter EXPORTING parent orientation = me->container =
o_splitter->orientation_vertical sash_position = 10. "percentage of " containers Now we can put a toolbar in the splitters upper container and append two buttons: Save and Close. CREATE OBJECT o_toolbar EXPORTING parent = o_splitter->top_left_container. CALL METHOD o_toolbar->add_button( fcode icon = 'SAVE' = icon_system_save
butn_type = cntb_btype_button ). Of course, we need to register methods for handling events that the toolbar res when the buttons are pressed. REFRESH t_events. s_event-eventid = cl_gui_toolbar=>m_id_function_selected. s_event-appl_event = 'X'. APPEND s_event TO t_events. CALL METHOD o_toolbar->set_registered_events EXPORTING events = t_events. SET HANDLER: me->on_toolbar_func_sel FOR o_toolbar. The textedit control is placed in the splitters bottom container.
caption = i_caption.
32
Index
A
Adapter 11, 19, 26 class lcl_application 21 interface lif_interface 20 aggregation 8 Alexander, Christopher 6 ALV grid 12, 30, 48, 49, 50, 59, 63, 64, 67, 68, 70, 71, 72, 74, 75, 80
F
Faade 11, 27, 36, 59 class lcl_mod_facade 30 class lcl_st_text_facade 31 field mappings table 52
multiple instantiation 16 MVC 11, 12, 63, 80 class lcl_con 66 class lcl_con_alv 71 class lcl_con_alv_facade 74 class lcl_con_dd 75 class lcl_mod 67
G
gang of four 6, 15, 19, 27, 37, 47, 63
R
reusability 49
C
CL_DD_DOCUMENT 65, 66, 70, 75 CL_GUI_ALV_GRID 64, 66, 71, 72 CL_GUI_DOCKING_CONTAINER 72 CL_GUI_SIMPLE_TREE 66 command tree 19 Company Decorator 61 Composite 11, 37, 46 class lcl_mod_composite 39 context menu 21 Controller 64
I
inheritance 8 internal table 48
S
SAPscript 63 Singleton 11, 12, 15, 17, 22 skins 80 SmartForms 63 Standard Text Decorator 59 state 64 sy-subrc 60
L
lcl_application 15, 16, 21, 70 lcl_con 66, 71 lcl_con_alv 66, 71 lcl_con_alv_facade 74 lcl_con_dd 66, 75 lcl_itab_dec 50, 53 lcl_itab_dec_company 61 lcl_itab_dec_material 61 lcl_itab_dec_st_text 59 lcl_itab_dec_vendor 53 lcl_mod 50, 61, 67 lcl_mod_composite 39, 68 lcl_mod_facade 30, 62 lcl_st_text_facade 31 lif_interface 20 lookup data, internal table 48
D
data-reference objects 66 Decorator 11, 12, 30, 47, 62 class lcl_itab_dec 50 class lcl_itab_dec_company 61 class lcl_itab_dec_material 61 class lcl_itab_dec_st_text 59 class lcl_itab_dec_vendor 53 implementation 61 naming conventions 48 demo application 11 Design Patterns definition 5 in software design 6 Dynamic Document 12, 63, 65, 70, 75, 80
T
text editor 30 transaction SO01 29
U
UML Class Diagram 8 Unified Modeling Language (UML) 8 usage 8 user-defined text 27
M
Material Decorator 61 model 63 Model-View-Controller MVC
V
Vendor Decorator 53 view 63
www.sap-press.com
85