Typically, when we build a single-page application, the frontend and the backend are living in two very separate worlds that are connected with a web API. Even if they are implemented with the same language (JavaScript), they cannot communicate directly using this language. They need something else in between, so we build a web API (REST, GraphQL, etc.), and that complicates everything.
First, the web API must be implemented on both sides: an API client in the frontend and an API server in the backend. Second, to transport the domain model between the frontend and the backend, we must constantly serialize and deserialize it. All this leads to a lot of code scattering, duplication of knowledge, boilerplate, and accidental complexity.
We get lost in translation.
Most of the time, web APIs are not functional requirements. They don't add any value to the product we are building. They are just a necessary evil so the frontend can communicate with the backend. But is that really the case? Wouldn't it be possible to get rid of these web APIs?
I started building Liaison to achieve exactly that: getting rid of these "pain-in-the-ass" web APIs.
With Liaison, frontend and backend can communicate directly with the language they are implemented in. The frontend can call a method in the backend without further ceremony. It is just a regular JavaScript method invocation.
The way it works is simple: a frontend class can "inherit" from a backend class. So, when a method is called, if this method is missing in the frontend, the corresponding method is executed in the backend, automatically.
For example, let's say the frontend is executing the following code:
await user.follow(anotherUser);
Depending on the implementation of
follow()
, the execution can happen:When a method is executed in the backend, the attributes of the involved instances (
user
and anotherUser
) are transported to the backend, the method is executed, and if some attributes have changed during the execution, those changes are automatically reflected in the frontend.Conceptually, it works like class inheritance. The only difference is that the inheritance occurs across two execution environments: the frontend and the backend. And when we call a method, it doesn't matter where the execution actually happens. For the developer, frontend and backend become one unified world.
So there is no need to build a web API anymore. We can still implement such an API if it is actually required (for example, we intend to open our application to third-party developers through a REST API), but for our own needs, we greatly benefit from doing without it.
Without the burden of building a web API, we can dramatically reduce code scattering, duplication of knowledge, and boilerplate. We can build faster, and better.
Is this approach working? I think it does. I built a RealWorld example with Liaison, both the frontend and the backend, and the outcome looks quite amazing to me: straightforward implementation, high code cohesion, 100% DRY, and zero boilerplate.
In terms of the amount of code, in case it matters, my implementation is significantly lighter than any other one I have examined:
The numbers represent the amount of lines of code excluding comments and test suites (count done on October 7th, 2019 using Tokei.)
Liaison is still at an early stage, and a lot of work remains so it can be used in production. I truly believe it is something worth trying, and I am actively working on it. I expect to release the first beta version in early 2020.