API-Centric Development
As a software developer, I have often expressed my indebtedness to those who have gone before me. Some of these were “giants” whose shoulders I have stood upon. Others were selfless “guides” who patiently navigated me around complicated roadblocks. In addition to the technical knowledge I obtained, this has impressed upon me other valuable experiences, two of which stand out more than others. First among these is the joy of paying it forward. Not just giving back, but giving unto those who will come after me. The second of these is the humility of realizing that I am never quite as clever as I might like to think. Whatever technique, skill, or novel solution I might come up with, someone else has already done it…probably years before it ever germinated in my head.
The MultiValue community is filled with several such seasoned and insightful people. The more well-rounded members have rightly identified many emerging software innovations as simply new labels for concepts that we have enjoyed for decades. A rather notable example would be the growing popularity of NoSQL databases. Their many advantages and can easily be applied to MultiValue. Hence, in an ironic twist, MultiValue databases – who long predate the term NoSQL – are listed among the NoSQL options (a fact that all MultiValue salesmen should take advantage of…). This is just one of many examples where MultiValue technology in general, and specifically Revelation Software products, can take advantage of modern trends and articulate how we have already been doing that for quite some time.
API-Centric Development
This brings me to the main topic I wish to discuss in this article: API-Centric Development. For the sake of clarity I will define what this means. Obviously, API is an acronym for Application Programming Interface. The term implies that our application has an interface, a published and documented method by which external systems can use it. In the most basic sense, a simple function is a type of API. One simply needs to know the correct arguments to pass in. Lately, API conversations have focused upon web applications. Google, among others, have helped to transform the web by making it easy to access their web services via APIs. An API-centric approach is one where the developer seeks to build an application upon a foundation of APIs, wherever this is reasonable and has purpose. API-centric development is forward thinking, as it looks to expose valuable logic in a way that is modular, reusable, and decoupled.
This is by no means a new or novel concept. I would even hasten to note that many features of an API-centric approach have long been employed by MultiValue developers. Yet, after years of working alongside dozens of developers and working within hundreds of applications, I continue to witness a tendency toward monolithic and top-down designs. It seems rather obvious why this is so. Most of us, and our applications, have legacy roots. Traditional MultiValue applications have the advantage (or disadvantage, as I’ll argue shortly) of running front-end and back-end systems in the same memory space. This is true for legacy applications that run in a terminal emulator as well as modern GUI applications such as OpenInsight. We have grown accustomed to the convenience of having all of our code, from the UI to the database, work within the same process. I refer to this as coupled software.
Coupled Software is Crippled Software
Yet, as the saying goes, “if it ain’t broke, don’t fix it.” My experiences have shown me that this methodology is broke and it needs fixing. The first time I struggled with this was during my first Advanced Revelation to OpenInsight conversion project. I recall my early optimism that this would be relatively easy. I expected a fair amount of work converting character based forms to GUI forms (although there were some who even wrote utilities to automate this). Code conversion, on the other hand, was expected to be much easier. After all, BASIC+ is an extension of R/BASIC. 90% of the language is exactly the same. Yet, that proved of little value when so many stored procedures were riddled with calls to AREV-specific interfaces or DOS commands. Virtually every routine required some degree of intervention before it could be used in OpenInsight. Certainly we adopted techniques to minimize our burden, but this was merely a band-aid to what I perceived was the real problem. While I did not articulate my thoughts quite so well in those days, nevertheless, I had come to the conclusion that coupled software is crippled software.
Too often I have observed many well-respected commercial software applications, written in Advanced Revelation, languish to the point of virtual extinction because the decision to convert to OpenInsight was long-delayed. In almost every case I have been involved with, this delay was due to the challenges of a coupled design. UI logic, business logic, and database logic were all co-mingled. Many of these applications are quite large and complex, which only made the conversion task that much harder. Yet, those that were converted were done so in haste (often because too much time had passed and customers were already moving on to other products), and a so-called path of least resistance (translation: direct port of the UI and code) was taken. Hence, the coupled (or co-mingled) design approach was transferred from Advanced Revelation into OpenInsight.
Those Who Cannot Remember the Past are Condemned to Repeat It
We have all heard this expression, perhaps written in various ways. How well this has proven true in the above discussion. It seems that many developers had forgotten the pain of converting applications so tightly bound together. Consequently, the next round of conversions – going from GUI to Web (or Mobile) – proved to be even more challenging. Why is that? Well, in addition to needing to learn new technology and a new paradigm, the underlying code cannot be converted in the same manner as before. Business logic and direct calls to the database which are wrapped inside commuter modules simply cannot work in a web application environment. Developers who want to extend their solutions into the cloud this way are faced with having to re-engineer their code. Web apps, by design, require a true client-server architecture. This approach is largely foreign to MultiValue developers.
This time, however, there are no shortcuts. Business logic must now be decoupled, free of UI constraints. Developers should avoid the temptation to simply write a new code for the web while leaving the old co-mingled code intact, but it will happen. It has happened. That is a shame. Nothing will kill the integrity of mission critical applications than multiple instances of the same business logic with very little control that will ensure changes to one instance will automatically be applied to the other.
APIs Aren’t Just for Web Applications
I was moved to write this very article because I just finished working on a project wherein all of the above pitfalls had existed and were resurfacing as I was being asked to extend the application’s core business rules. The application itself is a complex and specialized accounting software package. It originated as an Advanced Revelation application and has passed through many hands. While it currently operates in the cloud as a hosted published application, we have been asked to enhance the underlying accounting formulas and make them accessible to data entry forms, export files, reports, and eventually web services.
This is all well and good, except that much of the logic was designed to serve a single data-bound form. Hence, many of the critical formulas were embedded in the event handler logic or buried in symbolic fields. The logic was hidden away, unable to be extended.
I informed the client that we simply had no way to maintain the current design of the application and accomplish these new and long term goals. I was given permission to restructure the business layer. Fortunately, SRP has a standard template for wrapping up business logic and converting them into application services. Effectively, these services are APIs into the core business processes of the application. Since we follow a consistent structure, the APIs are also uniform, making it easy to identify and call any API within the application. This approach allows even the most complex applications to have business logic that is transparent and discoverable.
Forward Thinking
Our client’s investment to translate some of his critical business processes into API-centric code has already succeeded beyond the original intentions. I was asked to modify several accounting formulas, each one following unique rules depending upon the values of various fields in the database record. One important design requirement for an API (or application service) is that it operates completely based on inputs. Thus, I was able to quickly test each API by directly calling it from a test routine. This proved to work well, but I was convinced it could be more efficient.
To improve my testing, I created a very simple form that emulated Excel style data entry. Each row represented a data field. One column displayed the field names and the other column provided cells for data entry or formula results. Again, because the core logic is now wrapped in an API, it was very easy to have the event handler of the form make calls into the relevant application services and return the value. This new tool now makes it very easy to change key values and instantly observe how the formulas respond. I could also use the new APIs for unit testing.
This led to another benefit of modular software design: layering. Given that this is a complex accounting software application, many of the formulas rely upon other formulas. Therefore, many of the APIs were designed to call other APIs, thus maintaining the critical objective of having one place where core business logic is maintained. If that logic needs to be revised, it automatically propagates to all dependent APIs.
Nothing New Under the Sun
As expressed at the beginning of my article, I am not proposing anything revolutionary or exceptionally clever. However, I am sharing from my many years of experience and hoping it will profit many who care to read my words. Consider the above accomplishments. Now that these accounting processes are properly decoupled, they can be extended even further. The client can pursue mobile application development, unfeasible before due to co-mingled code.
The moral of the story is this: Decoupled code extends the life, flexibility, and extensibility of an application. I strongly encourage you to consider an API-centric approach to any project, no matter how small. You will be rewarded for the effort.
Great article Don, thanks for sharing. I totally agree!