ABAP Clean Design

Very often I am approached by developers, technical consultants and SAP enthusiast with the following question.

“What is the optimal way of writing code in ABAP? Is there any model or principle that should be followed?”

Well today I will take the opportunity to explain a few aspects of Clean Design that should be followed while coding in ABAP, or rather one should adhere to while coding in ABAP.

But before I move ahead, I would like to give you a short background on ABAP. Of course everyone of us are well aware of the history of ABAP. But I feel this is important to know before we move ahead.

ABAP was initially developed as a procedural language (just similar to earlier procedural programming language like COBOL). But ABAP has now adapted the principles of object oriented paradigms with the introduction of ABAP Objects. The object-oriented concepts in ABAP such as class, object, inheritance, and polymorphism, are essentially the same as those of other modern object-oriented languages such as Java or C++.

As object orientation begins to take shape, each class assumes specific role assignments. This division of labor helps to simplify the overall programming model, allowing each class to specialize in solving a particular piece of the problem at hand. Such classes have high cohesion and the operations of each class are closely related in some intuitive way.

The key features of object orientation are −

  • Effective programming structure.
  • Real-world entities can be modeled very well.
  • Stress on data security and access.
  • Minimizes code redundancy.
  • Data abstraction and encapsulation.

Now having said this, most of you might have guessed where the discussion is tending to.

Now most of us need to develop a class here and then to support various business objectives. And to do so, the easiest way, many of us choose is to create static classes with static methods and put our code into these methods and consider our job is done.

But do we consider the following points:

Are we actually imbibing the Object Oriented Behavior?

Does our class have any authenticity?

Well, to answer the first question. NO, we are not following the object oriented behavior. And to answer the second question, the authenticity of a class can be proved if it has a test class associated to it.

So let’s start with a simple example of a static class.

Now in this example, there is no abstraction nor encapsulation. Also, data security and access is NULL. Any body consuming this class, can access the members and can change the value of it. Also, the sole purpose of OOPs of having member functions, i.e., methods which operate on the members goes for a toss. Another, aspect from the authenticity point of view, no double class can be created and injected for this class during testing.

So, how can we address such a situation?

  • Always define methods and attributes as instance components.
  • Use singleton pattern only if really required.

This is a better design than before, as the attribute is private now. Hence, security and access to the data in the class is only possible via the method(s). So now we have restricted the member of the class to be manipulated by any consumer. Also, since there is no static method, a consumer needs to generate an instance to access the member functions, i.e., the method(s). So the member functions are bound to the instances generated. However, still the design is not perfect. Consider the following scenarios.

  • A user class needs to refer to this class. Therefore, it is not possible to replace this class with another class without changing the user class.
  • From testing purpose a double class needs to be a subclass of this class. Therefore this class cannot be final.

So, the above limitations can be removed by introducing an interface. User classes can refer to the interface and thus concrete on the methods and attributes they need. All other methods and attributes are private or protected and thus hidden or abstracted. Only immutable  & read only attributes are public.

Again, this is a better design but not very much on the cleaner side. We are able to remove the dependency of the user class which refers to our class by providing an interface for implementation by the user classes which needs to refer to our class. Also, as per to testing purpose, the double creation is now possible by using the interface, thus our class can be made final now.

However, for a consumer class, object creation is technical and complex as the constructor will have to offer optional parameters to allow the creation of different type of objects (use cases). And if the constructor contain all the logic and dependencies, these are going to be a part of every unit test and need to be inherited by subclass doubles. Also, by the look of the constructor we cannot ensure that if the class is singleton or not.

As a savior to above described limitation, offering at least one creation method per object type will allow simple and readable object creation with fewer (mostly non-optional) parameters. To enforce the exclusive use of the creation methods, the instantiation of the class needs to be made private. Also, by the labeling of the creation methods, we can clearly denote, if the instance to be returned is of singleton nature or not. [get for singleton instances and create for non-singleton instances]

This is a far better design than from what we had started. However, still there is a direct dependency from the class as the static creation method will be used. If many classes consumes this class, they will use the static creation method offered to instantiate the class. If tomorrow we need to replace the class with some other class, all the consuming classes needs to be modified. Also, a user class cannot collaborate with double class for isolated tests.

Hence, a better design will be to delegate the object creation for this class to a factory class. The user classes are no creator any longer. As global friend, factory class is the only class to access private creation methods of this class.

Now we can consider this to be a clean design, where we have factory to provide us with objects for different scenarios. Also, if tomorrow your class needs to be changed, the creation logic needs to be changed in the factory. Thus the consumer classes are void of any modifications.

This was a humble attempt form my end to explain how classes should be designed using Object Oriented approach adhering to a clean design concept. Kindly comment your feedback on this and if the community likes it, I will be share more content on the clean design aspect. Anyone can reach out to me with their queries on LinkedIn as well.

Since we all in a grave situation because of the COVID-19, lets utilize our free time and contribute as much possible to SAP community to build simple and robust code-base for the future.

#StayHome #StaySafe