Wednesday, September 15, 2004

Architecting to prevent API drift

The goal of every well architected application is to lower the total cost of ownership of code by reducing the time and effort that goes into the implementation, testing and maintenance of code. A powerful idea towards this end, is the use of interfaces.

Intefaces as defined by the Merriam Webster dictionary are the points "at which independent and often unrelated systems meet and act on or communicate with each other ". By clearly defining these interfaces, the application architect forms a well-known and easily referenceable contract or specification that defines how two or more software systems will interact with each other. The crisper the specification, the better the interface. To utilize the logic encapsulated within an application, the end or intermediate-user of the application must utilize the interface exposed. Thus a programmer wanting to use, for example, a MS Office application will need to write code that utilizes the interfaces of that program. These interfaces are also referred to as Application Programming Interfaces of APIs.

However, APIs like everything esle are prone to the pressures of changing business requirements and technologies. These forces, exert a slow but gradually building pressure to change the API. For example, over a period of time the assumptions, behind an API choice may be lost or obscured. As a consequence when, changes need to be made, the original pattern may not be adhered to in spirit. As changes are added into the application via extensions, refactoring or module replacement this drift gets progressively larger to the point where the original API becomes restrictive or counter-productive.

In another scenario, an interface may be designed to reduce the exposure of a new application to legacy applications (facade). For example, an e-commerce application may need to utilize data stored on a mainframe via a COBOL application. The facade has well defined types that represent or correspond to data types on the legacy end. Thus a integer type may be used to hold an numeric code that consists of 4 characters. However, with time a 4 digit code may no longer be adequate to represent all the possiblities. In that event an alphanumeric code may be adopted by the business. This alphanumeric code will however, not be supported by the integer type. The architect is now left in an unenviable position of changing the API.

In an engagement, involving a major corporation acquiring a smaller competitor and needing to unify its inventory tags. A three digit code did not suffice to represent all the possible combinations. The need to differentiate inventory items between the two firms necessitated the use of a much larger set of codes that the minimal possible.

A number of steps can be taken to mitigate this pressure. These fall into two broad categories:
1) Design with change in mind
2) Ensure that the assumptions behind the architecture are well known and the bueprints readily available.

Each of these steps may not by themselves provide a silver bullet, but then architecting a robust application is as much an art as a science. Considerable skill and judgement must be applied in making trade-offs between antagonistic criteria. However, in the long run, the pay-off is worth, many times over, the time and effort put into the endeavor.


(c) 2004 Vivek Pinto For more details please visit us at Wonomi Technologies