[HN Gopher] Swagger/OpenAPI examples are bad, like reaaalllyy bad
___________________________________________________________________
Swagger/OpenAPI examples are bad, like reaaalllyy bad
While reading about the OpenAPI spec, I found these examples for
"good" APIs: - https://petstore.swagger.io/ (older version) -
https://petstore3.swagger.io/ However, imho they are really bad
examples as they do not follow basic principles of good API design.
Here are some reasons: 1. They use "/pet" instead of "/pets" for
the pet collection (Besides the fact that "/pets" isn't even an
endpoint and you can not get a list of all pets ^^). 2. The login
& logout endpoints are under /user (i.e. /user/login, /user/logout)
3. You do not use PUT on a collection as they did with PUT /pet 4.
You do not use POST as they did with /pet/{pet_id} to update a
single resource. 5. You do not use POST to create a resource and
PUT to update the same resource as they did with PUT /pet and POST
/pet Some might argue that it is a matter of opinion that these
examples are bad. You may be right, but at minimum an API should be
self-consistent. But even that is not the case here. That's why
I'm wondering what this is all about. Do I not know the latest API
design principles yet or why are the examples for a de facto
industry standard so lousy? And btw what is your opinion on the
API design of the examples?
Author : d3nigma
Score : 9 points
Date : 2021-07-22 21:01 UTC (2 hours ago)
| ggm wrote:
| Is this about the semantics and syntax of English? Would your
| response be different in a hypothetical language where the
| pluralistic pet is (s)pet? How about if the plurality of pet was
| "scront" or "pet, uncountable many"
|
| Mapping English words with / as a separator and into a world of 4
| or 6 action verbs is a huge constraint on "meaning" in the
| linguistic sense.
| lhorie wrote:
| It feels like you're attacking a design without understanding the
| design principles behind it.
|
| Looking at https://petstore3.swagger.io, the API is `/pet`
| (singular), because that's exactly what it represents: the type
| of a singular pet. This design choice has to do with
| orthogonality: for example, what is `POST /pets` supposed to do?
| Create a new list of pets? That makes no sense. If you want to
| argue that it should create a new pet, then that makes no sense
| either, _because the endpoint is explicitly about a collection of
| pets_. This distinction may seem like nitpicking, but consider an
| entity type of ambiguous plurality like ` /group`. You want to be
| clear about whether an action on this endpoint applies to a
| `group` or to individual entities in the group and you want that
| semantic to be consistent with other endpoints.
|
| On the same vein about orthogonality, `/user/{action}` is
| orthogonal to `/pet/{action}` in the sense that they both follow
| the same OOP-ish pattern. Calling an endpoint merely `/login`
| doesn't fit into that mold (e.g. Can a pet login? Why is `/login`
| floating without a noun, but `DELETE /user/{id}` isn't? etc)
|
| The choices of PUT and POST have to do with what the HTTP spec
| says about idempotency. `PUT /pet` must be idempotent (i.e.
| replace a pet), `POST /pet` is not idempotent (i.e. create a
| pet).
|
| `POST /pet/{id}` is a bit of a seemingly counterintuitive one,
| but again it has to do with idempotency. It's actually a
| deliberate choice to indicate that there may be internal logic
| that isn't pure (for example, there may be a lastModified field).
___________________________________________________________________
(page generated 2021-07-22 23:02 UTC)