Posted: Sun Nov 04, 2007 5:29 pm Post subject: Development Standards-ABAP Programming Rules
Written by Sap Document
Tuesday, 22 August 2006
3.1.1 General Standards
· Before starting any development work, make sure that no existing functionality satisfies the same requirements. Then check for all user-exits and see if the required functionality can be achieved through them.
· The standard program pattern should be used for all programs.
· Use the "Pretty Printer" function in the ABAP Editor to properly format your program.
· ABAP programs that update master and transactional data MUST ALWAYS use SAP transaction codes (where transaction codes are available) by utilizing standard SAP Function Modules, BDC or 'call transaction' utilities. This ensures that logical units of work, rollback, locking operations and edits are performed. SAP tables MUST NEVER be updated directly.
· ABAP programs MUST NEVER be used to update configuration tables.
· SAP-delivered objects, including tables, ABAP programs, Dynpros, SAP transactions, etc. can only be modified according to the HPL Programme Modification Policy.
· If possible, write code that it is re-usable and can be stored in an include program.
· Keep program lengths to a minimum. Each program should handle a discrete problem.
· All programs must include proper error handling to avoid undesirable terminations. This means that the system status (SY-SUBRC) must be checked after every event in the program that changes it. Always test :
IF SY-SUBRC = 0
:::::::.
ELSE.
:::::::.
ENDIF.
A 'NE' (not equal to) search is more expensive.
· Use the CATCH/ENDCATCH statement to trap runtime errors.
· If there are a large number of data declarations necessary as part of a program, consider separating your declarations into a INCLUDE. The include name should be the same as the program name with the suffix '_TOP'
· Use subroutines (FORMS) whenever possible to improve readability and logic flow. Consider creating a subroutine whenever a block of code is called from multiple places in a program.
· R/3 provides a large amount of function modules that perform various tasks such as convert currencies, calculate dates, explode BOM's etc. In most cases, these modules are efficient and can reduce coding time, therefore they should be employed where possible. It is worth taking the time to search the function module library for a function that meets your requirements.
· Avoid the COMPUTE function if clearer ADDs, SUBTRACTs, MULTIPLYs, or DIVIDEs can be used.
· When assigning internal fields that are to hold values from databases, use the LIKE option to ensure that the variable has identical characteristics. Example:
DATA: WS_LIFNR LIKE LFA1-LIFNR.
· Use the INCLUDE statement for Data Declarations, PBO Dynpro modules, PAI Dynpro modules, Subroutines, and Individual Event Processing.
· Use an underscore (_) to connect multi-word variable names and/or MODULE names.
· When using the FILL statement, specify FILL FROM. For example, use FILL workarea FROM KA, instead of just FILL workarea.
· When a local variable is declared, it should be initialized in the declaration statement whenever possible.
· Use text elements to define a string constant or selection text. If the transport of text-elements is a problem, use data declared variables.
· Hardcoded values should never be used.
· No undocumented features of the ABAP language should be used.
· External PERFORMs should NOT be used.
3.1.2 Online Programs
3.1.2.1 General
· If the layout of screens is the same for multiple functions (such as ADD, MOVE, and DELETE), use the same screen for all functions. Use online status and security features to control which function is executed.
· Define all global data in the main program module instead of the PBO/PAI.
· To handle a lock entry failure, raise an error message (type E) preventing any further progress but leaving the user on the current screen. The user can take an alternative action or continue to try to lock the object. To minimize the impact on users, limit retries.
· When activating buttons or boxes, activate the associated text as well. This enables the user to click on the either button/box or the text.
· For additional standards, see the SAP online documentation, "SAP Styleguide".
3.1.2.2 Naming
· For online programs, the initial screen should always be 100. Screen numbering should follow functionality. For example:
100 - Initial
200 - Block 1
201 - Sub-functionality of Block 1
202 - Sub-functionality of Block 1
etc....
· Use Data Dictionary names (short, medium, long) for field text on screens where applicable.
· Preferably donot use the OK_CODE field as it fails at times. Instead always trap SY-UCOMM.
· Prefix radio buttons with RB_, push buttons with PB_, and check boxes with CB_.
3.1.3 Report Programs
· The only report screen is 1000, which is automatically assigned by SAP.
· When using the WRITE command, constants should be declared as pre-defined variables or defined as Text Elements. Hardcoded character strings should NOT be used alone. In cases where text elements are used, it should be defined and used in the WRITE command in addition to a corresponding string value. This technique ensures accuracy of output by using text elements, while improving readability of the program.
Example :
WRITE: /20 '*'(001),
/30 'Company Code Totals of Vendors'(002),
/30 'Company Code Overview per Vendor'(003),
/30 'and a Closing Sheet.'(004).
The same procedure applies for pre-defined variables.
· For list reports, include the following information in commented lines to give users a clear indication as to what the report consists of. For example:
- End-User Reports: selection criteria, entries found, requester, report name, date/time, exceptions, parameters, etc.
- Conversion/Interface Reports: number of records read, number of records processed, number of records written, date/time, transactions posted, etc.
3.1.4 Program Structure
ABAP is an event driven programming language. However, proper event driven program structure and modular coding is still important to maintain readability and efficiency of an ABAP program. A program should be divided into distinct sections which are properly documented in the code. Whenever possible, use function modules already available instead of creating new ones. Refer to the ISP program template in the Appendices section for the proper order and structure of your program.
Forms should not be too long to help ensure modularity and for ease of following the program logic.
All forms should be proceeded by the letter F and a number code to help identify related forms.
form f2000_main_processing.
perform f2100_modify_data.
perform f2200_calculation.
endform.
Note: If a form contains very general functionality that could be used in other programs, it may be useful to create it as a function module.
3.1.5 Readability
· Start each new command or clause on a new line. Do not put multiple commands on the same line.
· If a statement continues past one line, indent all subsequent lines.
· Skipped lines and indention should be used to promote clarity between sections of code as well as between file definitions and declarations.
· Use the Pretty Printer automatic formatting function for your programs to ensure uniform indentation of program code
· Standard Form headings. Add appropriate form description to these headings. Note: "Pretty Printer" only creates Form headings if no comment lines exists after previous ABAP statement.
3.1.6 Authorization Checks
As a rule, authorization checks should be used whenever appropriate to verify the access level of the user executing the program.
As of release 4.0A, SAP has introduced object-oriented elements into the ABAP language. However, we will not be using these techniques for any development, at least in the pre-implementation and post-implementation support period. Any development utilising object-oriented ABAP will not be approved for use in the production system.
3.1.7.2 Internal Tables
All ABAP programs should use internal tables that are populated in an initial data read phase. All work in the program should be done in or from these internal tables. This method is faster than using the actual database table and reduces the risk of table locks.
3.1.7.2.1 Defining Internal Tables
When defining a table the occurs statement only allocates an area in memory of the specified size. If more occurrences are needed during program execution the array is dynamically expanded. The execution is slower when outside the bounds of the array so therefore make it large enough to cater for most typical cases but not too large reserving unnecessary space.
Example :
DATA: BEGIN OF I_TAB OCCURS 100,
TELF1 LIKE KNA1-TELF1, "Phone no
BANKS LIKE KNBK-BANKS, "Bank
NAME1 LIKE KNA1-NAME1, "Last Name
END OF I_TAB.
NOTE: If you are unsure of the necessary table size or if it can vary dramatically i.e., 10 or 10,000 records depending on input parameters, then you are better off specifying the size as OCCURS 0. Rather it is always advisable to use OCCURS 0.
The access type of an internal table defines the way in which ABAP accesses the individual table entries. There are three access types: Standard, Sorted, and Hashed.
3.1.7.2.2 Standard Internal Tables
Standard tables have a linear index. You can access them using either the index or the key. If you use the key, the response time is in linear relationship to the number of table entries. The key of a standard table is always not unique, and you may not include any specification for the uniqueness in the table definition. This table type is particularly appropriate if you want to address individual table entries using the index. This is the quickest way to access table entries. To fill a standard table, append lines using the (APPEND) statement. You should read, modify and delete lines by referring to the index (INDEX option with the relevant ABAP command). The response time for accessing a standard table is in linear relation to the number of table entries. If you need to use key access, standard tables are appropriate if you can fill and process the table in separate steps. For example, you can fill a standard table by appending records and then sort it. If you then use key access with the binary search option (BINARY), the response time is in logarithmic relation to the number of table entries.
3.1.7.2.3 Sorted Internal Tables
Sorted tables are always saved correctly sorted by key. They also have a linear key, and, like standard tables, you can access them using either the table index or the key. When you use the key, the response time is in logarithmic relationship to the number of table entries, since the system uses a binary search. The key of a sorted table can be either unique, or non-unique, and you must specify either UNIQUE or NON-UNIQUE in the table definition. Standard tables and sorted tables both belong to the generic group index tables.
This table type is particularly suitable if you want the table to be sorted while you are still adding entries to it. You fill the table using the (INSERT) statement, according to the sort sequence defined in the table key. Table entries that do not fit are recognised before they are inserted. The response time for access using the key is in logarithmic relation to the number of table entries, since the system automatically uses a binary search. Sorted tables are appropriate for partially sequential processing in a LOOP, as long as the WHERE condition contains the beginning of the table key.
3.1.7.2.4 Hashed Internal Tables
Hashes tables have no internal linear index. You can only access hashed tables by specifying the key. The response time is constant, regardless of the number of table entries, since the search uses a hash algorithm. The key of a hashed table must be unique, and you must specify UNIQUE in the table definition.
This table type is particularly suitable if you want mainly to use key access for table entries. You cannot access hashed tables using the index. When you use key access, the response time remains constant, regardless of the number of table entries. As with database tables, the key of a hashed table is always unique. Hashed tables are therefore a useful way of constructing and using internal tables that are similar to database tables.
3.1.7.2.5 Collect
To fill a standard internal table without creating duplicate entries and add up the Packed, Integer, and Floating Point fields at the same time, use:
COLLECT itab.
but only for tables for which you expect approximately 50 entries or less. The COLLECT statement scans the table sequentially for a match on all fields that do not have a data type of Packed, Integer, or Floating-Point. Hence it is can be resource expensive for larger tables.
3.1.7.2.6 Into (Select Into)
To load an internal table from a database table where the structure of the internal table is the same as the structure of the database table use:
SELECT * FROM dbtab INTO TABLE itab.
instead of:
SELECT * FROM dbtab.
MOVE dbtab TO itab.
APPEND itab.
ENDSELECT.
3.1.7.3 Database Selections - General Rules
· Minimize database accesses. Keep the number of communication processes between the database and application servers, as well as the transferred dataset as small as possible.
· Do the most restrictive calls first. For example, to process all materials with a quantity-at-hand above 50, the tables containing stock quantities should be read before the material master tables.
3.1.7.3.1 Do not use Order By clause on non-key or non-indexed fields
Bring the data into an internal table with a single call and then sort the internal table. This relieves the database of the additional sort requirement and utilizes the processing and memory of the application server.
3.1.7.3.2 Decrease the number of Database Calls
In all cases look to decrease the number of database calls. Whenever possible issue calls to retrieve all records into an internal table. Do the processing using the internal table.
3.1.7.3.3 Nested Select Statements
Do not use any Nested Select statements under any circumstances.
3.1.7.3.4 Having Clause
In a SELECT statement, the HAVING clause allows you to specify a logical condition for the groups in a GROUP-BY clause. Effective use of the having clause can reduce the set of data transferred from the database to the application server. When the having clause is used, the aggregates and groups are constructed in the database instead of the application server, thereby reducing the resulting set.
3.1.7.3.5 Programs that update the database
When creating a program that writes new or update existing records you MUST secure that your program handles COMMIT at a reasonable frequency. As a general rule, you should do a commit every 1000 or 10 000 records. If your program is running for a long period of time without doing a commit, the data base and finally the whole system will be deadlocked and eventually shutting down the system is the only option left to terminate the execution as all resources are consumed by your program.
3.1.7.3.6 Use Open SQL
Open SQL is SAP's version of SQL and is designed to work with most RDBMS Systems (Relational Database Management Systems). Avoid using any native SQL features as they are not recommended.
3.1.7.4 Select Clauses
· To avoid performance problems as large part of the key as possible should be specified in a select clause.
· If you only are interested in a few fields from a table,
DO: select <field1> <field2>... from <tab> into <wa> <wa> where....
This technique will improve performance and use of internal memory.
DO NOT: select * from <tab> where....
· Use select single * from ... as much as possible. Only use select * from ... when absolutely necessary. Select single will return only one record. However, if you don't specify the whole key to the table, the returned record will be any line of the records that meets the specified key. Only use Select Single when the full key of the table is known.
· Specifying values for as many of the table's key fields in a WHERE clause will make the SELECT statement more efficient than checking values after the select.
· Never use any processing statement within SELECT ::: ENESELECT. In case it is required, populate an internal table corresponding to the table, loop at the internal table and do the processing there.
· Specifying the 'left-most'/least specific key fields in a WHERE clause improves efficiency.
For example, the key fields (in sequence) of the table KNC3 (Customer special G/L transaction )
MANDT - Client
KUNNR - Customer number
BUKRS - Company code
GJAHR - Fiscal year
SHBKZ - Special G/L indicator
When selecting data from this table, it would be more efficient to specify a value in the WHERE clause for the field KNC3-BUKRS, rather than KNC3-GJAHR. That is:
SELECT * FROM KNC3
WHERE KUNNR EQ '0000000001'
AND BUKRS EQ 'US01'.
.. ..
ENDSELECT.
will be more efficient than:
SELECT * FROM KNC3
WHERE KUNNR EQ '0000000001'
AND GJAHR EQ '1996'.
....
ENDSELECT.
· You can specify as many WHERE conditions as you like in all types of database tables ? i.e. transparent tables, pool tables and cluster tables. However, you should be aware for performance reasons that complex WHERE conditions involving pool and cluster tables usually cannot be passed to the database system. They must be processed by the SAP database interface through post?selection.
· Selecting via non-key fields. When selecting records from a database table when only part of a field (on which selection is based) is known, use the LIKE option as part of the WHERE clause.
For example:
SELECT * FROM T001G
WHERE BUKRS EQ 'US01'
AND TXTKO LIKE '__PERS%'.
....
ENDSELECT.
is more efficient than:
SELECT * FROM T001G
WHERE BUKRS EQ 'US01'.
CHECK T001G-TXTKO+2(4) = 'PERS'.
3.1.7.5 Defining Variables
· When defining variable use "LIKE" as much as possible to ensure automatic consistency with the items in the R/3 tables.
· All variables should have a description to the right of the declaration.
· Always keep the SAP names. DO NOT "translate". If you need the same type of data from different tables like document numbers for different documents, prefix the name with the table name like:
WS_VBAK_VBELN "Sales Order No.
WS_LIKP_VBELN "Delivery No.
3.1.7.6 Testing one field for multiple values
When testing an individual field for multiple values, you can use:
IF field = value1.
....
ELSEIF field = value2.
....
ELSEIF field = value3.
....
or
CASE field.
WHEN value1.
....
WHEN value2.
....
WHEN value3.
....
ENDCASE.
The first method is more efficient when checking a field for up to about five values. Beyond this, you should use the CASE statement. At this point it becomes more efficient than the nested Ifs, and will also improve the readability of the program code
3.1.7.7 Optimizing IF and CASE structures
To optimize IF and CASE structures, always test values in order of the likelihood of each value occurring.
For example, WS_FIELDX can have values 'A', 'B', or 'C'. A value of 'B' is the most likely value to occur, followed by 'C', then 'A'. To optimize a CASE statement for WS_FIELDX, code the CASE statement as follows:
CASE WS_fieldx.
WHEN 'B'. "Most likely value
....
WHEN 'C'. "Next most likely value
....
WHEN 'A'. "Least likely value
....
ENDCASE.
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
All product names are trademarks of their respective companies. SAPNET.RU websites are in no way affiliated with SAP AG. SAP, SAP R/3, R/3 software, mySAP, ABAP, BAPI, xApps, SAP NetWeaver and any other are registered trademarks of SAP AG. Every effort is made to ensure content integrity. Use information on this site at your own risk.