Good post. It's worth pointing out this is diametrically opposed to the "Web vs. native: let's concede defeat" piece that was popular yesterday.[1]
> When a user pushes a button in a website or a mobile app, they don't want to wait for a request to be sent all the way to the server to calculate the new state of the screen.
The guest was talking about the difficulty of putting yourself in the shoes of someone far away from the global data-centres, when you live and work in Silicon Valley / New York / London (he's from New Zealand).
He also said (which I thought was interesting) that Amazon preloads the first items on the next search page, so the user doesn't have to wait for the server, and then loads the rest in the background (with the idea that by the time they have examined the first items, the others will have arrived).
Could you expand on this? My perception has been the rejection of Meteor by experienced programmers has been mostly fear driven and a lack of understanding, but that has been my own opinion. I'm interested in understanding better what is keeping experienced developers from adopting the framework.
Latency compensation/optimistic UIs is one of the first things that clued me into why Meteor is so great back in 2012 when I watched the original screencast: https://www.youtube.com/watch?v=fsi0aJ9yr2o
The reason is actually a common theme throughout Meteor: boilerplate code, and somewhat relatedly "devops" type code, are taken care of by the platform so you get to focus on building your app.
It's such a big focus of Meteor's design compared to every other platform, and it's what's kept me coming back for three years.
In fact, it's surprising that so few other platforms have picked up on the fact that eradicating boilerplate is a feature, and they should compete on it. Maybe with more posts like this, they'll be inspired to head in that direction!
> Whenever the user takes an action, you need to first update your UI to make things look fast, then send a request to the server to do that modification on the real database.
Isn't this just lying to the user? What if the user acts on the update (e.g. closes the page, satisfied the file has been saved) and thereby loses data?
A common pattern is to indicate when the data is persisted on the server but still show a predictive update first. Take chat systems as an example: Whatsapp will show your message you just posted immediately but then it will indicate its persistence by showing you two checkmarks on your message.
Meteor's architecture allows you to have slightly different models in the "predictive" mode and "persisted" mode.
Our team also runs into this issue. Dealing in real time means real time changes. Even if we have to wait on an return from the database to the api to the client.
So we simulate the changes as the user makes the action, 'optimistic UI updating' and then wait for confirmation on the server to persist the data. During that waiting period, we tell the user that their changes are being saved, but they are free to do what ever they wish.
It lets the user know things are happening, but might not persist because we are still in the mode of saving, yet allows the user to carry on with their tasks while we deal with the information they send us.
If they close the page, during this time, they are well aware that the changes are happening. The request has been made, it just didn't return yet.
On the other hand if something was shown to the user indicating changes were pending, yet allowed other tasks to be done simultaneously and still have everything come out in correct synchronous order, are people not better off with the 'lie'?
What you describe is ideal and not a lie. Reporting progress ("Saving...") while allowing concurrent edits is great! But it's dangerous to claim the file has been saved before the save is complete, in the name of "make things look fast."
I think the author should have mentioned that latency compensation with meteor can be made optional.
This is in contrast to a large proportion of existing patterns where the option to simultaneously pile on tasks and keep synchronicity is not available.
Well, if you are designing such a system, you'd want to make sure that you hook into the close page function and give an alert saying 'If you close this page, the file will not finish saving' or something of the sort. Also, you'd probably want to design it such that the 'file save' operation is one of the first things you do rather than the last.
When dealing with sensitive data it's still possible to show progress bars, spinners,... But in most cases it's best to lie to the user and it's what Meteor does by default.
Say you're asked to observe a video of a ball moving forward in a straight line, then the video is paused, and you're asked to predict where the ball goes. You say, "Straight ahead into the target." Then they play the video and instead of hitting the target, someone catches the ball. Oh no, you lied! You horrible, horrible liar!
How does this address the problem of not saving user-submitted data after informing them you've done precisely that? This seems _very_ bad.
I think we're debating the merits of different classes of update here. Some updates are not essential (UI preferences, etc.), but other requests by their very nature, are--billing, messaging, draft editing, etc.
It would be "very bad" for some types of applications and not for others. Clicking "Save" on some complex document is the type of thing where you probably want to report "saving..." and then "saved" only after confirmation back from the server, but for a lot of simple operations that you know should almost always succeed (especially if you're doing something with websockets and you are tracking connected state, so you have a pretty reasonable expectation that you're able to communicate with the server in the next 1s), the best approach is often to assume they're going to succeed, update the UI as if they've succeeded, then if they fail, make sure to call attention to that unexpected case and put the UI back in the right state.
This is just one of the default mechanisms of Meteor. You can also construct regular calls to the server which do not have latency compensation (specifically, by having your update code exist on the server only).
This is commonly called dead-reckoning in the games space and is used all over the place because perceived latency is such an issue with realtime simulations.
Getting a good prediction and then knowing how to gracefully reconcile a missed prediction is part art, part science and what makes building those systems a ton of fun.
While often related, dead reckoning in games refers to a particular technique for latency compensation, not the general concept. Specifically, it refers to calculating positions based on last known velocities.
> When a user pushes a button in a website or a mobile app, they don't want to wait for a request to be sent all the way to the server to calculate the new state of the screen.
[1] https://news.ycombinator.com/item?id=9603845