Business Object classes play a key role in ABAP OO Design, because SAP transactions are almost always about Business Objects. In RAP there is no Business Object class, however there is a Behavior class. In RAP there are multiple development object which form together a Business Object. These objects are:
- CDS data modelling = CDS Root view
- Behavior definition
- Behavior class
This blog post is about bringing RAP and ABAP OO Design together. For this research I have used SAP Developers Tutorial “Create and Expose CDS Views (Unmanaged Scenario)“. I have extended this example with OO design.
RAP functionality can be split into querying and business object operations. Querying is out of scope for this blog post because it is completely handled by the RAP OData framework, so no extra coding needed over there. The focus for this blog post is on pulling the business logic out of the Behavior class and moving it to the Business Object class.
Strict mode
Before we start, first an important note. The developer tutorial is not yet based on behavior definition Strict mode that’s why in this example the Behavior class method “modify” is used instead of separate strict mode methods.
Introduction to RAP Behavior class
Let’s first have a look at how the behavior class works. I have created a class diagram of the tutorial example.
The behavior class does not have public, protected or private methods, because it is not allowed to call the behavior class directly. It must be called by the RAP framework, which means by an OData call or by using the statements READ/MODIFY ENTITY/ENTITIES.
In an unmanaged scenario the business logica and the persistence logic has to be placed in the behavior class. The unmanaged behavior class has two local classes to implement this logic. The first class is the Behavior handler, which handles the business logic for the read and modify (insert, udpate, delete) and also for adding validations and determinations. The second class is the Behavior saver which handles the persistence. In the class diagram are only the methods shown which are used in the tutorial.
The RAP service can be tested in the Preview app which can be started from the Service Binding. Below the scenarios for the booking are described and the calling of the behavior class.
- Booking list
- This is querying. The Behavior class is not used.
- Create booking
- Push button Create
- Fill the fields
- Push button Create
- Beh. class – behavior handler: method modify,
parameter roots_to_create is filled.- Table lhc_buffer=>mt_buffer is filled.
- Beh. class – behavior saver: method save.
- Table lhc_buffer=>mt_buffer is read.
- Statement INSERT is executed.
- Beh. class – behavior handler: method modify,
- Show booking
- Click in list on booking
- The Behavior class is not used
- Click in list on booking
- Edit booking
- Click in list on booking
- Click on button Edit
- Change fields
- Click on button Save
- Beh. class – behavior handler: method read
- Beh. class – behavior handler: method modify
parameter roots_to_update is filled- Table lhc_buffer=>mt_buffer is filled.
- Beh. class – behavior saver: method save is called.
- Table lhc_buffer=>mt_buffer is read.
- Statement UPDATE is executed.
- Delete booking
- Select in list a booking
- Click on button Delete
- Click on Yes
- Beh. class – behavior handler: method modify
parameter roots_to_delete is filled- Table lhc_buffer=>mt_buffer is filled.
- Beh. class – behavior saver: method save
- Table lhc_buffer=>mt_buffer is read.
- Statement DELETE is executed.
- Beh. class – behavior handler: method modify
Convert design from RAP to RAP OO design
A Business Object is always designed in the Business layer. In RAP the Business object is combination of
- CDS data modelling = Root view
- Behavior definition
- Behavior class
In OO these development objects are moved from the Business layer to the Interface layer, because the business logic will be moved from the Behavior class to the BO class. The SQL statements will be moved from the Behavior class to the Data Access Object class.
Basic OO Design Class Diagram
In the class diagram below these two classes are added.
- Booking Business Object class (BO)
- Booking Data Access Object (DAO).
This class diagram is created by applying the design patterns mentioned in the next paragraphs.
Apply “Data Access Object pattern” – DAO class
The DAO class is added for the database interaction. It executes the SQL statements SELECT, INSERT, UPDATE and DELETE.
In this case it has also logic for reading the last booking number (called booking id). But it does not have the logic for determining the new number, which is the last number + 1. Normally in SAP object numbers are determined by a separate object for number ranges, which grants that a number is unique.
The data of the object is kept in memory during a connection session in member variable BookingData. OData is stateless, that’s why the data is only in memory during one HTTP call.
The responsibility of the DAO is to read the data and keep the data in memory, change it and persist it to the database. The DAO will also delete a record when method DELETE is called.
The handling of the DAO is about 4 steps.
- Get the instance. (Method getDao or createDao)
- Execute action. (Method updateData, delete) (not needed for a create).
- Save action. (Executes the SQL statements)
- Commit work. (Confirm actions to the database.)
From specific DAO class to a generic DAO
In this example case the DAO class is a specific class for Bookings. Designing a a generic DAO class will speed up the process of developing unmanaged scenarios. Also the reading of the database can be improved to read only the required data which will improve the performance. This kind of design is called an Entity framework and is often combined with “Object-relational mapping (ORM)”.
In the managed scenario the DAO class is completely automated by SAP, so RAP has also it’s own Entity framework.
Unit testing
The DAO class is independent so it can be tested very well by making use of a unit test class in the Booking DAO class. See the unit test code on GitHub Booking DAO – unit test.
Apply “Business Object pattern” – BO class
The “Business Object pattern” introduces the Booking Business Object class. The business logic actions of the Behavior class are moved to the BO class.
The BO class is for executing validations, determinations, CRUD actions and other kind of actions. Other kind of actions are for example “Creating a Booking Email and sending it to the customer”. The BO class is not allowed to have any SQL statements. The BO class must use the DAO class to execute the database interaction so that the business layer and data access layer are separated. The reason for separating these classes are to makes the BO class code more readable and it makes the BO class independent of the database. So it is about “SOLID – S – Single Responsibility Principle” and “Segregation of Concerns”.
Unit testing
The BO class is independent of the RAP behavior class, so it can be tested by making use of method calls instead of RAP statements. (RAP statements are READ ENTITY / MODIFY ENTITY.)
The DAO class does not depend on other classes, so it can be tested very well by making use of a unit test class in the Booking BO class. See the unit test code on GitHub Booking BO – unit test.
Commit work
When the BO class is called from RAP framework the commit work is handled by the RAP framework. Adding a COMMIT WORK in the behavior handler or in the behavior saver class will result at syntax check time in message “The command “COMMIT” is not allowed in a BEHAVIOR class.“. Executing a COMMIT WORK in a class which is called by the behavior class will result at runtime in “BEHAVIOR_ILLEGAL_STATEMENT – Short Text Statement “COMMIT WORK” is not allowed with this status.“.
When the BO class is called from for example a unit test, than the COMMIT WORK has to be programmed explicitly. See for example to unit tests of the BO class in Booking BO – unit test.
Role of the Behavior class
Before applying OO design the behavior class was part of the Business layer. After applying OO design the behavior class is part of the interface layer. It acts as an adapter class between the RAP framework and the Business Object class. And that is good, because it contains RAP specific code which stays in the interface layer.
The local buffer class in the behavior class won’t be needed anymore, because the “Booking Business Object factory class” will buffer the Business Object instances.
In the code is clear that always calls the BO class, see Behavior class – local types code.
Reuse and unit test optimization
Optimized Class Diagram
It is good practice to split the public section of class (a.k.a. class interface) to separate “interface class”. This is the SOLID principle D – Dependency Inversion Principle. That makes it possible to have a reference to the interface instead of a concrete class. This makes it possible to use for example a test double class instead of the actual concrete class.
Also factory classes are added to separate the instantiation logic from the main class. This is called the “Factory Method pattern”.
Applying these two principles to the BO and DAO class results in this Class diagram.
This might look like a much more complex class diagram because the BO class and DAO class are both split into 4 “classes”. To keep the class diagram clearer you could choose not draw the interface classes and factory classes. Instead you could add “+ FT” and “+ IF” to the name of the main class, fore example “Booking BO + FT + IF”.
Apply “Factory method pattern” to BO class and DAO class
The factory method pattern means that the instantiation of the BO class is executed in the BO factory class. This will open up possibilities for
- Instantiating a sub class of the Booking BO class to make use of inheritance and polymorphism.
- Dependency injection for test double classes.
This pattern is also be applied to the DAO class.
Apply “Dependency injection” to factory classes
By applying the “Factory method pattern” also “Dependency injection” can be added. Therefor the static method setFactory() has to be added to the factory class for setting the Test double factory instance.
The explanation of test doubles is left out of scope for this blog post. For more information on test doubles see Open SAP course Writing Testable Code for ABAP.
Scenarios
- The list of bookings are shown.
- The Behavior class is not used. This is querying.
- The “request features” will be called, but these are not used in this scenario.
- Create booking
- Push button Create
- Fill the fields
- Push button Create
- Behv: Method modify is called, parameter roots_to_create is filled.
- BO FT class: createBookingBo()
- DAO FT class: createDao()
- Behv: Method save is called.
- BO FT class: save()
- BO class: save()
- DAO class: save() – SQL INSERT
- Behv: Method modify is called, parameter roots_to_create is filled.
- Show booking
- Click in list on booking
- The Behavior class is not used
- Click in list on booking
- Edit booking
- Click in list on booking
- Click on button Edit
- Change fields
- Click on button Save
- Behv: Method read is called
- BO class: getData()
- Behv: Method modify is called, parameter roots_to_update is filled
- BO class: updateData()
- DAO class: updateData()
- Behv: Method save is called.
- BO FT class: save()
- BO class: save()
- DAO class: save() – SQL UPDATE
- Behv: Method read is called
- Delete booking
- Select in list a booking
- Click on button Delete
- Click on Yes
- Behv: Method modify is called, parameter roots_to_delete is filled
- BO class: delete()
- Behv: Method save is called.
- BO FT class: save()
- BO class: save()
- DAO class: save() – SQL DELETE
- Behv: Method modify is called, parameter roots_to_delete is filled
Using Business Object class by Client classes
The term client class represents any class which will call the class under subject. The class under subject is in this case the Booking BO class. For OData calls the Booking BO class will be called by the RAP framework via the behavior class.
However now the business logic is moved from the Behavior class to the BO class, the BO class can also be called directly without using the RAP framework. The business logic is now independent of the RAP framework. Now any class in the business layer and any class in the interface layer can access the BO class by calling methods instead of READ / MODIFY ENTITY.
In the example class diagram below he client class can call the Booking BO operations.
Summary
Advantages
What are the advantages of applying OO design to RAP?
- By placing the business logic from the behavior class to the business object class we get full control of the instantiation of the business object class.
- It makes it possible to create unit tests based on test doubles.
For more information see course:Writing Testable Code for ABAP - Inheritance generalization and specialization can now be applied to the Business Object class. Also other patterns like factory method pattern and more constructional patterns can be applied.
- It makes it possible to create unit tests based on test doubles.
- The behavior class handles multiple BO instances at once. The business object class handles one BO instance, which makes the code better readable.
- All RAP specific logic is placed outside the Business layer and into the Interface layer. So there is a clear separation between Interface layer and Business layer.
- From an architectural point of view it is good practice to split the interface layer and business logic so you are more flexible in calling the logic. When SAP might introduce a new interface layer than you do not have to copy the code to the new framework. That’s why putting business logic in SAP GateWay also was not a good decision. The same for BOPF which added unnecessary complexity over plain ABAP OO.
- The persistence logic (SQL INSERT, UPDATE, DELETE) is split from the business logic by making use of a DAO class. The DAO class is independent therefor to be tested separately by a unit test class. By splitting the code from the behavior class the BO class code is more readable.
- Client classes can call the methods of the BO class and there do not need to use READ / MODIFY ENTITY. By just using plain ABAP OO the code is more readable.
- The class diagram will become more fine grained so there are more possibilities to make use of reuse and all the OO concepts and principles.
Disadvantages
What are the disadvantages of applying OO design to RAP?
- It will require more code but it is worth to split to logic considering the advantages.
Conclusion
My conclusion is that ABAP OO Design and RAP unmanaged scenario form a very good combination. Using RAP as an interface layer which is very good at OData and using OO design for BO and DAO logic to get the most out of all OO concepts for reuse optimization.
To gain experience with this, I recommend executing the mentioned tutorial and than applying the class diagram mentioned in this blog and download the code from GitHub to see the example code.
Code on GitHub
The ABAP code is placed on GitHub, see https://github.com/alwinvandeput/abap_oo_design_rap_unmanaged.
Up next…
In the upcoming blog post I will describe my research on applying OO design to the RAP managed scenario.