Hello SAP, where are my APIs?
This is a blog post I wanted to write for quite some time and my first try on writing a rant. And what could be a better set up for a rant than a broken heel at the beginning of summer?
Before starting to work in the area of SAP CRM and SAP IS-U most of the development I did was on the Java platform. When starting to develop on the SAP Netweaver platform two things really struck me. The first one was the lack of n modern IDE, the second one the lack of consistent, well documented, object oriented APIs. The first problem has recently been solved for by ABAP in Eclipse. The second one will be the topic of this blog post. The missing of consistent, well documented, object oriented APIs is in my opinion the result of a missing focus on API design by SAP. While some areas of the Netweaver platform offer rather nice APIs, most parts and almost all applications are lacking them.
Symptoms of the missing APIs
I think there are quite a number of issues resulting from missing API design. These range from increased development effort to problems during EhP upgrades. From my experience most of these issues are symptoms caused by the following underlying problems:
- Working on the wrong abstraction level
- Duplication of functionality by creating custom APIs
In the following section I’ll describe each of these problems and the symptoms causedby them in some more detail.
Working on the wrong abstraction level
If you follow some of the different space on SDN for some time, you will most likely recognize that some similar questions are asked again and again. These questions usually contain some patterns like, “which table stores information X”, “how is table Y linked to table Z” or “how to update table W”. These kinds of questions in my opinion usually show that someone is working on the wrong abstraction level. The underlying requirements for these questions are the need to read or update some business object stored in one of the tables. For example, instead of asking how to update table BUT050 the real requirement is how to add a business partner relation to a business partner. However, as the available APIs do not abstract from the underlying tables, developers tend to think and work on the table level rather than on the more suitable business object level.
The result of working on the wrong abstraction level is ultimately bad design and bad code quality. If developers think in terms of databases tables instead of objects they will most likely write select and update statements across their code. The result of this is code that is difficult to test and hard to maintain.
Duplication of functionality by creating custom APIs
When no suitable APIs are available developers tend to redevelop similar functionality over and over again. This is not only true for custom developments but also for the SAP standard. For example, a simple search for all usages of the BAL_LOG_MSG_ADD function module in one of our CRM systems revealed about 50 classes using this function module. The following list contains some of the classes I found:
- CL_CRM_LOG
- CL_CRM_BSP_CU_APPLOG
- CL_CRM_BSP_CU_APPLOG
- CL_DMC_APPL_LOG
- CL_LOG_PPF
All of these classes try to wrap the function module based API of the application log with an object oriented one. Each of these classes does more or less the same with some slight variations to it. In addition to the SAP standard classes wrapping the application log I also found some Z-classes as well as on “standard” class in our own namespace.
Duplication of code or functionality is always bad design. The lack of easy to use APIs even for basic tasks like logging fosters duplication. This ultimately results in increases defect rates in custom code and leads to longer development times and / or lower quality.
Features of good API design
Good API design is an extensively discussed topic. For this blog I will use a list of features for good API design initially given by Joshua Bloch in his talk “How to design a good API and why it matter” (cf. http://lcsd05.cs.tamu.edu/slides/keynote.pdf or How to Design a Good API & Why it Matters). According to Joshua Bloch a good API is
- Easy to learn
- Easy to use, even without documentation
- Hard to misuse
- Results in easy to read and maintainable code
- Sufficiently powerful to satisfy requirements
- Easy to extend / evolve
- Appropriate to the audience.
In the context of development on the SAP Netweaver platform I would extend the list above by the requirement for the API to be object oriented. In my opinion most of the APIs provided by SAP fail according to the above characteristics.
An Example of current APIs: The business partner APIs
In the following sections I will analyze the APIs currently provided by SAP with respect to the characteristics mentioned above. As an example for this analysis I will use the different APIs for business partners.
There are two business partner APIs that are regularly use in the context of SAP CRM and SAP IS-U (besides the ever so common SELECT * FROM BUT000 ;). These are
- the business partner BAPI API
- the CRM BOL API.
I know there are quite a number of other APIs for business partner, but for the purpose of this blog I focus on these two. The use case I will use to analyze the APIs is to search for a business partner with a given name and read its default address.
The business partner BAPI API
Using the BAPI API this use case can be implemented using the following code. Note that I did not implement any error handling here to keep the example more concise. Furthermore, I did not take into account the possibility of having different kinds (e.g. person, organization or group) of business partners to simply things further.
DATA: search_data TYPE bapibus1006_central_search,
search_results TYPE TABLE OF bapibus1006_bp_addr,
central_data_person TYPE bapibus1006_central_person,
address_guid TYPE bu_address_guid,
address_guid_32 TYPE sysuuid_c,
address_data TYPE bapibus1006_address,
return_vals TYPE TABLE OF bapiret2,
address_string TYPE string.
FIELD-SYMBOLS: <search_result> TYPE bapibus1006_bp_addr.
search_data-mc_name1 = 'Test'.
CALL FUNCTION 'BAPI_BUPA_SEARCH_2'
EXPORTING
centraldata = search_data
TABLES
searchresult = search_results
return = return_vals.
READ TABLE search_results ASSIGNING <search_result> INDEX 1.
CALL FUNCTION 'BAPI_BUPA_CENTRAL_GETDETAIL'
EXPORTING
businesspartner = <search_result>-partner
IMPORTING
centraldataperson = central_data_person.
CALL FUNCTION 'BAPI_BUPA_ADDRESSES_GET'
EXPORTING
businesspartner = <search_result>-partner
IMPORTING
standardaddressguid = address_guid.
address_guid_32 = address_guid.
CALL FUNCTION 'BAPI_BUPA_ADDRESS_GETDETAIL'
EXPORTING
businesspartner = <search_result>-partner
addressguid = address_guid_32
IMPORTING
addressdata = address_data.
WRITE / central_data_person-fullname.
WRITE / address_data-street && ` ` && address_data-house_no && `, ` && address_data-city.
Analyzing this piece of code and the BAPI API according to the criteria mentioned above I came to the results listed in the table below. While the analysis is certainly subjective I think it points out some of the problems with the BAPI API. In my opinion the major problem is the need to know the underlying database mode in detail to being able to use the API. In summary I think the BAPI API for business partners is not a good API with regard to the criteria.
Criteria | Analysis |
Object Oriented |
The API is based on function modules and not object oriented. |
Easy to learn | In my opinion the API is tied very closely to the underlying data base model. Without a sound understanding of this data base model it is very difficult to guess which function modules to use to get which data. For example, it is not clear which fields to use to search for a business partner name without knowing the underlying database model. |
Easy to use, even without documentation |
As stated above the API is not usable without a sound understanding of the business partner data model. |
Hard to misuse |
It is easy to misuse the API. For example, it is quite easy to miss the need to convert between the different GUID representations used in the API resulting in a dump during runtime. |
Results in easy to read and maintainable code |
As the code is based on function modules it is not very concise and therefore harder to read. However, once one understands the API the core is reasonably well read and maintainable. |
Sufficiently powerful to satisfy requirements |
It is definitely powerful enough to fulfill the requirements for reading, storing and updating business partner data. |
Easy to extend / evolve |
The API can only be extended using the enhancement techniques (e.g. BAdIs or implicit enhancement points) provided by SAP. |
Appropriate to the audience. |
The BAPI API is not appropriate for its audience as it forces developers to switch between an object oriented and the structured programming model. Furthermore, it requires developers to understand the underlying database model in detail. |
The CRM BOL API
Implementing the same use case using the CRM BOL API results in the following code. Again I omitted some error handling as well as the handling of different business partner.
DATA: bol_core TYPE REF TO cl_crm_bol_core,
query TYPE REF TO cl_crm_bol_query_service,
query_result TYPE REF TO if_bol_entity_col,
bp_entity TYPE REF TO cl_crm_bol_entity,
address_entity TYPE REF TO cl_crm_bol_entity,
related_entities TYPE REF TO if_bol_entity_col,
full_name TYPE string,
street TYPE string,
house_nr TYPE string,
city TYPE string.
bol_core = cl_crm_bol_core=>get_instance( ).
bol_core->start_up( iv_appl_name = 'BP_APPL' ).
query = cl_crm_bol_query_service=>get_instance( 'BuilHeaderSearch' ).
query->set_property( iv_attr_name = 'MC_NAME1'
iv_value = 'Test' ).
query_result = query->get_query_result( ).
bp_entity = query_result->get_first( ).
related_entities = bp_entity->get_related_entities( iv_relation_name = 'BuilAddressRel').
address_entity = related_entities->get_first( ).
full_name = bp_entity->get_property_as_string( iv_attr_name = 'FULLNAME' ).
street = address_entity->get_property_as_string( iv_attr_name = 'STREET' ).
house_nr = address_entity->get_property_as_string( iv_attr_name = 'HOUSE_NO' ).
city = address_entity->get_property_as_string( iv_attr_name = 'CITY' ).
WRITE / full_name.
WRITE / street && ` ` && house_nr && `, ` && city.
In contrast to the BAPI API the code of the BOL API is more concise and therefore a little more readable. In contrast to the BAPI API the need to use several auxiliary variables (e.g. street, house_nr and city) leads to some additional code . These auxiliary variables could be omitted if I had used the GET_PROPERTIES method instead. However, in my opinion the reading the properties individually is easier to read and therefore leads to cleaner code. While the BOL API is a significant improvement over the BAPI API with respect to readability, there are still a number of problems I see with this API. Still it is necessary to know the underlying data mode quite well in order to perform a query. Furthermore, the API uses a lot of magic strings (e.g. relation names, property names) that need to be taken from the BOL model (using transaction GENIL_MODEL_BROWSER). This complicates developing using the BOL API as, for example, code completion is not available to read relations and attributes. With respect to the API criteria above the BOL API still fails in some important areas
Criteria |
Analysis |
Object Oriented |
The API is object oriented. However, the business objects are not first class citizens of the API. |
Easy to learn |
The core BOL API is reasonable easy to learn. However, the usage of the API requires a constant look up of the BOL model. Furthermore, there is no consistent implementation of the BOL model across different applications (e.g. business partner vs. IS-U integration). Sometimes certain parts of the API (e.g. certain queries) simply do not work as expected. |
Easy to use, even without documentation |
As stated above the core BOL API is reasonable easy to learn. |
Hard to misuse |
It is still easy to misuse the API resulting especially in the more advanced areas like changing entities and transaction handling. |
Results in easy to read and maintainable code | The code using the BOL API tends to be more concise then the code of the BAPI API. However, the extensive use of magic strings still results in quite unreadable code especially in more complex scenarios. |
Sufficiently powerful to satisfy requirements |
The BOL API is definitely powerful enough to fulfill the requirements for reading, storing and updating business partner data. |
Easy to extend / evolve |
The core part of the API can only be extended using the enhancement techniques (e.g. BAdIs or implicit enhancement points) provided by SAP. In contrast to that, the application model (e.g. the business partner model) can be extended using a combination of customizing and custom code. |
Appropriate to the audience. |
The BOL API was designed to build the CRM Web UI and enable a separation of the application data model and the underlying database model. However, I think the BOL API still is not a really usable API for business partners. |
What the business partner API should look like
If I lookat the task I used to analyze the business partner APIs, namely to search for a business partner with a given name and read its default address, and think of a nice API for this I end up with something like the code below:
DATA: query TYPE REF TO cl_bp_query_serice,
query_result_col TYPE REF TO cl_collection,
bp TYPE REF TO cl_bp,
bp_address TYPE cl_bp_adress,
street TYPE string,
house_nr TYPE string,
city TYPE string.
query_result_col = query->query_by_name( 'Test' ).
bp = query_result_col->get_next( ).
bp_address = bp->get_standard_address( ).
street = bp_address->get_street( ).
house_nr = bp_address->get_house_nr( ).
city = bp_address->get_city( ).
WRITE / bp->get_full_name( ).
WRITE / street && ` ` && house_nr && `, ` && city.
When I look at the code of this imaginary business partner API it has multiple advantages over the existing ones:
- It is really object oriented
- The code is concise and readable, the intention of the code becomes immediately clear.
- It would be very easy to learn and use without any documentation as the objects and its methods speak for themselves.
- It’s the kind of API I as a developer are looking for.
I know that my nice imaginary API cuts some corners and omits some of the complexity that underlies the business partner data model. However, I’m sure that with a focus on API design this is what SAP APIs could look like.
Summary
So what the result of all this?
First, all SAP applications I’ve been working with suffer from the same problems, there are no suitable APIs. If you need further examples have a look at the CRM one order API or even worse some of the SPA IS-U APIs.
Second, I think SAP should focus on API design and developer productivity as an important part of the product development process. SAP products (at least the on premise solutions) are basically never used out of the box. In all SAP installations custom code is necessary to adapt the standard software to the needs of the customers. By providing usable APIs SAP could significantly reduce the necessary development efforts and implementation time, increase the quality of custom code and, ultimately, reduce the TCO of the overall solution.
So, SAP when are us starting to build some nice APIs for us?
Christian
Really nice blog!! I wish SAP implements your suggestions 🙂
A really well thought out and articulated piece Christian.
Those following this topic might also be interested in my Dude, Where's my API? post from earlier this year and the Google+ hangout it refers to.
Cheers
Graham Robbo
Hi Graham,
thanks for the link. I somehow missed this post. I'll definitely have a look at it and I also need to follow the SAP developer center space.
Christian
Good post Christian. Its a shame that we as developers & customers of SAP have to try and lead the way with providing an OO model via projects like: EsperancaB/sap_project_object · GitHub .
Its great that folks are contributing to these projects but like you indicate its time SAP took a long hard look at the mess of function modules they have accumulated over the years and give us a nice clean API like your example scenario.
Chris
I don't believe the underlying code base and application logic lend themselves to building APIs well at all... Read API, probably yes. Modification... I really don't know...
I wish the best of luck to any team setting out to wrap just the two basic entities used in IS-U (Business Partner and Contract Account) in a usable API, without extensive modification of existing code. For building new applications (is there a business case for SAP to try to re-factor existing SAP Applications to new API?)... At the end of the day deep down I will still be thinking: fine, now the FKK_SEPA_BEFORE_SAVE and the rest of FKK_SEPA piggies have got themselves a nice OO lipstick 🙂
Hi Janis,
I agree with you that building a useable API is a very hard task. Especially in the area of IS-U the existing code base won't support the creation of a nice, easy to use API. Therefore, building APIs for existing application like IS-U will require large development efforts. And just writing some simple OO wrapper around exiting function modules won’T do the trick.
SEPA is a great example in this respect. If you search for SEPA related note on the SAP service portal you'll find 112 notes released in may alone! For me this is a clear indicator
that even SAP is struggling to extend existing application. For customers this problem is even worse as they will have to build on the basis provided by SAP. For a regulatory requirement like SEPA this results in large project efforts for customers (due to the poor quality of the delivered SEPA implementation, missing APIs etc.) and, ultimately, in a high TCO for the overall solution. And the overall TCO is in my opinion where the business case for SAP is. SAP needs customers to help to lower TCO in order to being able to compete with its solutions with other vendors. APIs and developer productivity are an important building block there and an area where SAP has a lot of work to do. I think SAP will have to invest and improve in the area of APIs even within existing applications.
Christian
Seriously... I have to disagree with your post, the problem is you are thinking like a java developer expecting ABAP to behave that way. Your example of an ideal API is actually way worse than the BOL example, because you want API to provide you hardcoded methods for everything. Providing dynamic property attributes instead of hardcoded SET/GET for everything works much better and you abstract anything.
Next your biggest problem is complaining about the code not being object-oriented and not liking that switch. Just because something it's object oriented doesn't mean it not's designed right. The data model for one-order and the business partner are pretty darn powerful and "timeless". They were designed so well that SAP has put at least five or six different UI's on top of the core API.
Finally you need to learn the data model to really be able to develop with SAP CRM. Sorry but expecting the API defintion to do all the work for you is lazy.
Take care,
Stephen
Hi Stephen,
thanks for your reply. Finally some controversy here 😉
You are quite right withyour remark that I thinks like a Java developer (sometimes). I don't thinks that is a bad thing so. Some other languages / frameworks provide good solutions for things that are difficult in ABAP and vice versa. I agree with you that it might be no option to hardcode all the setter and getters. But I could think of different solution like code generation or meta programming to solve this issues. ABAP keeps evolving as a language, maybe sometime there will be different solutions available.
I also think the data models for BP and one order are great data model. As you mentioned the five or six UI on top of these data models as well as their usage across industries and applications prove their quality. However, I don't think these data model
should be visible in the API as much as it is currently the case. For example, it shouldn't matter for me as a developer how the data is stored on the DB (unless I want to change or extend the data model). Why do I have to read different fields if I want the name of a BP of type group, person or organization? An API should abstract away such details on the first level but provide access to them if needed. I think such features are easier to provide in an OO API. Nevertheless you are right, even a function module based API can be a good API.
For me abstracting some details of the underlying database model is not a question of being too lazy to learn but rather a question of separation of concerns. If for whatever
reason (e.g. a big change like HANA enablement) the database model would have to change, all applications that are tied closely to these database models need to change as well. If you have a layer of separation in between you might get away with a lot less change.
Finally, I really like the BOL API compared to e.g. all of the SAP IS-U APIs at it at least abstracts some things. 😉
Christian
You realize that for business partner that most of those API's are already abstractions on top of the physical database tables. Trust me those API's would a lot worse if they were exact 1:1 to the physical tables. Have you ever used SD11 and looked at PRM_BP?
In terms of having separate name fields, that's not a database design, that's a model design. Could it been designed better? Yes, but it's really a non-starter. I would think you would much rather want to complain about the underlying db model for marketing attributes assigned to business partners or perhaps sales area data.
In terms of HANA I actually asked about CRMD_ORDER_INDEX and questions on whether putting CRM on HANA would that need to be 'removed'. The answer was no and was useful in a HANA based environment. However I woudl agree that the entire application from the ground up needs to be rewritten if you truly want to talk about HANA.
The BOL is much better compared to other options. I really wish SAP would have extended the BOL concept fully in ERP. They then could have slowed decoupled the old db model away from the current application model.
Take care,
Stephen
Hi Stephen,
yes I realize that the BAPI APIs are already an abstraction over the DB model. For example BUT000 contains attributes of organizations, groups and persons whereas the data model of the API separates those already. However, the underlying DB design if frequently visible in the API as well. For example, we need to pass primary keys of the DB tables between different API calls (e.g. the address number or the address guid). This is also a reason why I favor OO APIs. They allow to easily abstracting away such details.
I totally agree that that SAP should have extended the BOL concept also to ERP. The same is true for the BOPF which also seems to be a very good option (I haven’t used it in a project so far myself). However, such concepts never seem to be extended beyond the scope of the application they were developed in. This is another reason why I think SAP should focus on API design in the development process in order to extend good concepts across applications.
Christian
At a risk of derailing this discussion... would the BOL-Genil handle this scenario with ease: in one LUW, create the Business Partner bank detail and assign it to Contract Account (or the equivalent thereof in CRM)?
Since the scenario appears to be implemented in FPP4 (just look at the number of bugs for that baby), the underlying "business logic" of application(s) should be supporting it. I know of no way to implement it using IS-U BAPIs, however... The rationale for having it - so the application does not need to start keeping "process containers" and support restart capabilities for the simplest of "processes". Less work for Utilities Check Cockpit, in other words 🙂
Would the BOL-Genil permit instantiating Business Partner from (structured) data? The rationale: when extending SAP standard, more often than not the data is already read (in SAP standard) and passed around. There is enough (mass) processing where querying again would impose unacceptable performance penalties.
I apologize if those are basic questions - I did look around trying to find the answers 🙂
cheers
Janis
Hi Janis,
the BOL should handle both scenarios you described without any problem. For example, the SAP standard allows to create new bank data and assign it to a newly created contract account when creating a new contract in the UTIL_IC role (component IUICCON).
Christian
Thank you, Christian - I'll be suggesting to colleagues that we invest time to understand if we can use BOL in ERP somehow and if it would be a suitable fit in terms of target architecture and all our "pet features" for building our own business entity layer, at least when it comes to BP and CA. The magic strings can be dealt with, if they are hidden away in one place (a factory, for example). Same with the BP names, I believe.
I actually think that the customers, when embarking on extensive development projects in or on top of SAP applications, must invest in their own API, if they find no suitable stuff in SAP. And, despite some of the tradeoffs, that there should be no more than one call to any SAP standard FM (released or otherwise) in custom code - in a (static) wrapper method, that maps from parameters in own naming convention to FM interface and turns the FM exceptions into exception classes 🙂
Hi Janis,
OK I guess misunderstood you questions. Although the BOL is available in ERP there are basically no implementations of BOL objects delivered. AFAIK the BOL isn't used in SAP
standard code anywhere in ERP. My statement was only true for the BOL in CRM. While you could certainly use the BOL in ERP as well you would basically need to build all necessary implementations of BOL objects yourself. Therefore it might be better to have a look at the BOPF first which seems to have some more traction in the ERP area. Furthermore, it enables a nice rapid prototyping approach via its WebDynpro integration.
Christian
Yes, thank you, the Genil models ISU* available in IS-U do not look like something worth getting involved with (developed for limited purpose) and according to Note 1772224 are a dead end anyway.
You do realize that the address is a "separate object" in the data model and you are not passing the address guid/key because database selection? Instead a business partner can have more than one address so once again the model is use the key of the address that is related as "primary" with the partner. I really fail to see how these API's are terrible by exposing these keys. If we went down this road for addresses we would end up a whole new address management module per appliction instead of "reuse" with a "thin veneer".
What happens when you want to work with multiple records and not the whole object. From a performance standpoint it would be terrible if we had to have an API model that loads the entire object(when we aren't using it).
The most interesting point about OO vs non-OO API's, is that even after at least 10+ years of ABAP objects we have RFC's and not remote method calls'. It just seems weird that SAP hasn't really provided a good OO replacement to RFC between ABAP stacks. Perhaps that's a question everyone should ask SAP about instead of arguing on which type of API to use. While we are there let's also ask why SAP GUI dynpros are still in use after 11+ years of Netweaver 😉 .
Take care,
Stephen
Hi Stephen,
I realize that addresses are a separate object in the data model. But when working with business partners I don’t care about this. All I’m interested in ad business partner addresses. The point I want to make is that there are better ways to abstract the 1:n relation between business partners and address than passing keys around.
With respect to performance I don’t see why we an API that abstracts certain parts
needs to be worse from a performance point of view. You can still implement lazy loading of certain parts of the data model, buffering etc. As mentioned above IMHO performance is in an SAP context often used as an excuse to work directly on the DB.
RFCs are for me not an OO vs. non-OO topic. RFCs are one the multiple interface technologies (Gateway, Web Service, the ICF, etc) available within the application server. Therefor, the question for me is relay how you implement the RFCs, Web Service or Gateway service. Here I’d always chose an OO based approach.
Christian
The problem is that you don't see RFC's as an issue and only want a data model that suits your particular needs instead of something that has to support multiple applications and be more generic.
If you aren't upset by the fact that SAP never replaced RFC with something else, then you really shouldn't be complaining about any API's delivered by SAP in the first place. Your fundamental issue is caused by the lack of a proper widescale replacement in the kernel level to RFC. Then again since you think eclipse is a modern UI for ABAP, I understand your reasoning. BTW, I personally think think Elcipse and SE80 are the wrong approach from both a technical and business perspective for SAP.
Take care,
Stephen
The point is, we shouldn't care. I program in a lot of different languages, Java, C#, Objective-C and I've worked with a lot of frameworks like Android and Cocoa.
The correct way to get the the address is:
You shouldn't have to know any primary keys. That's the way it works in all other frameworks, and the way it's done in SAP is just archaic. You attack Eclipse because it's not cloud based, I don't understand how you can defend the disastrous SAP API, that doesn't even provide FMs for all objects.
Did you not see my comment about how SAP failed to provide a real OO replacement for the RFC's or is your goal to constantly attack my views?
I did see it, but I fail to see how that correlates in any way to the discussion of good API design.
Okay if you didn't understand how RFC factored into SAP API design, then you are missing a large point and complaining about the wrong issues on SAP Provided API's.
Going back to ancient history/recent history:
- BAPI's or RFC's was SAP's first attempt at public API. They are still the preferred API between ABAP based systems.
- SAP then introduced Jco which provided access to those "RFC's"
- Then OO ABAP was introduced and SAP did not provide an equivalent remote method invocation in the language. Instead SAP went down the whole SOA/ESA route and only provided a limited use of external calls.
- The internal API that connects the entire business suite together(ABAP to ABAP) is still based on RFC and is not object oriented. IE ERP to other components is nothing more than a series of RFC calls.
If you want SAP to provide a proper API then SAP needs to fix the issue of that even that the internal components of the business suite don't use anything more than RFC.
The funny part is the API's being complained about are probably at least 15 years old. My point is that we really should be complaining to SAP about why they never established a common semantic layer for the business suite used internally instead of focusing on very very small problems such as having to fuss with passing in keys to code that was built 15 years ago. However if you really want to complain about minor issues be my guest. While we are at, let's ask why we didn't get ABAP in eclipse in 2004/2005 as they could have done and were trying to do in partial fashion.
Take care,
Stephen
Maybe if I was saying that you can only make a good API using SE24 and classes, but I'm not.
A class is similar to a function group, and a FM are similar to methods, you can have a good API using Function Modules.
Christian's point was that you shouldn't have to know table primary keys, and that is valid both with classes and function modules. It's conceptual, it doesn't depend on the technical implementation.
Minor issues from your point of view. This blog shows I'm far from alone in my "quest".
Couln't agree more with this blog.
The application log example is the clearest one, in fact I'm building my own class abstracting the BAL* function modules complexity and it is a lot of work.
I did this because although several exist, they all are application specific and as such do not cover all needs or have irrelevant functionality (IF_RECA_MESSAGE_LIST is a good example).
With regards to the "lazyness" comment above, I don't think it is a bad thing at all. You get lazy on the standard code and model usage aspects, which enables you to concentrate your efforts on the specific parts of your own application (which in an ideal world would be designed in OO also, integrating with the standard API seamlessly). It is the same kind of laziness you (hopefully) apply when designing your own utility classes or methods and then reuse them multiple times.
While I couldn't agree more with the API part, bringing up OOP makes my eyes roll again ("ugh, those Java people can't live without their precious objects, boohoo" 🙂 ). This is the whole different subject, although I do understand that when you start on "dear SAP" path it's very hard to stop. 🙂
You're spot on with lack of APIs though. Personally I would just settle for the APIs that work, but even that seems to be luxury in some cases (shameless plug for my blog). Or the parameters are so counter-intuitive (and undocumented) that using such API/function requires sacred knowledge and a secret handshake. Like others, I do hope SAP gets this message. Although if they've ever bothered to patrol SCN they would've already found dozens of opportunities where an API is clearly needed by many customers.
Just to clarify - from what I've seen, the forum inquiries on the table fields are usually coming from the query/reporting requirements. In a report it could be just inefficient to call an API/method/whatever for every single customer, for example, when the report needs to display hundreds of records.
Jelena, with regards to efficiency, I think I understand what you mean because I strugled with the concept at first tries to grasp OO.
You can have the class "CUSTOMER" have a static method SEARCH, which based on range parameters, returns a list (internal table) of instances. Internally, this method could read KNA1 massively once, then loop results and create one instance per KNA1 record.
Then, when from your report you call R_CUSTOMER->GET_NAME, it is NOT doing a SELECT SINGLE, but merely returning the NAME1 field stored in a global attribute. That's the beauty of it, you can later define a different source of customer names, without touching any of your reports, because the table access is encapsulated. Granted, you can achieve something similar with function modules, but you wouldn't have a handle to each customer as you have with objects.
Alejandro,
The main problem is in most cases your query criteria aren't based on simple object/table, but on much complex one.
e.g.
Select all sales orders whose customer's attribute X is equal to Z.
In such cases, usage of existing API/classes isn't efficient (As it doesn't/cannot cover all the existing relations between different business objects).
Shai, of course it can get tricky. You could then have a query class which accesses those different tables and returns the corresponding objects.
My point was just to show that not necessarily 1 method call equals 1 select, because I got that impression from the comments.
Anyway, there's often a trade off between performance and code readability / maintainability.
Hi Jelena,
Not working APIs are really the worst. Some of the BOL abstractions for SAP IS-U in SAP CRM are that way. They only seem to work for exactly one use they were developed for.
I did not have any examples for obscure parameters in my little code examples. But I agree that they are one reason the APIs are hard to use. Such parameters and missing documentation lead from my experience to the following development process. First, developers search for a function module or method, then they execute the “where used” function in SE80 / AiE. Next they search in the result for some SAP standard code that seems to do the same or a similar thing to what they want to implement. Finally the code is copy and pasted, tweaked and debugged until it works.
With regards to efficiency I have a different opinion. Performance is in my opinion just an excuse for not using an API and using the “simpler” direct selects instead. For me it is a form of premature optimization (http://c2.com/cgi/wiki?PrematureOptimization). Most of the SAP APIs I have seen implement some kind of buffering. Using them will in most cases result in better performance than coding direct select (at least for everything no trivial). Skipping the API and working directly on the DB should be the last resort if everything else fails and performance becomes an issue.
Christian
This is such an important message to get to SAP and well done for taking it head on The specified item was not found.
I agree partially with the blog, but IMO a real usable solution to improve development would be to think an abstraction level higher.
Think of creating a development UI which can 'connect' directly to the existing business transaction which needs to be extended. Also usable to find out where the presented data originates from (which is not always obvious anymore).
This development UI could present the developer with an overview of extensions which could be implemented on this certain business transaction.
Including all customizing posibilities which could make development not necessary when it turns out it can be customized by standard means.
When development efforts would be guided from the environment one wants to make changes to, then APIs are not that important anymore...
Improving the development UI would be a more solid solution for the future then, IMHO, arguing about how the readability of code could be improved.
And yes, SAP has lots of pollution in their code base because object oriented thinking has never been the core philosofy in the past.
But their ABAP help and websites improved gigantic the past few years. I am convinced SAP will improve the maintenance of their software because this is something they have to achieve
to stay competitive.