You are on page 1of 8

Separation of Concerns

Background
The term 'separation of concerns' (SoC) was coined in Edsger W. Dijkstra's article On the role of
scientific thought from 1974:
"... But nothing is gained --on the contrary!-- by tackling these various aspects simultaneously. It
is what I sometimes have called 'the separation of concerns', which, even if not perfectly
possible, is yet the only available technique for effective ordering of one's thoughts, that I know
of. This is what I mean by 'focusing one's attention upon some aspect': it does not mean ignoring
the other aspects, it is just doing justice to the fact that from this aspect's point of view, the other
is irrelevant." (Springer-Verlag, 1982)
Separation of concerns is a principle used in programming to separate an application into units,
with minimal overlapping between the functions of the individual units. The separation of
concerns is achieved using modularization, encapsulation and arrangement in software layers.
Although the classic three-layer architecture of the SAP system - now named SAP NetWeaver
Application Server ABAP (AS ABAP) - is ideal for ABAP programming based on the SoC
principle, this possibility was never explored. Application programs (in other words, dialog
programs in module pools or reports in executable programs) were usually displayed as
monolithic blocks, in which the system simultaneously reacted to user actions of the presentation
layer, completed the application logic and executed accesses to data on the persistency layer.
This type of programming is no longer relevant in today's programming word, where concepts
like service-oriented architecture (SOA) set the trend.
Rule
Following the SoC Principle
Follow the separation of concerns principle. Model your applications strictly as serviceorientated applications. It is especially important that you separate the logic of the application
layer from the logic of the presentation layer, the persistency layer and the logic for
communication with external systems. Encapsulate the repository objects of the individual
concerns in separate packages.
Details
The SoC principle identifies the parts of an application with a specific purpose and encapsulates
these parts in closed units. These units only communicate with each other using specified
interfaces. Thanks to this principle, the software - which would have otherwise been
overcomplicated - is divided up into manageable components. As a result, the software is:

 more stable  easier to understand  easier to reuse  easier to transport  easier to maintain  easier to test Regarding the last point. automated module tests. Bad Example The following graphic shows two examples of an ABAP application that do not follow the SoC principle. In fact. it would even be true to say that following the SoC principle is a prerequisite for executing isolated. the two bad examples here are the programmer models for reporting and dialog programming that were propagated by SAP for a considerable length of time! This may sound .

this type of implementation would be too much for a simple program. We are convinced that the quality of these programs can be improved not only by following naming conventions. TRY. PARAMETERS p_carrid TYPE spfli-carrid. As a result. but also by changing the paradigm for the procedure used for programming tasks. Of course. real applications are usually very long ABAP programs (executable programs. This source code has the same functionality as the source code above. MESSAGE alv_exc TYPE 'I' DISPLAY LIKE 'E'. module pools). SORT spfli_tab BY cityfrom cityto. alv_exc TYPE REF TO cx_salv_msg. in which all concerns are handled at the same time. Both the data declarations and the implementation of the functions are mixed together. The following source codes proves that you can implement the SoC principle using classic ABAP procedural methods (in this case. the example is not bad due to the reporting or programming of transactions itself. DATA: spfli_tab TYPE STANDARD TABLE OF spfli alv TYPE REF TO cl_salv_table. cl_salv_table=>factory( IMPORTING r_salv_table = alv CHANGING t_table = spfli_tab ). as we have already stated. As we have already mentioned. alv->display( ). all the concerns are implemented in separate procedures that are assigned to layers. we want these programming guidelines to be more than just an introduction to our naming conventions. However. subprograms). it was usually restricted to reusing functional units and was rarely focused on the actual available layers. In addition. it would be too much to insist that concerns should be completely separated even in short programs like in the source code above. CATCH cx_salv_msg INTO alv_exc. However. SELECT * FROM spfli INTO TABLE spfli_tab WHERE carrid = p_carrid. REPORT z_non_soc_report. large volumes of global data were usually created that were used in different procedures and layers. data presentation and the associated declarations all occur in one single unit. To be more precise. but due to the way in which these applications are usually implemented. if you needed to test the . Access to persistent data.unbelievable but. ENDIF. all the parts of the program were inherently dependent on each other and could not be tested individually. However. The mini report in the following source code is a typical example of how different concerns are mixed together in a single program unit. ENDTRY. IF sy-subrc = 0. data processing. If modularization was performed.

DATA: carrid TYPE spfli-carrid. TRY. IF arc = 0 PERFORM sort_table CHANGING table. alv->display( ). TYPES spfli_tab TYPE STANDARD TABLE OF spfli. ENDFORM. PERFORM display_table USING table. CATCH cx_salv_msg INTO alv_exc. * Application layer FORM sort_table CHANGING table TYPE spfli_tab. DATA: alv TYPE REF TO cl_salv_table. FORM display_table USING table TYPE spfli_tab. IF sy-subrc = 0. arc TYPE sy-subrc. START-OF-SELECTION. REPORT z_soc_report. cl_salv_table=>factory( IMPORTING r_salv_table = alv CHANGING t_table = table ). CALL SELECTION-SCREEN 100. ENDFORM. PARAMETERS p_carrid TYPE spfli-carrid. * Presentation layer FORM get_carrid CHANGING value(carrid) TYPE spfli-carrid. carrid = p_carrid. the only possibility would be to adapt the source code as shown below. table TYPE spfli_tab. MESSAGE alv_exc TYPE 'I' DISPLAY LIKE 'E'. The program of the following source code can now be easily assigned test methods in ABAP unit test classes. SELECTION-SCREEN BEGIN OF SCREEN 100. . which test the individual procedures. ENDIF.concerns in the above source code individually and independently of each other by using module tests. ENDIF. ENDTRY. alv_exc TYPE REF TO cx_salv_msg. PERFORM get_table USING carrid CHANGING table arc. SELECTION-SCREEN END OF SCREEN 100. PERFORM get_carrid CHANGING carrid.

* Persistency layer FORM get_table USING carrid TYPE spfli-carrid CHANGING table TYPE spfli_tab arc TYPE sy-subrc. arc = sy-subrc. Good Example The following graphic shows how an ABAP application should look that follows the separation of concerns. SELECT * FROM spfli INTO TABLE table WHERE carrid = carrid. . The following source code shows how the separation of concerns should be implemented instead using methods in concern-specific classes. ENDFORM. However.SORT table BY cityfrom cityto. this separation of concerns using subprograms shown above does not create a good impression. ENDFORM.

These packages have package interfaces.After the concerns have been identified. A package can restrict the usability of its repository objects even more by using access control lists. SELECTION-SCREEN END OF SCREEN 100. encapsulating all database tables of an application in a package for persistency services prevents any program. The boxes for the individual concerns in the graphic represent packages. REPORT z_soc_class_report. repository objects in one package can only access the objects of another package using package interfaces. from accessing these database tables. PUBLIC SECTION. METHOD get_carrid. data types) belonging to a concern should be located in corresponding packages. The reverse is also true. In encapsulated packages. TYPES spfli_tab TYPE STANDARD TABLE OF spfli. programs in the persistency layer cannot communicate directly with components in the presentation layer. CLASS-METHODS: get_carrid RETURNING VALUE(carrid) TYPE spfli-carrid. which is often necessary. which is checked by the syntax check. You should prepare the package encapsulation (by choosing Package Check as Server) in the package properties. For example. SELECTION-SCREEN BEGIN OF SCREEN 100. PARAMETERS p_carrid TYPE spfli-carrid. they are implemented in ABAP object classes. such as a Web Dynpro ABAP application. All the repository objects (classes. Subdividing the separation of concerns in a package is a concept supported by subpackages. . A package check is performed during the extended program check. ENDCLASS. that does not belong to this package. display_table IMPORTING VALUE(table) TYPE spfli_tab. CLASS presentation_server IMPLEMENTATION. The package concept (encapsulated packages) supports this separation of concerns. For example. CLASS presentation_server DEFINITION. The following source code shows how to adapt the separation of concerns from the above source text for classes local to the program. The concerns shown in the graphic are the main tasks that are usually performed in ABAP application programming:  Communication with a user interface (UI) using UI services  Actual application logic  Access to persistent data using persistency services  Communication with external systems using proxy services These main rules can be subdivided further.

ENDCLASS. PUBLIC SECTION. CLASS-METHODS get_table IMPORTING carrid TYPE spfli-carrid EXPORTING table TYPE spfli_tab arc TYPE sy-subrc. ENDCLASS. alv_exc TYPE REF TO cx_salv_msg. MESSAGE alv_exc TYPE 'I' DISPLAY LIKE 'E'. CATCH cx_salv_msg INTO alv_exc. ENDCLASS. alv->display( ). PUBLIC SECTION. PUBLIC SECTION. ENDMETHOD. arc = sy-subrc. CLASS report DEFINITION. ENDMETHOD. METHOD get_table. DATA: alv TYPE REF TO cl_salv_table. ENDIF. SELECT * FROM spfli INTO TABLE table WHERE carrid = carrid. ENDMETHOD. IF sy-subrc = 0. cl_salv_table=>factory( IMPORTING r_salv_table = alv CHANGING t_table = table ). CLASS application_server DEFINITION. ENDTRY.CALL SELECTION-SCREEN 100. carrid = p_carrid. CLASS persistency_server IMPLEMENTATION. ENDCLASS. METHOD display_table. SORT table BY cityfrom cityto. CLASS-METHODS sort_table CHANGING table TYPE spfli_tab. TRY. CLASS persistency_server DEFINITION. CLASS application_server IMPLEMENTATION. ENDCLASS. METHOD sort_table. . ENDMETHOD.

real program units (unlike in the second source code). START-OF-SELECTION. CLASS report IMPLEMENTATION. The larger and more realistic the application program. METHOD main. At first glance. depending on the layer. In addition. But only on the first glance. A real application program usually only consists of 25 lines. table TYPE spfli_tab. carrid = presentation_server=>get_carrid( ). arc TYPE sy-subrc. in other words. It is only by using these interfaces that you can achieve the other benefits of separating the concerns (in addition to the testing capability achieved in the second source code). If the reuse options for ABAP Objects are used appropriately.CLASS-METHODS main. the individual steps are now wrapped in classes. but in global classes that are assigned to different packages. presentation_server=>display_table( table ). DATA: carrid TYPE spfli-carrid. it is even possible to reduce the amount of source code. application_server=>sort_table( CHANGING table = table ). These packages are connected to each other using package interfaces. the above source code appears to be very excessive compared to the first source code. ENDIF. . report=>main( ). ENDMETHOD. the smaller the proportion of the overhead that is generated from wrapping the concerns in classes. wrapping is not performed in one single program. persistency_server=>get_table( EXPORTING carrid = carrid IMPORTING table = table arc = arc ). In practice. ENDCLASS. ENDCLASS. IF arc = 0.