Live data from Hacker News

REST Anti-patterns

marcelo-cure.blogspot.com

91–100 of 133 posts

Re: REST Anti-patterns

#91
post #89

Earlier quoted context omitted.

I would simply PATCH { "status" : "closed" }, as that's how PATCH works in rails. Regarding the deposits, the difference is that 'deposits' is a collection of deposit resources vs 'deposit' as a verb. I think in this case it makes a lot of sense to do it that way, as you can then GET /account/12345/deposits and see all the deposits ever made.

OK, so the original one used a verb at the end of the URL, whereas it should have used a noun. In practice, this wil often means that the URL is almost identical - here for example, it will be: POST /accounts/12345/deposits instead of: POST /accounts/12345/deposit Perhaps your example would be more obvious if it had different terms, where the noun and verb were more distinct - maybe 'game' and 'play'. Even then, from…

> you end up with some horrible URLs just so it's RESTful

No, you don't. RESTful applications use URLs as opaque identifiers, and communicate all information via resource representations. Communicating information via resource identifiers is decidedly not-RESTful, so any particular URL structure chosen to communicate specific information in the URL is, ipso facto, not RESTful.

Re: REST Anti-patterns

#92

Earlier quoted context omitted.

This type of approach can be great. It is parallel to the idea to the "business is an exchange of documents", and the documents represent "transactions" in the sense of "an invoice", "a packing slip", "a deposit slip", "an order", etc.

> "business is an exchange of documents" Did you just make up this phrase? It's really good!

I've been saying it for a while. I talked to the developers of this product about a decade ago:

https://www.kuali.org/kfs

and that was the thinking behind how that system was built. Also this is the paradigm behind

http://www.enterpriseintegrationpatterns.com/

and it must predate the computer.

Re: REST Anti-patterns

#93
post #66

This misses the elephant in the room. The REST-inspired API that requires 10,000 API calls to do something that could be done in 1. This is a disaster from a simple performance perspective. There is no simple way to build transactions on top of REST so if you need to do something that involves updating more than one data record you really are best off updating them all in one API call. When you are writing a web fron…

You might want to check out GraphQL: http://graphql.org/ . One of its killer features is the ability for clients to specify exactly the data it needs and obtain it in a single request/response.

Also checkout David Nolen's "Clients in Control"[0]. He approaches specifically those points mentioned, and pilfers ideas from Relay and Falcor.

[0]: http://www.datomic.com/videos.html

Re: REST Anti-patterns

#94
post #65
post #61

Earlier quoted context omitted.

For the deposit/withdrawal/transfer set, depending on the specifics of how they are actually moving the amounts around, would likely be best served as their own resource. Since a deposit/withdrawal is just a transfer anyways, just having "/transfer" would be likely be good. The connotation here is that the client is creating a transfer on the server. The body for this request could take the relevant account numbers (…

So I would make a request like: POST /transfer from_account_id=12345&to_account_id=67890&amount=10 Perhaps I've misunderstood your comment, as I don't really understand why this is better than the original: POST /accounts/12345/transfer to_account_id=67890&amount=10 or even: POST /accounts/12345/withdraw amount=10

Having the /account/:accountid/transfer is not a terrible idea, but I would avoid it because the transfer resource is able to stand on it's own with making it tied to a single account resource.

The key point though is that 'transfer' is the resource to perform all three of the original deposit/withdrawal/transfer actions.

Re: REST Anti-patterns

#95

This misses the elephant in the room. The REST-inspired API that requires 10,000 API calls to do something that could be done in 1. This is a disaster from a simple performance perspective. There is no simple way to build transactions on top of REST so if you need to do something that involves updating more than one data record you really are best off updating them all in one API call. When you are writing a web fron…

If your application needs so many objects at once, yes, then you probably need something else. Or you just abstract it away through some POST interface alongside with the 10k resources.

> There is no simple way to build transactions on top of REST so if you need to do something that involves updating more than one data record you really are best off updating them all in one API call.

Yes, you can do that. I mean, if your really need to do that. Otherwise, your client should check the server resources for whether they represent to correct data. And you can always implement something like implicit transactions, where you create a transaction resource and append data to it or create new resources in a certain context.

EDIT: BTW. You don't have to do everything in REST. You can always "upgrade your protocol". So having a link myrpc://myserver:port is very valid.

> If Fielding's thesis went in the trash and got replaced with "one click, one API call, update the UI" we'd hear a lot less carping about how awful the web platform is.

Then we would end up building clients that always implement 100% of your RPC API. And we would not be able to move resources around. Implementing clients and servers would become an all-or-nothing thing, which really bad.

> Careful reading of the http spec is a road to hell anyway because 80% of it is dark corners that aren't really used or implemented.

By that you mean, that YOU have only used 20% of the spec so far? So why is it bad in general? I did not see these dark corners.

Re: REST Anti-patterns

#96
post #89

Earlier quoted context omitted.

I would simply PATCH { "status" : "closed" }, as that's how PATCH works in rails. Regarding the deposits, the difference is that 'deposits' is a collection of deposit resources vs 'deposit' as a verb. I think in this case it makes a lot of sense to do it that way, as you can then GET /account/12345/deposits and see all the deposits ever made.

OK, so the original one used a verb at the end of the URL, whereas it should have used a noun. In practice, this wil often means that the URL is almost identical - here for example, it will be: POST /accounts/12345/deposits instead of: POST /accounts/12345/deposit Perhaps your example would be more obvious if it had different terms, where the noun and verb were more distinct - maybe 'game' and 'play'. Even then, from…

The url might be very similar, but the way it is used - what methods you call on it and with what content, is completely different.

Re: REST Anti-patterns

#97
post #89

Earlier quoted context omitted.

I would simply PATCH { "status" : "closed" }, as that's how PATCH works in rails. Regarding the deposits, the difference is that 'deposits' is a collection of deposit resources vs 'deposit' as a verb. I think in this case it makes a lot of sense to do it that way, as you can then GET /account/12345/deposits and see all the deposits ever made.

OK, so the original one used a verb at the end of the URL, whereas it should have used a noun. In practice, this wil often means that the URL is almost identical - here for example, it will be: POST /accounts/12345/deposits instead of: POST /accounts/12345/deposit Perhaps your example would be more obvious if it had different terms, where the noun and verb were more distinct - maybe 'game' and 'play'. Even then, from…

Yes, it should have been a noun, because a URL is a Uniform Resource Locator, and a verb is not a resource. HTTP methods are for verbs. Sometimes this can lead to strange URLs, but applying the noun/verb rule consistently does simplify things.

One thing that helps is not nesting resources too deep, to avoid having really long URLS.

Re: REST Anti-patterns

#98
post #16

Other commenters are correct that POST /accounts/4402278/close is not right (and also fairly hilariously contradicted in the next section). Account status (open, closed, suspended, whatever else) is a property of the account, in the same way that the account owner's name is a property of the account. If you went to all the trouble to represent each account as its own resource, which I assume responds correctly otherw…

> Other commenters are correct that POST /accounts/4402278/close is not right (and also fairly hilariously contradicted in the next section).

Of course its right. Read the POST spec. POST is for processing data. Its up to the server to what is processed how. If the POST is for closing a bank account, it is valid. I think, my bank would need verify a lot of things before I can close my account with a single click. So the operation cannot be idempotent and thus requires a POST.

I mean, if you are fine with setting just a flag in your bank, you can be fine with a PUT. But I will not become a customer of your bank.

Re: REST Anti-patterns

#99
post #35

HATEOAS is much less important for programmatic APIs. You either hard-code knowledge of the URL scheme in the API client, or you hard-code knowledge of the payload schema in the API client. There isn't a huge amount of difference here IMO, especially if you have some kind of versioning mechanism in your URL routing. Hard-coding URL scheme permits more pipelining and concurrency in the client. Embedding URLs in payloa…

If your implementation can rely on Hypertext, you can build it different. You can build a state machine where parts of your application are "componentised" without knowing the context of a resource.

Re: REST Anti-patterns

#100
post #89

Earlier quoted context omitted.

OK, so the original one used a verb at the end of the URL, whereas it should have used a noun. In practice, this wil often means that the URL is almost identical - here for example, it will be: POST /accounts/12345/deposits instead of: POST /accounts/12345/deposit Perhaps your example would be more obvious if it had different terms, where the noun and verb were more distinct - maybe 'game' and 'play'. Even then, from…

> you end up with some horrible URLs just so it's RESTful No, you don't. RESTful applications use URLs as opaque identifiers, and communicate all information via resource representations. Communicating information via resource identifiers is decidedly not-RESTful, so any particular URL structure chosen to communicate specific information in the URL is, ipso facto , not RESTful.

I'll give a specific specific example from my own experience of building an intranet. I had documents that people could print.

    POST /documents/12345/print
To me, while this was not RESTful, it was the most readable way I came up with. When I asked somebody who had more experience with REST than me, he suggested I build the URL like this:

    POST /users/123/print-jobs

    url=/documents/12345
Doing this, I would have to add validation to make sure it was a printable URL. Also, there was no corresponding GET request, so it seemed pointless. And it made the code weirder, as the 'print' action would be separated from the rest of the actions on documents.

So how would you do it instead? Or you would do it the same way, and just not worry about the problem?

It seems that consensus on how to do REST breaks down when you have custom verbs.

Post reply on HN