Day 27: Design Resilient Interfaces
Interface design is at the heart of software engineering. While it takes a good program to implement an algorithm, it takes a top programmer to design clean interfaces that will make software development easier, not harder, as time goes.
First let consider our definition of resilient interface. In a few words, an interface is resilient if it can resist the test of time. In any project, as development progresses, a number of concepts will change and need to be reevaluated. This reevaluation will involve the needs and wants of users, managers, as well as the personal preferences of software developers. A resilient interface will help the development of these new features, instead of becoming a hindrance in the process.
Resilience in Web Software
For example, a good interface for a web system will provide the basis for future growth of the site, as new services and interfaces are added. In such a design, it is expected that data will be accessed in a uniform way. Data manipulated and stored by the service will also be, whenever possible, independent of how it is acquired. Observing these guidelines will, overtime, provide simple interfaces for the access and manipulation of data, and will result in a reduction in maintenance efforts.
On the other hand, an inappropriate software interface for a web service would difficult future expansion. For a concrete example, this could involve the tendency to tie particular data attributes to the way it is accessed. In that case, if the data access changes, then this kind of interface will become an obstacle that needs to be circumvented by future developers.
Core Qualities of Software Design
Good interfaces are about the essential qualities of the software. Rather than trying to capture simple details, the objective becomes to understand the core of a computational problem. But designing interfaces is not only about understanding the present requirements. It also involves the experience of understanding the inevitable changes in requirements over time.
That is why it is so difficult to create resilient interfaces for a completely new service: if you see a particular problem for the first time, it is hard to anticipate all the issues that will need to be addressed in the future. Therefore, it also becomes increasingly hard to anticipate the necessary flex points that can make that expansion possible.
Experience becomes a fundamental skill in determining those areas of the product that will require revision. The same design experience is also vital to avoid gratuitous generality, which can effectively impose a performance penalty on the software.
I have encountered many examples of poor design, and they frequently involve solving a simple problem with an algorithm that is more general than necessary. While one can sell such an strategy based on the perceived future “flexibility”, it doesn’t make sense to live with features that will never be used. The cost of applying an over-engineered solution will most certainly become a heavy toll to developers.
For example, I have seen frameworks that provide event-based capabilities that are useful, but hardly necessary for a database-driven application. The result was that maintenance costs became almost prohibitive, and the possibility of introducing bugs were much higher than necessary.
Adding flex points to a software design should be done with care and full understanding of the possible directions for a product. Creating complex interfaces just for the sake of it can be a fatal decision for the future of a project.
Designing software interfaces is an activity that has an impact much higher than just implementing code. The implementation of a feature or a complete product may take a few weeks or months. But the design used will dictate the direction of the product for years to come.
A balanced design needs to take into consideration the needs of the product and the organization behind it. It should be possible to add features to the existing implementation, but we should also avoid the onerous maintenance of unused features and options.
Resilient interfaces, therefore, don’t appear as an individual, one-time effort. It is more commonly the result of experience with several designs, which contemplate deep understanding of the domain area and the programming language used in the implementation.
About the Author
Carlos Oliveira holds a PhD in Systems Engineering and Optimization from University of Florida. He works as a software engineer, with more than 10 years of experience in developing high performance, commercial and scientific applications in C++, Java, and Objective-C. His most Recent Book is Practical C++ Financial Programming.