Modular Design and OOP – How bad do you want it?
This blog is a bit different from the more technical ones because it is essentially describes a “what if” scenario, which I don’t think will ever be implemented. Regardless, I believe the idea is interesting enough to “put to paper” and discuss.
It comes in the sequence of all the blog posts surrounding Unit Testing, including my own, where we discuss modular design as a requirement for unit tests, and good code in general. We also come to the conclusion that most people don’t do it, and it’s hard to force change. Force is the key idea, what if you, as a SAP manager, really wanted to force your team to do it?
My crazy pitch? Make some of your developers use a Developer Edition without SAP_APPL or any other functional modules. Read along if you’re intrigued.
A pratical example
This week I’ve been analysing some developments around EWM and Fiori (for warehouse operations) and was faced with three situations:
- Not being able to take advantage of a Fiori suite for warehouse operations designed for WM (not EWM) when the business processes are the same;
- Seing a Gateway service that directly calls a EWM Function module;
- Not being able to access the Fiori instance because it was not connected to the corporate VPN. I had to create tests on my local “Docked” ABAP AS and Cloud Platform Web IDE. (Thanks a lot Nabi Zamani ).
I looked at the existing code and in general it is good code (especially on the Fiori side) but there was no focus on reusability as the Fiori/Gateway was completely hardwired to EWM. If I ever wanted to use this with normal WM I would have to rewrite everything,
Gateway and modular design
I know Gateway gives you some model generation tools where you can use ABAP dictionary structures and function modules do create entities and entity sets. Don’t. Don’t use them if you want to have the slightest chance of having a modular design.
- Your data model will be tied to the specific module, including data elements;
- The model is designed around how that particular module works, instead of the business requirements.
- It kills modular design as what should be your repository layer (API calls) is tied to the frontend.
Call me old fashioned but I like to write my own OData services code, and it helps in the shift to OData v4 (and trust me you’ll want to shift to V4 when SAPUI5 is completely compatible).
So what happens when you have a Developer Edition without SAP_APPL or EWM? You can’t use the Function Modules or the Data Elements (Win!). I used “Strings” and general objects like collections and hash maps, so nothing is tied to a particular functional module like EWM.
Repository Layer as Plugins and Unit Tests
The second impact of having no EWM on my machine, is that I can’t create the repository layer. No databases to call, no EWM BAPIs. So what does this force me to do? Use an Interface to abstract all my API/DB calls and create a mock class so I can run the code.
This mock class needs to create test data of course, which I can reuse for my unit tests. By forcing myself to have a separated class for all the DB/API code, I made the code testable.
In this model, you can think of the repository layer as a plugin. As I abstracted the business logic on the interface level, I can then write a repository class for EWM and another for WM (this plugin can only be developed in an instance with EWM/WM).
Tie this to ABAPGit, where you have a repository for the generic app, and others for the plugins, and you have a highly scalable development landscape.
Fiori, Cloud Platform and MockServer
On the Fiori (frontend) front this means you’ll easily separate what is your business model from EWM which will speed up your process. You can even have a Fiori/Gateway guy doing your business logic, and more traditional ABAPers creating the plugins. Even if you want to use the backend server, you have test data supplied by your mock.
Fiori/Gateway teams can interact faster with the business users using SAP Web IDE mocking server to quickly iterate without the constant need for a EWM (insert other module) consultant.
In terms of Cloud Platform, do I think it is critical? I’m on the fence on that one. On one hand it does speed up the process, and if you are using Cloud Platform Portals the integration with the Fiori Launchpad is great. If you’re not using Portals, SAP Web IDE will nevertheless speed up the process because of the Gateway automatic mocking and metadata synching (this is important for quick iteration).
The downside
Of course this has downsides (which is why nobody actually does it). I can think of several:
- Keeping your developer machines updated;
- Still no HANA on the developer ABAP AS;
- Having a large enough team to split your developers into two groups;
- Having a budget that makes it worth the modularisation.
- Changing developer mindset.
- You can do all this with code guidelines and code review and force this without all the extra work.
The last one is the most important. Most companies have ridiculous coding guidelines like the one that forces you to use ZCL_ to name a class when it’s redundant, but have no guidelines in place for actual coding practices. It’s a lot simpler then going through all this trouble just to have modular code.
As a last comment, one that my Development Lead may read, the EWM “plugin” still needs to be written by “someone”. 🙂 Truly modular design at work.
Interesting read. Never used function modules do create entities and entity sets. But I can' say you've convinced me to stop using ABAP dictionary structures for the creation. By using the same structures as exporting/returning parameters in whatever form of modularisation is used, you're sure everything is and remains in sync. And especially when you correct the standard generated code for $expand, that becomes even more important.
As far as the modularisation, there you can do all you want I guess. But I've recently seen a complete framework with a huge amount of classes, where a bunch of data is read and put into a class model, only to read that same data from the instances immediately after and pass it back to the frontend). So yes, a lot of opportunities for re-use. But not so sure that it's an improvement performance wise.. or will aid in the maintenance..
It all depends I guess..
Thanks for the feedback. In terms of the "business layer" in my example I do have a lot of what you would call passthrough code. I just gets the code from Gateway, sends to repository, and then gets the repository output and passes it back to Gateway..... for now.
I have for example a method that is called "optimize_route" that currently does nothing and just returns the input, but in the future I could implement additional rules there. Unlike my "Freedom" blog where I did have a ton of non-DB dependent logic, here I don't at the moment, so it's more of a leap of faith, I invested time into future maintenance.
That's the main problem with modularisation, when someone is developing is seems like a waste of time. The Fiori/Gateway app I discuss at the beginning worked just fine.
Hey Joao,
in the buildup, when you write about forcing change on developers, I thought you aim for something like: un-install (or block in some way) SapGui entirely -> Coding then has to be done using AdT / Eclipse.
But I like your idea
just as much!
best
Joachim
I'm conflicted (does exist as word?) about the extreme modularization, to be honest.
Keep stuff separated? Sure.
Keep the code clean and optimized? You can bet on it!
But as Patrick van Nierop hinted, the excessive modularization leads to Java style: respect all the theoric rules and then you end up crying when you have to adapt the code.
I'm also struggling into accepting to keep a "general class for multiple services": honestly, i do not know if it's the best approach.
I say so because i developed 4 OData Services for 4 different applications requiring to access Work Orders data.
And each of them is quite different from the others to optimize the data selection and to avoid to retrieve a lot (or not enough) informations.
I repeat myself, i'm not sure which is the best approach and it's a lot of time i'm on the fence, dancing on it and evaluating both the options.
Criticisms have been given, so, now, i want to thank you for the good blog: even if i'm a bit skeptical on the practical side, it gives a lot of good points to think about!
First let me thank you for the feedback.
In the example there is a focus on separation between layers: Gateway, Services, Repository. I didn't defend the usage of one OData service or many, what I said was important was the decoupling of Gateway from the API, so that I can change functional modules without rewriting the frontend.
With the decoupled logic, you can handle gateway filters in order to select different queries on the services layer, but it's probably easier and cleaner to have odata services. The point of having a generic odata service is when you are creating one with no specific focus on an app. You create it to share information with sources you may not even know about.
For example in my non-SAP life, I have this situation where we have to access a Oracle DB from the cloud so we need to make view available via HTTP. We don't know the queries we will want to make on this view, so we either develop specific services for each additional query that comes along, or we develop an odata layer on top of it. But that's because we don't know which queries may come up.
Regarding too excessive modularisation, I think in general modularization leads to better maintenance, there may be exceptions of course.
Thanks a lot for the reply.
As i said, i do not know what's better and i think that, apart the general concepts of modularization, each case is pretty alone and unique.
How often do you need a generic service like your Oracle view over a more specific one?
Since you are going to develop something on the top of it, you are still specializing it so...
Well, i do not want to push my point of view at all, just speaking to myself to find a better approach to the issue for my developments.
For this, again, thanks for the blog!
In terms of the Oracle, the architect from the customer side doesn’t want to have to develop a soap service for everything, she wants to have something that can support several queries that she can’t antecipate.
It is an architecture decision which I can understand.