The issue perceived
Some developers have concerns about having too many classes affecting performance and maintainability.
Classes are a form of modularisation; in and of themselves, they have no significant effect on performance. It is in the use or implementation of classes that problems can arise.
What problems?
- Obsessions with pure object orientation
- Classes with too many methods and attributes
- Too detailed object orientation
- Designing objects for single use and not considering bulk actions. E.g. a class for handling materials - but then when a bunch of materials is needed, selecting each material singly, instead of select into table.
In my experience, ABAP Object orientation is more about considering the programming problems in terms of objects communicating with each other. E.g. userids, handlers (screen, database…), layers (MVC) - rather than traditional OO paradigm of “Everything is an object”. ABAP OO programming is rather different to most OO languages. Java, for example, has only a few programming keywords and basic types; ABAP is far richer and we should use that richness for our advantage.
Hit me with another class!
While too many classes can make an application overly complex, there are some scenarios that indicate you should be considering adding a class or two (or more).
- Your class is becoming complex and big
- Class is dealing with multiple conceptual objects
- Class is dealing with multiple responsibilities
- It becomes clear that there is scope for reuse for part of the class.
- Same code being used in two or more classes.
- Similar code is being used in two or more classes (add a class and use subclasses for the specialisation).
- Subclass where there are logical checks for a type.
- Similarly named methods
- CASE or IF..ELSE..(ELSEIF)... for different behaviour according to type, especially if it appears in multiple places.
Case study
Consider file handling. You might find you have many programs that read files from the user's PC. Each program might have code like this:
DATA(extension) = me->get_file_extension( filename ).
CASE extension.
WHEN 'CSV'.
me->read_data_from_csv( ).
WHEN 'XLSX'.
me->read_data_from_xlsx( ).
...
ENDCASE.
It makes sense in this case to create a class for handling files to take over common file handling tasks. In every program that needs to deal with files you could replace the above (and remove the specialised methods) with something like:
zcl_file_handler=>get_handler( file_name )->read_data( IMPORTING e_data = my_specific_data ).
Where
file_name contains the full name of the file, the static method
get_handler returns an instance of a file handler (factory pattern), and
my_specific_data is an internal table with fields for the data I need.
There are many types of files that can be uploaded from the PC, e.g. CSV, XLSX... so you would subclass the file handler with a class for CSV files, and another for XLSX files, with the specifics needed to generically load the different file types.
In this case
get_handler takes the file name and returns the correct subclass according to the file extension. In the subclasses,
read_data (which should be abstract in the superclass), dynamically fills the table e_data correctly with the contents of the file. Of course, error handling must be in place to deal with incorrectly formatted files.
Note, that if you need to handle more file types, or change the way an existing file type is handled (e.g. moving from reading XLSX via OLE, and instead using some of the classes that directly handle XLSX), you don't need to change any of the programs that use the file handler. Previously, you'd have to update each one, with all the effort and potential for mistakes that incurs.
Pragmatism
I've been programming using ABAP objects now for over 15 years. In that time, I've adopted what I consider a pragmatic approach to class creation
- Use classes to program in layers - UI, logic, DB etc. (Also known as separation of concerns).
- Make use of the richness of ABAP - e.g. consider internal tables as objects, with “methods” like READ, LOOP AT etc. Don't create a class that emulates Java or C++ iterators. (See this blog for a more detailed explanation)
- Use private methods to prevent duplicate code being written within a class
- Use additional classes where indicated above
- Stuff OO if it gets in the way of simplicity or performance critical operations!
- Be very careful with the database access layer, that in the pursuit of object orientation, performance is not sacrificed. (One reason I no longer use persistent objects).
Tl;DR - Take home lesson:
Create a new class where it makes programmatic sense.
- Properly designed developments are simpler, cheaper, more robust, safer to maintain and easier to test.
- Don’t not create a class just because you’re worried about too many classes.
- Don’t create a class for the sake of some programming philosophy.
- Do study design patterns and use them where appropriate.