Clean up reusable software's API
Writing firmware that can be reused requires creation of a clean Application Program Interface (API). The API needs to be well thought out so that it makes re-use easy and productive. Ideally, the API should possess at least these six characteristics.
Characteristic #1 – Be obvious and easy to understand -- As with any piece of software that will be reused from one application to the next, an API should be simple, obvious, and easy to understand. And to remember! Using an existing component or library can be extremely annoying when the API is inconsistent and uses seemingly random syntax. You don't want a user to be constantly looking through documentation in order to find the right call or operation.
Characteristic #2 – Be extendable -- Technology changes at a staggering pace and sometimes those changes require additions or modifications to an API. An API should therefore be developed in such a way that it is easily extendable to encompass new features without having to rewrite the API from scratch or perform a drastic overhaul. The ability of the API to add new functionality while maintaining consistency to previous versions is a key factor that will help determine its long-term survivability.
Characteristic #3 – Have high cohesion -- Cohesion refers to the degree in which the elements of a module, or in this case the API, belong together. An example of low cohesion would be lumping all of a microcontrollers peripheral functions into a single interface. The interface would be large and unwieldy. The microcontroller peripheral functions could instead be broken up into separate modules, each with API functions specific to an individual peripheral, to increase cohesion.
Characteristic #4 – Make use of abstract data types -- A good API will be used on more than one system, platform, and MCU. The implementation details may need to be slightly different between the systems but the interface needs to remain consistent. The use of abstract data types can help separate the use of data from the implementation details and help make the interface more portable.
Characteristic #5 – Use encapsulation and data hiding -- A good API should follow best practices for object-oriented software, even if the software is written in C. Any variables that the API will manipulate should NOT be global. Instead, perform access to critical data through get and set helper functions. An API should also expose as little as possible to the external world, i.e., only what the API user needs to know. Essentially, an API should provide its functionality in a black box fashion. The user doesn’t need to know the API's implementation details, only pre- and post conditions for using the interface.
Characteristic #6 – Follow the principle "Less is more" -- The best APIs are capable of providing critical system functionality while doing so through a few simple interfaces. Developers can be tempted at times to expose every possible function of a peripheral, chip, or application library through the API. They instead should carefully think through the API and minimize how many features it exposes. Many complex and unwieldy APIs can be refactored into simpler interfaces that users will find more manageable.
API’s are critical to the development of reusable software and the proper design of an API can ensure it's useful for years to come. What other characteristics should a good API have?
Jacob Beningo is principal consultant at Beningo Engineering, an embedded software consulting company. Jacob has experience developing, reviewing and critiquing drivers, frameworks and application code for companies requiring robust and scalable firmware. Jacob is actively involved in improving the general understanding of embedded software development through workshops, webinars and blogging. Feel free to contact him at firstname.lastname@example.org, at his website www.beningo.com, and sign-up for his monthly Embedded Bytes Newsletter here.