SOUI : Service Oriented User Interfaces
My story begins with a heap of user data, and a hard working team of engineers spending valuable time finding it all, and putting it together. In our business, several teams need to report to all sorts of third parties, about the data we collect and use. It’s vital to our business.
The problem is that we haven’t been able to quickly add new fields to make sure all the data is saved to one canonical place. Engineers are spending some nights and weekends hunting errant data, and then putting that data into a database.
Four weeks ago, we decided to start groundwork on a new data collection framework, where we could quickly add new fields to a user interface, and collect the associated data, with little engineering effort.
Two Degrees of Freedom
I guess the conventional way to design user interfaces is to place a web server in front of some APIs and then call it a day. Like so:
That is a common way, and is often “good enough”; but I don’t think it is. That approach only gives two degrees of freedom to the engineers leveraging that user interface (UI engineers and application engineers). One can change the user interface, and Another can change the APIs; but they are forever tightly coupled, and this has serious affects.
Most changes to the APIs will affect the User Interface (UI). The UI depends directly on the APIs. So, the engineers are faced with a dilemma: either work in lock step; or require an APIs per consumer; or version the API and support multiple versions; or add a layer in their code that handles changes to the APIs gracefully. There is another option: making UI self-reliant. A third degree of freedom can be obtained by providing an abstraction between the User Interface code and everything else.
Three Degrees of Freedom
I am proposing to add an additional degree of freedom, by adding an extra abstraction. This will have the effect of making changes to the User Interface cleanly separated from the APIs.
Rather than just add another layer between the APIs and User Interface, I had the idea to make the API a first class citizen of the SOA world. The user interface shall have it’s own API.
The freedom comes in the form of a contract. No longer is the UI a slave to the whims of the API, it is now an independent service, with it’s own contract and it’s own rules. This has the power of freeing up UI developers to develop new features in parallel to API developers.
I intuitively like how the UI API is now a first class citizen, not beholden to the the DB APIs, and also how the User Interface’s relationship to the UI API itself is on par with the DB APIs relationship to the DB. It feels “fair” to me. Otherwise it’s always a struggle of who controls the content and format of the API!
Benefits of First Class UI Services
There are a few benefits that come from truly separating user interface concerns from all other concerns. These include: fully testable; focused; independently deployed; composed; declarative; and the freedom to design better ways of interacting with user interfaces. Most of all, the benefit is freedom. Making an independent service for user interfaces free UI developers to make independent decisions.
Fully Testable Code is Higher Quality Code
With clearly defined interfaces in place for our UI API, we can declaratively provide a plethora of inputs. UI Engineers can generate a suite of tests to ensure their interfaces work in all expected conditions: e.g. long text blobs in a caption; erratic user input; code injection; etc…
On the other hand, consumers of the UI API can write tests around whether the proper UI is request (rather than produced.) It’s a clean separation of concerns. You can see the result.
Below is example code I created to render a random number of checkboxes.
The UI API developers can use their own Mock Controller to interact with their UI Service to build & test different UI test layouts of components. The saveUrl in the example code will be called when an end-user clicks a “save” button. The UI developers can write a very clean test that makes sure that a provided URL receives a POST with the appropriate data, when an end-user clicks “save”. All this testing ensures developers can deliver a consistent and reliable customer experience.