DEV Community

loading...

Discussion on: Good Bye Web APIs

Collapse
mvila profile image
Manuel Vila Author

Thanks, @stereobooster , you raise important points.

What happens if server code is updated, but client still uses old code?

The server only exposes the type of the attributes and the signature of the methods. So it's no different than a traditional web API. If you change your API endpoints, you break the client. You can make incremental changes though. In case of breaking changes (which is generally not recommended), there is a way to specify a version number when you expose your backend so that the frontend can automatically reload itself.

Is there a way to reload data from server?

Yes, all database related methods offer a reload option.

How does it solve waterfall of requests problem? Or n+1 query problem?

The frontend and the backend communicate with the Deepr protocol. For now, you can send Deepr queries manually (like you would do with GraphQL) to solve the n+1 query problem, but in a near future, I'd like to implement sugar to make the operation easier.

Is there a way to subscribe to changes on the server (long polling or websockets)?

Not yet, but it is on the road map.

Collapse
stereobooster profile image
stereobooster

The frontend and the backend communicate with the Deepr protocol. For now, you can send Deepr queries manually (like you would do with GraphQL) to solve the n+1 query problem, but in a near future, I'd like to implement sugar to make the operation easier.

Nice. This make sense. Deepr looks very similar to GraphQL. Does it mean it has the same "problem" with client side cache resolution? e.g. when you have list of objects and then you update one of them, you need to have resolution otherwise update won't be represented in the list

Thread Thread
mvila profile image
Manuel Vila Author • Edited

The cache problem is out of the scope of Deepr, but Layr (which is built on top of Deepr) partially solves this problem with an identity map. So, all object updates should be automatically synchronized. What remains to be solved though is the case of object additions or removals in collections. For that, I need to add the concept of query subscriptions. It is on the road map but it is not an easy task and it will take a while to be implemented.

Collapse
sleeplessbyte profile image
Derk-Jan Karrenbeld

The server only exposes the type of the attributes and the signature of the methods. So it's no different than a traditional web API. If you change your API endpoints, you break the client. You can make incremental changes though. In case of breaking changes (which is generally not recommended), there is a way to specify a version number when you expose your backend so that the frontend can automatically reload itself.

Traditional APIs are very different. For example, versioning through content-negotiation has none of these problems. Having a server do content-negotiation is a very powerful method to server different agents (for example browsers, or app version, or xxx) different responses, based on their capabilities. This seems completely impossible with Layr.

Even when you use versioning, what happens if you do a rolling update with Layr? That is, you've updated half your servers, but not the other half, with a load balancer in front of it? Will half of it fail?

It also sounds like the entire HTTP Caching protocol would conflict with Layr, that is, Layr will try to do its own synchronisation, ignoring or conflicting with what was previously possible using HTTP Caching. Why is that important? CDN and proxy caching. GraphQL in general suffers from this.

But the worst thing is that the API layer generally forces you to degrade the quality of your codebase. Indeed, it's quite challenging to keep your code DRY and cohesive when your frontend and your backend are separated by a web API.

Isn't this conflating use cases of SSR or those where the backend is very similar to the front-end? In the majority of the work I did the past 10 years, the backend and frontend are completely different, and should be. It feels like the authors of the library haven't had good experiences with trying to write maintainable backend and frontend code and ran into these issues (which is understandable, I've had similar issues too!), but are trying to solve it on the incorrect/unfortunate abstraction.

Thread Thread
mvila profile image
Manuel Vila Author

Traditional APIs are very different. For example, versioning through content-negotiation has none of these problems. Having a server do content-negotiation is a very powerful method to server different agents (for example browsers, or app version, or xxx) different responses, based on their capabilities. This seems completely impossible with Layr.

Let's be real. In practice, how many apps have multiple API versions? My guess is that 95% of the apps have only one API version that serves browsers, mobile, etc. API versioning is a pain in the ass to implement and maintain so we usually go with a single API that supports backward-compatible changes.

It also sounds like the entire HTTP Caching protocol would conflict with Layr, that is, Layr will try to do its own synchronisation, ignoring or conflicting with what was previously possible using HTTP Caching. Why is that important? CDN and proxy caching. GraphQL in general suffers from this.

Layr is made to build web apps, not websites, so HTTP Caching is not an essential feature. It might be supported in the future, but it is not on the priority list.

Isn't this conflating use cases of SSR or those where the backend is very similar to the front-end? In the majority of the work I did the past 10 years, the backend and frontend are completely different, and should be. It feels like the authors of the library haven't had good experiences with trying to write maintainable backend and frontend code and ran into these issues (which is understandable, I've had similar issues too!), but are trying to solve it on the incorrect/unfortunate abstraction.

The author of the library (me) has more than 25 years of experience building full-stack applications.

Thread Thread
sleeplessbyte profile image
Derk-Jan Karrenbeld

Let's be real. In practice, how many apps have multiple API versions? My guess is that 95% of the apps have only one API version that serves browsers, mobile, etc.

API versioning is a pain in the ass to implement and maintain so we usually go with a single API that supports backward-compatible changes.

We write applications for millions of daily users, with clients that can be as old as 2 years (updating them is not in our control). Maintenance of up to 5 versions of the representations of the resources of our endpoints is trivial, because we barely ever have to touch old versions. They just keep working.

I think that the reason so many APIs only have 1 version is because versioning is hard, not because they shouldn't / don't want to have them. So yes, I agree with you that many APIs only have one version, but that's probably more a consequence of tooling not allowing for it, such as this, than that people shouldn't have it.

Having backwards compatible APIs (for example by only adding fields, and never removing/changing fields, which is definitely good practice) doesn't mean you shouldn't/won't have versioning.

  • Stripe has versioning (and mostly backwards compatible changes)
  • Facebook has versioning (and mostly backwards compatible changes)
  • GitHub has versioning (and mostly backwards compatible changes)
  • Twitter has versioning (and mostly backwards compatible changes)

That said, the statement that traditional APIs are no different than Layr-enabled APIs is just false. It just doesn't hold up. I don't know why you're stating anecdotal experience or opinion as fact.

Layr is made to build web apps, not websites, so HTTP Caching is not an essential feature. It might be supported in the future, but it is not on the priority list.

Dismissing HTTP Caching because you think web apps don't need it / don't primarily benefit from it means we can't discuss this.

The author of the library (me) has more than 25 years of experience building full-stack applications.

Then your post and this library seems more out-of-place than I thought before.

Thread Thread
mvila profile image
Manuel Vila Author • Edited

I think the misunderstanding comes from the fact that we are not building the same kind of applications.

I cannot speak about building an application for millions of users. I've never done that. I build small-to-medium applications and I designed Layr for this use case.

So Layr is probably not good for Stripe, Facebook, Twitter, etc. But I believe it is great for the vast majority of developers that don't work on large-scale applications.

Thanks for pointing that out. I edited the "What's the catch?" section to make it clear that Layr is not made for large-scale applications.

Thread Thread
sleeplessbyte profile image
Derk-Jan Karrenbeld

It would be helpful if experienced people stopped making statements that are opinions as if they're fact. This only spreads misinformation and less experienced people are going to take it at face value and run with it.

Good luck with the endeavour.

Collapse
wormss profile image
WORMSS • Edited

Is there a way to subscribe to changes on the server (long polling or websockets)?

Not yet, but it is on the road map.

Yeah, that is a MAJOR massive catch.. That pretty much turns this completely unusable for anything other than meaningless apps that that store a users data in a silo. EG, a note keeping app that doesn't have the ability to share notes between users.

Thread Thread
mvila profile image
Manuel Vila Author

@wormss , I think you misunderstood. Not being able to synchronize clients in real-time with web sockets doesn't mean there is no shared storage. It's no different than any web app, the backend stores data in a database, so any data can be shared between users.

Thread Thread
wormss profile image
WORMSS

If I am reading your example above correctly, "value" is synchronous, so it would never know if someone else has incremented it? So reading it client side will be wrong the moment someone else adds it.

Thread Thread
mvila profile image
Manuel Vila Author

The backend is stateless, so in the example, the counter is unique for each user. To share the counter among all users, the backend must save it in a database.

Thread Thread
wormss profile image
WORMSS

And again, I ask how the UI gets to know that it has changed.

Thread Thread
mvila profile image
Manuel Vila Author

When you execute a remote method on an object, the attributes of the object are automatically transported between the frontend and the backend. So, when you change an attribute in the backend, the change is reflected in the frontend.