Monday, 15 June 2015

Can Adding an API Save Your System?

Creating an api as a publicly accessible interface to your system can actually make your system better than it currently is!

A bold claim I know, but bear with me and I will try to justify this claim. Lets begin by imagining a large system which has evolved over time into something your customers like. It fits the purpose, it earns you money, it continues to grow and evolve. All sounds well. Now look behind the curtain, in the box, under the surface. Those little duck legs are paddling like mad just to keep the serene appearance on the surface. Your system has evolved into something if a mess beneath the surface. You're not at fault, its a fact of any software systems that over time commercial pressures mean that technical debt accrues and the system architecture is corrupted into a mess. Often UI and business logic boundaries are blurred, code duplication becomes rife, maintainability is generally reduced.



A nice clean architecture would have clear separation between the layers of the system in terms of the responsibilities, but more importantly in terms of the code base.  In reality many systems blur these boundaries over time and code that should be in a business layer may be forced into the UI layer by time and commercial pressures.  For a system with one UI this does not surface as a problem, but consider adding a second UI, quickly the business rules that you think are robust and well tested are being violated.  How come? Well they were implemented in the previously sole UI, but are now being bypassed by the new UI.  This highlights the build up of technical debt that putting the code in the wrong place causes.  But as I say, you could live with this happily for years unless you introduce a new UI.

In a clean system the abstraction between layers should be such that any layer could be replaced an the system still function.  If there is an overlap in responsibilities between layers this is not so straightforward.

Given the evolution of the technological landscape to a much more mobile, flexible one, with the desire to access everything from everywhere, there is an obvious drive towards supporting multiple interfaces to a system to accommodate this.  Take a system that was written for a standard office of the past.  It may have a big thick client with maybe just a shared database behind, or a thickish client with a server side engine that does the grunt work and a central database.  To evolve either of these systems a web front end may be produced utilizing the same data.  Where a server side engine existed this may be reused for consistency of functionality and minimal effort to create the new UI.  If however any of the business logic existed in the client this will need to be replicated in the new web service.  If we extend further and add mobile applications the logic will need to be placed in these too.  And what about integrations with third party systems?  Where does the logic sit there?  We need to contain all the logic in a common business layer, just as our clean system architecture planned.

This is a problem I have seen many times over the years, and often when creating this one new UI the decision was taken to do the 'easy' thing at the time and duplicate the logic.  Often this resulted in the logic being implemented inconsistently in the new UI.  And worse, any bug found in either flavour of the system would only be fixed in that one flavour.

Recently I have been working on the addition of a rich RESTful API for a mature system, and where we find a hole in the business logic due to the API bypassing all UI layers the decision has been taken to do the right thing.  Move the business logic into the business logic layer so all UIs have the same logic implemented by the common layer below.

All this sounds like a lot of bad coding has happened in the past, and that bad decisions have been made as to where to put code logic.  But this is not the case in reality.  Image a form in a system that allows you to enter data.  A numeric field is entered, and the form restricts the format of the data.  E.g. non negative, with enforced bounds and precision.  The business layer of the system may well be the place that all the data validation is being performed, but what if some of the boundary conditions that should be guarded against are missed when writing this validation code?  No-one made the decision to miss this validation.  The testers thought of the boundary cases and tested them.  The system held up robustly as the UI did not allow the user to enter the invalid data.  But if the UI had not enforced these restriction then the invalid data may have gotten through.  There was no way to test this.  We thought the system was robust, and it was, but only via the single UI that was available to the testers to explore/exploit the system.

If in the scenario of the ever evolving technological landscape above we add a second UI, for whatever reason these restrictions may not be possible and the system becomes just that bit more fragile.

With an API, we can decide to implement no restrictions (other than type) on the data input and thus force the (common) business layer to take the responsibility for all the data validation.

The decision made to do this on the system I am currently writing the API for means that the API will be a little slower to produce, but more importantly the overall system will end up in a much better state of technical health.  And the biggest benefit from this is that if a new UI is needed in the future that maybe does not even use the API but communicates directly with the business layer, we can be confident that the logic will be intact and robust.

So the addition of an API will not directly save your system, but can give you confidence that the system is fit and healthy enough to evolve further into a rapidly changing world that may put ever more challenging requirements on the core of the system.

No comments:

Post a Comment