How we sped up delivery, improved reliability and eased our processes in one fell swoop. A Back End & Front End romance story.
I take an approach of “how can this be easier/better” with my engineering, architecture and strategy work, this is the story of how we simplified and improved one of the most tedious parts of Back End (BE) to Front End (FE) relationships, whilst making the whole thing quicker, easier and in general, better. It comes down to one word: Contracts.
I like the above photo, a lot: it was a phenomenal feat of engineering; two teams drilling under the Channel Tunnel and meeting precisely in the middle. Thankfully software engineering is a little simpler than that.
However, when building Front End applications that rely on APIs et al, engineers can often find themselves starting from an unknown place, even with some pre-alignment and planning. The aim was to resolve these problems and others, and this is how we did that, and some additional positives that came about also.
Does this sound familiar? A project is started, and the BE team work on their API endpoint. They finish their version, send the endpoint to the FE team and the FE team run it, using the response to build their code.
This is a fairly common occurrence and means that the teams work synchronously, probably with some (if not, a lot) of back and forth as the project goes on. This leads to many problems and blockages, such as waiting on BE to provide mock objects in order to build out FE features, not necessarily knowing what will be optional or not, and various other problems that you’ve probably experienced with this approach.
I have used this approach as recently as the last year, and in many companies, the techniques we use now took a while to arrive at. Initially, persuading the various teams to change their approaches was a hurdle to overcome, but now that we have these processes implemented, we won’t be going back.
The major part of our newer approach is not something particularly innovative, it’s planning. The first part of this process is for the project leads to work together to plan and work out what data is needed. We use various things to do this, including designs and minimum requirements, the product and design teams will generally have scoped and specced much of how the feature should work.
Once that is done we define our contracts. These act as a single source of truth that all work is based off. This is what we call them, but other teams may call it something else. We call it a contract because it’s just that; an agreement that both parties adhere to.
Those contracts are then used as our middle point, the point at which the two teams meet. Once the contract is defined the two teams can work in parallel, and don’t need to communicate as much. That’s how we sped up delivery — because we meet at a pre-agreed and specific point, the teams can now work asynchronously, shaving weeks if not months off a project.
You can do that now, without any technical changes needed, but, the technical changes make this approach easier. This technique relies on documentation, type generation and using atomic/molecular components.
How these pieces fit together
From a BE point of view, the major change is that all API’s require documentation; we use Swagger/OpenAPI for this, but other mechanisms will also suffice.
The next step is that we use those docs to generate TypeScript types that will be used throughout the Front End application. We use DtsGenerator for this.
Once the types are available, the components can start to be built out. We take an atomic/molecular approach, using Storybook to develop the necessary components and their variants. Combined with type-driven functions, our components match the designs and are tested appropriately based on the types we have, without needing a working API.
An example of this would be that if an object has an optional prop that might affect the way the component looks or works, the types dictate the way the code works, and the tests/stories back these up.
Combining all of this has allowed us to have multiple teams working in parallel, and sped up the delivery. Using the automated types based on the documentation means that all potential variances of our components can be handled, thereby improving the reliability of our codebase.
Most of all, this process has removed a lot of unnecessary and potentially overcomplicating communication between teams. Because we work middle out, with a single source of truth, everyone knows exactly what everything can or should look like.
I suppose you could say that the relationship between the Front end and the Back end teams has never been better. With easier communication, working more in harmony and a collective effort to make the features as best as possible. 😍
It’s fair to say that there are some problems that can arise, and a good QA process will help catch these. One of these is the need for extending the API’s which can cause delays as this could block the FE development, I have found however that the benefits far outweigh the negatives we have found so far.