Code reuse is a very important aspect of programming. OO has some additional features for code reuse like inheritance and class interfaces.
In this design step you can become creative in finding the best reusable solutions based on the OO concepts. By OO concepts I mean the OO principles, SOLID principles, design patterns, anti-patterns and your own experience to make your solution as reusable as possible. See for an overview on OO concepts blog post
ABAP OO Design: Basic Terms Overview.
For now it is important to know the basic OO principles like instantiation, encapsulation / data hiding, inheritance, realization and polymorphism. If you do not know these terms, than please search them on the internet to have a basic knowledge on these terms.
Generalization
"Reuse optimization" is retrieving generic parts from a specific class a generic components. So you might expect that this is called
generalization. H
owever in OO design the term generalization is linked specific to inheritance and means designing a super class based on a sub class. (And specialization is creating a sub class based on a super class.)
However I like to use the word generalization for all kind generalizations, not only for inheritance, but also for creating a class interface, one or more composite child classes, dependency classes, moving data to parameters or moving data to the database. So generalization specific for inheritance will be called inheritance generalization.
Retrieving generic parts form the specific class
The goal of generalization is to retrieve
generic parts from the specific class. The generic parts can be data types, constants, data, method definition or a complete method. The generic parts can be moved to generic classes or class interfaces. Also hard coded data can be moved to the database.
The picture below mentions the components of a specific class which must be looked at for generalization.
This is what I call a technical way of looking at "generalization", these are the options of
what can be retrieved from a specific class.
A functional way of looking at these "generalization" is studying the OO concepts, because the concepts explain
why you should do it.
Generalization options
Here the generalization options which I use most:
- Parameterize
- Specific data in the class can be moved to the method parameters, and than it is not specific anymore.
- Separation of Concerns Class splitting
- If the class contains multiple responsibilities it could be an candidate to be split into into multiple classes.
- Data to database moving
- When the class contains hard code data, than it can be moved to the database.
For example hardcode text, which are translated to with text elements, can be moved to Standard texts (T: SO10). By adding a parameter to the method with the Standard text name the data has become from specific to generic.
- Move parameters to database
- When an interface has many parameters, you could decide to place those parameters in a database.
For example see table Output processing settings (TNAPR). Based on the field Output type (and some other key fields) you get all the settings for an output message.
- Moving code to another code language
- For example you coded ABAP to map data from an ABAP deep structure to HTML. This code could also be mapped using XSLT. XSLT is very useful for mapping to HTML.
- Adding a Facade class
- Facade generalization is based on the Facade pattern.
This is used when the specific method contains many method calls, which can also be reused for other objects. A new class can be created with a generic method interface calling these methods.
- Class Interface Abstraction
- Abstraction is "the process of removing characteristics in order to reduce it to a set of essential characteristics."
So Class interface abstraction means moving some method or all method definitions of a class to a separate Class Interface. This Class interface can be reused by multiple classes so these classes have a common interface.
A Class Interface contains only the definition and not implementation of methods. Classes which inherit from a Class Interface must implement the methods. This "inheriting" is called Realization.
An entire public section of a class can be separated from it’s implementation to a Class Interface. Or 1 or some method definitions can be placed in a separate Class Interface.
- Inheritance Generalization
- Create a super class from a sub class.
- Abstract super classes
Super classes can become too abstract to be a real life object and than the class is an Abstract class. An abstract class means that it can not be instantiated.
Within an abstract class a method can be implemented or can exist without implementation. An method without an implementation is called an abstract method.
Creating abstract classes is also called abstraction. Let's call it "Class abstraction" to distinct it from "Class interface abstraction".
To become a pro on "Reuse optimization" you can explore all OO concepts. You do not have to memorize them all. Just by seeing them you learn a lot about what is possible. A fun way of getting to know design patterns are the videos of Christopher Okhravi in his serie on
Design Patterns in Object Oriented Programming. And after that proceed with the rest of the "Gang of Four Design Patterns".
Where to start generalization?
Every class in the class diagram has to be checked for generalization.
Good practice is to start with the independent classes. An independent class is a class which does not depend another class (within the current class diagram). Mostly these classes are on the right side of the class diagram.
Handling the specific class after generalization
After the specific class is generalized, the specific class has to be modified.
The result can be:
- The specific class will become a subclass of the generic class.
- The specific class will instantiate the generic class.
- The specific class is not needed anymore and it will be deleted.
Generalization during design or during programming
It is good practice to do generalization always during design. But also during programming the generalization step can take place. The reason for doing it during programming is, that sometimes it is better to program first a not generalized specific class and after that one works, refactor it by applying generalization. The goal of this approach is to not get stuck in a too complex generalized class diagram. This approach is called
"Make it work. Make it right. Make it fast.". So make the "not generalized" class work first and after that make it a right by applying generalization.
A second reason for doing it during programming, is that you found out there is already a specific class containing the generic parts which can be reused. So you start
refactoring this specific class first.
Proceed...
In the next blog post the example conceptual class diagrams from the previous blog post will be generalized. Most of the generalization techniques mentioned in this blog post will be used.