Personal Insights
Thoughts on stable ABAP APIs
In this blog post, let’s look at APIs inside an ABAP system. A API in ABAP can be seen as a set of ABAP objects, for simplicity take DOMA + DTEL + TABL + TTYP + CLAS + INTF as an example.
I consider changes to an API to be stable if the changes in the API do not cause errors in the ABAP programs that consume the API.
Consistency
The set of objects in the API must be consistent, all objects referred must also be considered part of the API.
Example: The following interface refers to DTEL MANDT, which refers to DOMA MANDT, both being part of the definition for the “moo” method, and thus should be considered part of the API.
INTERFACE zif_bar.
METHODS moo IMPORTING iv_mandt TYPE mandt.
ENDINTERFACE.
The consumer of an API must be able to lookup all the details by looking just at the API, nothing more, nothing less.
Implementation code
Method implementation code is not part of the API, it is up to the provider of the API to have any implementation, which can change independently of the consumer.
Example: This implementation code refers to TABL T000, but its implementation code so not part of the API provided by CLAS ZCL_BAR
CLASS zcl_bar DEFINITION.
PUBLIC SECTION.
INTERFACES zif_bar.
ENDCLASS.
CLASS zcl_bar IMPLEMENTATION.
METHOD zif_bar~moo.
DATA impl TYPE t000.
ENDMETHOD.
ENDCLASS.
Use of the API is possible
If an interface is part of the API, the consumer must be able to implement the interface. Likewise, if a method is part of the API, a consumer must be able to call the API.
This easily follows if the API is consistent, but as ABAP is a large language, it takes effort to catch everything that should be part of the API.
Building new APIs
When building new APIs consider the following:
INTF should not reference CLAS objects, do proper OO design and define interfaces properly.
Don’t add Function Groups/Function Modules as part of an API, function modules have been considered obsolete for many years.
Stable changes
Following changes(and more?) are possible to make while keeping the API stable,
DOMA
- Compatible type changes, for example: extending a field from 20 characters to 30 characters
DTEL
- Changing to a type compatible domain
- Changing descriptions, it will not break the consumer programs
TABL
- Adding fields
TTYP
- Type compatible changes
INTF
- New optional parameters in methods
CLAS
- New methods
- New optional parameters in methods
Unstable changes
DOMA + DTEL
- Incompatible type changes
TABL
- Removing fields
- Renaming fields
- Incompatible type changes
TTYP
- Setting a new table key
INTF
- New methods(might cause syntax error in consumer implementations)
- Removing methods
- Removing mandatory method parameters
- Adding INTERFACES
CLAS
- Removing methods
- Removing mandatory method parameters
And I probably missed a lot of details, comments welcome below 🙂
Hi Lars,
I my opinion this is a very important point. People like to think of HTTP and REST, when they hear the word API. But thinking about APIs in custom ABAP codebases in terms of a set of small, loosley coupled "services" that can be accessed via stable interfaces can help to make development more efficient and harden the system.
I like to define the capabilities of such a service via interfaces. For each service these interfaces are stored in a extra package called Z*SERVICE*API, together with all relevant DDIC structures used in the interface and a factory class that allows to get an instance of the service. All other objects of the service are considered as internal and cannot be accessed from outside.
Best regards,
Ben
Hi,
why not adding new interfaces to a class?
Yea, thanks, that would be okay, always another example in ABAP 🙂
Hi Lars Hvam
nice blogpost.
But why do you consider adding an interface to a class an unstable change? IMO this is a nice example of a stable change. The current consumers can use the class as before. In addition the added interface supports new usage scenarios.
Christian
Thanks, see the comment above, I've updated the text in the post 🙂
Great writeup, Lars.
Definitely food for thought and an interesting starting point for ABAP code reviews.
Two comments:
Shouldn't this be refined to stable provided it are new fields at the last position of the table/structure?
Adding new fields elsewhere is potentially unstable (of course this should never be the case in an ideal world but hey, it's ABAP).
Shouldn't this be DOMA + DTEL?
Cheers
TABL: hmm, yea, I think you are right, thanks
DOMA + DOMA: thanks, updated
I'd go further. There are statements that stop working when adding certain types of structure components. For example adding a substructure or a table type makes it no longer a flat structure preventing certain statements, same with strings. I dont think all these statements are obsolete. Also keep in mind the enhancement category which aims to prevent this error when using appends.
Regarding DOMA: Even with compatible type changes, won't you get wrong behaviour if there are conversion exits in place and you have an old value somewhere that didn't get updated with the exit using the new length?
Good post Lars, programming in ABAP with an API principe is really nescecary. I'd like to think the main use case for API is MVC. Too many times people program directly in reports, function modules, webdynpro, gateway dpc classes, ... . How many times I've seen the UI change or additional requirements to automate something via job next to the manual report, if you programmed it clearly via API and MVC, reuse is almost 100%!
Hello Lars,
any change to the public interface is an Unstable Change. This means not only all changes to published routines the client could rely on, but also as you describe changes in the data dictionary can be unsafe.
Further, we must add the communication protocol to the API:
Let us image a API that allows to OPEN, READ and CLOSE a FILE. The implicit expectation (the communication protocol) is that a FILE is OPENed before it is READ. Now suppose the first version of the API allows multiple CLOSE operations on the same file without error.
A change to trigger an exception when CLOSE is called more than once is an Unstable Change that could potentially happen without change of the routine signature.
best regards,
JNN
Hi Lars,
sorry to say that, but there are a lot of gaps and inaccuracies in your writing. For example you claim that it would be stable to add a method to a class and unstable to add a method to an interface. Actually it is more ore less the other way around, respectively it depends.
It is stable to add a new method to an interface, as long as you use the addition DEFAULT IGNORE or DEFAULT FAIL.
And it is unstable to add a method to a class if this class is not declared as FINAL. Because then adding a method XYZ would break any sublass that also has declared XYZ already.
Regards,
Michael
Hi,
Thanks, I forgot about the DEFAULT IGNORE statements.
And true, there is the case where XYZ has already been defined in the subclass.
DEFAULT IGNORE/FAIL possible in v740sp08 and up
Furthermore, adding an interface to an interface can also be stable, as long as the added interface has no methods or only methods with addition DEFAULT... (see above).
Another unstable change would be to remove an interface from a class or interface, even if it has no methods, attributes or other members! This is because instances of the remaining class or interface can suddenly not be used any more in positions where a reference to the removed interface is needed.
Thanks, I've been considering moving the information to GitHub, so its possible to fix all my bugs 🙂
Its ABAP, its complex...
I disagree extending the length of a domain is a compatible change, as it generates incompatibilities in dependencies.
if I change zbar to be 4 characters I break this code.
Yes it's bad practice to rely of field lengths like that but still valid code
PS: this might also apply to foreign RFC clients which sometimes use fixed length fields to translate ABAP structures in native records
yea, thanks for the example