Applying Object-Oriented Programming Principles to APIs / Integration
To give you some context, I started as a C and Assembly language programmer and then moved to Object-Oriented Programming using C++. As with any change, initially after moving to OOP, I felt my freedom was taken away but slowly and steadily I realized the power that OO concepts can bring in.
After about 5 years of programming fun, I got introduced to the world of integration. It was so easy to learn and, during the first few months, I felt my skills were underutilized. But I feel my knowledge of OO programming principles has helped me in building a strong integration career.
Here, I will try to map those concepts to explain how those principles could be applied to the realm of integration or APIs.
Encapsulation and Abstraction
Encapsulation relates to protecting data and behavior to avoid misuse by the clients. Abstraction relates to hiding the details and exposing only the things that matter to the callers.
In the world of integration or APIs, we do not have to expose entire logic back to the consumers. E.g., let’s say you have to create an API for accepting web orders. For creating order, we first need to check if there is enough stock in inventory and then after successfully accepting the order, the stock in inventory needs to be reduced.
It would be a bad idea to expect the consumers to do it for you. The logic for checking and reducing inventory should be private to the Create Order API.
Now, you can have Check Inventory and Reduce Inventory as different APIs altogether but as far as Create Order is concerned, it should only be expecting the consumers to submit details of an order and nothing other than that!
Polymorphism allows us to redefine the way something works depending on either the way the method is called — (overloading) or by changing the implementation of the method itself (overriding).
In the world of integration, you will often have a requirement to route requests based on an input parameter you get in the incoming payload.
Instead of doing an “if-else if-else” sort of construct in your implementation, a better approach will be to have a dynamic call to a sub-flow or sub-process. Most integration solutions allow that.
Having such dynamic calls provides 2 key benefits:
a) Code Readability: The Main flow will be much simpler to read, understand, and maintain.
b) Extendability: If in future more routes are added, it will just be a matter of adding sub-flow.
Although most integration tools do not allow to “inherit” code, the key benefit behind having inheritance is Reusability. Being an integration developer/designer you should be lazy. Being lazy would teach you to create reusable libraries for code that you will never have to rewrite.
Reusability could be achieved either by creating a separate API or by extracting common pieces of code into a reusable library of some sort that can be reused across projects.
With reusability also think about how you are going to maintain versions of this API or library and how will it impact existing projects. Such reusable APIs or libraries should mostly be backward compatible.