Mark my words.
My list of predictions about the future of software. I started this list in response to the announcement of Riffle. I have a history of correctly predicting some changes to software development, but I’ve had no way of checking the accuracy of my predictions up to this point, as I did not captured them anywhere. This post will be used to track my predictions, so that their veracity may be verified.
These predictions were written before they came to fruition.
Within five years a reactive query system, possibly Riffle, will become commonplace in web app development. March 7th, 2022.
The introductory essay on Riffle was published five days ago, and it appears to be another step toward fulfilling a prediction of mine for web development. Among other things, it’s a reactive database query system, such that your application automatically rerenders when the database is updated. Importantly, the reactivity is derived automatically from SQL queries. When you perform a query in the UI, the system will subscribe to changes to the resultant data and rerender your UI when that data is altered. Granted, Riffle is “local-first,” which means it’s not much different from Redux in its utility, but the important step forward is that they are automatically deriving observation from basic SQL queries. I predict that someone will build a reactive SQL system for cloud databases, and it will take over web app development. It is also possible that someone will invent an entirely new database with reactive queries, or that an existing database, like GraphQL, will be extended to include them.
A reactive query system will work as follows. The app developer will use conventional queries to access data, not subscriptions, during a render step. The reactive system will then parse the query to determine which subscription to the database is required such that any change to the results of the queries triggers a notification to the client. That subscription will automatically be applied at the same time that the database is queried for the current state of the requested data. The UI will then be rendered to the screen, but every time that the database changes in such a way that the results of the query might have changed, the query will be rerun, and any changes will trigger an update to the UI. The application code will then consist of a mapping between database queries and UI elements, with no code dedicated to storing the results of a SQL query, subscribing to changes, or reacting to changes specifically.
The complexity of building this system comes from the delay in accessing or updating data on the web. Riffle, in particular, uses a local SQLite database running with WASM, which makes automatic updates almost instantaneous. In contrast to a reactive system, imperatively handling state allows an app developer to decide how they want to handle local caching of or asynchronous updates to the database. Roughly speaking, a reactive query to the cloud would need to handle the delay in communication in one of two ways, either with loading screens or with a predictive cache.
To introduce loading screens, a loading status would be returned whenever the query is yet to be fulfilled or the local cache of the remote database determines that the query will likely change due to some pending update. If a reactive query returns a
loading status, the UI code could then handle that status however it chooses to, likely with a loading screen of some form. A loading screen may appear to diminish the utility of a reactive system, but the advantage lies in not having to imperatively manage subscriptions; not in avoiding any appearance of asynchrony.
The second way to handle the delay in communication is with a predictive cache of the remote database. A predictive cache would update immediately whenever a change request is transmitted to the remote server. The UI could then be rendered synchronously, which would work perfectly if the network couldn’t fail, which, of course, it can. If a network failure occurs, a reactive system would have the tools to roll back the UI to match the new understanding of the unaltered database. Since the reactive system controls UI updates and state changes, the system could simply rerender with the prior database state. The system would then have two choices. It could roll back all local state to fix any erroneous updates since those updates were based on the false notion that the prior change was successful, or it could keep the local changes to navigation and have the update silently disappear. I doubt either of these solutions would be widely adopted, as it would either manifest as the application skipping backward without warning, or data disappearing from the app without warning, neither of which would result in an acceptable user experience.
An alternative method to handling a failed update is to simply notify the application UI that the network is unavailable and that the local cache is not being persisted to the cloud. This would allow the UI to display a notification or to halt further interaction by the user, which is how most web apps work today. This solution would likely be acceptable to most developers, and so, if a predictive cache is used, this is the solution to network failure that I predict would be implemented alongside it. The status of the network would then be provided using an alternative query, which would also be reactive. The query could be configured based on tolerances for network delays, like “has the network been down for more than three seconds.” If the answer to such query is “yes, the network has been down for more than three seconds,” the render function would branch into its notification renderer, or a blocking error screen, whichever the developer prefers. It should be noted that Riffle appears to be compatible with many of these solutions, as a local database does not preclude background syncing.