Jestem nowy w REST i zauważyłem, że w niektórych usługach RESTful używają one różnych identyfikatorów URI zasobów do aktualizacji / pobierania / usuwania i tworzenia. Jak na przykład
- Twórz - używając / resources metodą POST (obserwuj liczbę mnogą) w niektórych miejscach używając / resource (liczba pojedyncza)
- Aktualizacja - za pomocą / resource / 123 z metodą PUT
- Pobierz - za pomocą / resource / 123 z metodą GET
Jestem trochę zdezorientowany tą konwencją nazewnictwa URI. Czego powinniśmy używać w liczbie mnogiej lub pojedynczej do tworzenia zasobów? Jakie powinny być kryteria przy podejmowaniu takiej decyzji?
rest
resources
naming-conventions
uri
JPReddy
źródło
źródło
Odpowiedzi:
Założeniem użycia
/resources
jest to, że reprezentuje on „wszystkie” zasoby. Jeśli to zrobiszGET /resources
, prawdopodobnie zwrócisz całą kolekcję. Przesyłając do/resources
, dodajesz do kolekcji.Jednak poszczególne zasoby są dostępne w / zasób. Jeśli to zrobisz
GET /resource
, prawdopodobnie popełnisz błąd, ponieważ to żądanie nie ma żadnego sensu, a/resource/123
ma doskonały sens.Korzystanie
/resource
zamiast/resources
jest podobny do tego, jak chcesz to zrobić, jeśli pracowaliśmy z, powiedzmy, systemu plików i kolekcji plików i/resource
jest „katalog” z poszczególnymi123
,456
pliki w nim.Żadna z tych dróg nie jest dobra ani zła, wybierz to, co lubisz najbardziej.
źródło
Dla mnie lepiej jest mieć schemat, który można odwzorować bezpośrednio na kod (łatwy do zautomatyzowania), głównie dlatego, że kod będzie tym, co będzie na obu końcach.
źródło
Nie widzę sensu w robieniu tego i myślę, że nie jest to najlepszy projekt URI. Jako użytkownik usługi RESTful spodziewałbym się, że zasób listy będzie miał tę samą nazwę, bez względu na to, czy uzyskam dostęp do listy, czy do określonego zasobu „na” liście. Powinieneś używać tych samych identyfikatorów bez względu na to, czy chcesz użyć zasobu listy, czy określonego zasobu.
źródło
Liczba mnoga
orders/
pobiera indeksowaną listę zamówień.Na przykład:
GET /resources
- zwraca listę elementów zasobówPOST /resources
- tworzy jeden lub wiele elementów zasobówPUT /resources
- aktualizuje jeden lub wiele elementów zasobówPATCH /resources
- częściowo aktualizuje jeden lub wiele elementów zasobówDELETE /resources
- usuwa wszystkie elementy zasobówA dla pojedynczych elementów zasobów:
GET /resources/:id
- zwraca określony element zasobu na podstawie:id
parametruPOST /resources/:id
- tworzy jeden element zasobu o określonym identyfikatorze (wymaga weryfikacji)PUT /resources/:id
- aktualizuje określony element zasobuPATCH /resources/:id
- częściowo aktualizuje określony element zasobuDELETE /resources/:id
- usuwa określony element zasobuZwolennicy liczby pojedynczej pomyśl o tym w ten sposób: Czy poprosiłbyś kogoś o coś
order
i oczekiwałbyś jednej rzeczy lub listy rzeczy? Dlaczego więc miałbyś oczekiwać, że usługa zwróci listę rzeczy podczas pisania/order
?źródło
Order
to dobra nazwa dla klasy, która zajmuje się pojedynczymi instancjami obiektów odnoszącymi się do jednego rzędu.OrderList
to nazwa klasy, która zajmuje się wielomaOrder
instancjami.Orders Table
to dobra nazwa tabeli bazy danych zawierającej wiele zamówień.Pojedynczy
Wygoda Rzeczy mogą mieć nieregularne nazwy w liczbie mnogiej. Czasami nie mają. Ale pojedyncze nazwy są zawsze dostępne.
np. CustomerAddress nad CustomerAddresses
Rozważ ten powiązany zasób.
Jest
/order/12/orderdetail/12
to bardziej czytelne i logiczne niż/orders/12/orderdetails/4
.Tabele bazy danych
Zasób reprezentuje byt taki jak tabela bazy danych. Powinien mieć logiczną pojedynczą nazwę. Oto odpowiedź na nazwy tabel.
Mapowanie klas
Zajęcia są zawsze pojedyncze. Narzędzia ORM generują tabele o takich samych nazwach jak nazwy klas. Ponieważ coraz więcej narzędzi jest używanych, pojedyncze nazwy stają się standardem.
Przeczytaj więcej o Dylemacie programisty interfejsu API REST
źródło
/clothe/12/trouser/34
:)clothe
jest czasownikiem. Pozostałe interfejsy API zwykle trzymają się rzeczowników, gdy mówią o zasobach, i używają czasowników podczas opisywania akcji. Forma pojedyncza jestclout
, ale jest archaiczna i prawdopodobnie lepiej by ją zastąpićgarment
.Podczas gdy najbardziej rozpowszechnioną praktyką są RESTful apis, w których używa się liczby mnogiej, np.
/api/resources/123
Jest jeden szczególny przypadek, w którym uważam, że użycie nazwy pojedynczej jest bardziej odpowiednie / wyraziste niż liczby mnogie. Jest tak w przypadku relacji jeden do jednego. W szczególności, jeśli element docelowy jest obiektem wartości (w paradygmacie projektowania opartego na domenie).Załóżmy, że każdy zasób ma jeden do jednego,
accessLog
który można by modelować jako obiekt wartości, tj. Nie byt, dlatego nie ma identyfikatora. Można to wyrazić jako/api/resources/123/accessLog
. Zwykłe czasowniki (POST, PUT, DELETE, GET) odpowiednio wyrażają zamiar, a także fakt, że związek jest rzeczywiście jeden do jednego.źródło
GET /users/123/location
powinien pobrać lokalizację, w której pracuje użytkownik. Czy takGET /users/123/locations
naprawdę konsument nie wprowadza w błąd?accessLog
jest modelowany jako atrybut lub wartość, a nie jako jednostka, powinien być liczbą pojedynczą. Jeśli masz zbyt dużo inżynierii, wpis w dzienniku byłby bytem i miałbyś/api/accessLogEntries?resource=123
.Dlaczego nie podążać za powszechnym trendem nazw tabel w bazie danych, w którym ogólnie przyjmuje się formę pojedynczą? Byłem tam, zrobiłem to - wykorzystajmy ponownie.
Dylemat nazywania tabel: nazwy w liczbie pojedynczej i mnogiej
źródło
Jestem zaskoczony, widząc, że tylu ludzi wskoczyłoby na mnogą rzeczownikową modę. Czy podczas implementacji konwersji liczby pojedynczej na liczbę mnogą zajmujesz się nieregularnymi rzeczownikami w liczbie mnogiej? Czy lubisz ból?
Zobacz http://web2.uvcs.uvic.ca/elc/studyzone/330/grammar/irrplu.htm
Istnieje wiele rodzajów nieregularnej liczby mnogiej, ale są one najczęściej:
Rodzaj rzeczownika Formowanie liczby mnogiej Przykład
źródło
Z punktu widzenia konsumenta interfejsu API punkty końcowe powinny być przewidywalne
Idealnie...
GET /resources
powinien zwrócić listę zasobów.GET /resource
powinien zwrócić kod statusu na poziomie 400.GET /resources/id/{resourceId}
powinien zwrócić kolekcję z jednym zasobem.GET /resource/id/{resourceId}
powinien zwrócić obiekt zasobu.POST /resources
powinien wsadowo tworzyć zasoby.POST /resource
powinien utworzyć zasób.PUT /resource
powinien zaktualizować obiekt zasobu.PATCH /resource
powinien zaktualizować zasób, publikując tylko zmienione atrybuty.PATCH /resources
powinien wsadowo aktualizować zasoby, publikując tylko zmienione atrybuty.DELETE /resources
powinien usunąć wszystkie zasoby; tylko żartuję: kod statusu 400DELETE /resource/id/{resourceId}
Takie podejście jest najbardziej elastyczne i bogate w funkcje, ale także najbardziej czasochłonne. Jeśli więc się spieszysz (co jest zawsze w przypadku tworzenia oprogramowania), po prostu podaj swój punkt końcowy
resource
lub liczbę mnogąresources
. Wolę formę pojedynczą, ponieważ daje ona możliwość introspekcji i oceny programowej, ponieważ nie wszystkie formy liczby mnogiej kończą się na „s”.To powiedziawszy, bez względu na powód, z którego najczęściej wybierał programista, jest stosowanie liczby mnogiej. To jest ostatecznie droga, którą wybrałem i jeśli spojrzysz na popularne api
github
itwitter
takie właśnie są.Niektóre kryteria podejmowania decyzji mogą być:
Więc to zależy od ciebie. Cokolwiek robisz, bądź konsekwentny.
źródło
POST /users
powinien utworzyć jednego użytkownika, dodając go do kolekcji. Nie zgadzam się.POST /users
powinien utworzyć listę użytkowników (nawet jeśli jest to lista 1), gdziePOST /user
powinien utworzyć dokładnie jednego użytkownika. Nie widzę powodu, dla którego zarówno punkty końcowe w liczbie mnogiej, jak i w liczbie pojedynczej nie mogą współistnieć. Opisują różne zachowania i nie powinny nikogo dziwić ich funkcji.POST users/<id>
utworzyłby nowego użytkownika.PUT /users/<id>
zamiastPOST
.POST
ma interpretację „dodaj to do kolekcji i określ identyfikator jako część tego”.PUT
ma interpretację „zaktualizuj (lub dodaj) ten zasób o tym identyfikatorze”. Więcej informacji na temat tej zasady można znaleźć na stronie restcookbook.com/HTTP%20Methods/put-vs-post .Moje dwa centy: metody, które spędzają czas zmieniając liczbę mnogą na liczbę pojedynczą lub odwrotnie, są marnowaniem cykli procesora. Mogę być oldschoolowy, ale w moich czasach rzeczy były nazywane tak samo. Jak wyszukać metody dotyczące ludzi? Żadna regularna ekspresja nie obejmie zarówno osoby, jak i osób bez niepożądanych skutków ubocznych.
Angielskie liczby mnogie mogą być bardzo dowolne i niepotrzebnie obciążają kod. Trzymaj się jednej konwencji nazewnictwa. Języki komputerowe miały dotyczyć przejrzystości matematycznej, a nie naśladowania języka naturalnego.
źródło
Wolę używać formy pojedynczej ze względu na prostotę i spójność.
Na przykład biorąc pod uwagę następujący adres URL:
/ klient / 1
Potraktuję klienta jako odbiór klienta, ale dla uproszczenia część kolekcji jest usuwana.
Inny przykład:
/ wyposażenie / 1
W takim przypadku wyposażenie nie jest poprawną liczbą mnogą. Traktowanie go jako zbioru sprzętu i usuwanie kolekcji dla uproszczenia sprawia, że jest zgodny z przypadkiem klienta.
źródło
POST /customer
to nie jest samo - wstawić jednego klienta?POST /customer
czyta mi to tak, jakby to było wysyłanie dothe
klienta. Nie kolekcja klientów. Przyznaję jednak, że preferowana jest liczba mnoga. Tak długo, jak nie są mieszane tak jak inne odpowiedzi. To byłoby niezwykle mylące.Identyfikator trasy powinien być wyświetlany tak samo jak indeks listy, a nazewnictwo powinno być kontynuowane odpowiednio.
Ale niektóre zasoby nie używają identyfikatorów na swoich trasach, ponieważ jest tylko jeden lub użytkownik nigdy nie ma dostępu do więcej niż jednego, więc nie są to listy:
źródło
W przypadku konwencji nazewnictwa zwykle można bezpiecznie powiedzieć „wybierz jedną i trzymaj się jej”, co ma sens.
Jednak po konieczności wyjaśnienia REST wielu osobom reprezentowanie punktów końcowych jako ścieżek w systemie plików jest najbardziej ekspresyjnym sposobem na zrobienie tego.
Jest bezstanowy (pliki istnieją lub nie istnieją), hierarchiczny, prosty i znajomy - już wiesz, jak uzyskać dostęp do plików statycznych, lokalnie lub przez http.
W tym kontekście reguły językowe mogą doprowadzić cię tylko do tego, co następuje:
I lubię to.
Chociaż z drugiej strony - to twój katalog, możesz nazwać go „zasobem lub wieloma zasobami”, jeśli tego chcesz. To nie jest naprawdę ważna rzecz.
Co ważne, jeśli umieścisz plik o nazwie „123” w katalogu o nazwie „resourceS” (w wyniku czego
/resourceS/123
), nie możesz oczekiwać, że będzie on dostępny za pośrednictwem/resource/123
.Nie staraj się, aby był mądrzejszy niż musi być - zmiana z liczby mnogiej na singluar w zależności od liczby dostępnych zasobów może być dla niektórych estetyczna, ale nie jest skuteczna i nie ma sensu system hierarchiczny .
Uwaga: Technicznie możesz tworzyć „dowiązania symboliczne”, aby
/resources/123
można było uzyskać do nich dostęp za pośrednictwem/resource/123
, ale to pierwsze wciąż musi istnieć!źródło
Rzucić okiem na Google „s API Design Guide: Nazwy zasobów dla innego spojrzenia na nazewnictwa zasobów.
W skrócie:
Warto przeczytać, jeśli myślisz o tym temacie.
źródło
Używanie liczby mnogiej dla wszystkich metod jest bardziej praktyczne przynajmniej w jednym aspekcie: jeśli opracowujesz i testujesz interfejs API zasobów za pomocą Postmana (lub podobnego narzędzia), nie musisz edytować identyfikatora URI podczas przełączania z GET na PUT na POST itp. .
źródło
Oba przedstawienia są przydatne. Od jakiegoś czasu używałem liczby pojedynczej, przegięcie może być trudne. Moje doświadczenie w tworzeniu ściśle pojedynczych interfejsów API REST, programiści używający punktu końcowego nie mają pewności, jaki może być kształt wyniku. Wolę teraz używać terminu, który najlepiej opisuje kształt odpowiedzi.
Jeśli wszystkie zasoby są na najwyższym poziomie, możesz uciec od pojedynczych reprezentacji. Unikanie przegięcia to duża wygrana.
Jeśli wykonujesz jakiekolwiek głębokie linkowanie w celu reprezentowania zapytań dotyczących relacji, programistom piszącym przeciwko Twojemu interfejsowi API można pomóc, stosując bardziej rygorystyczną konwencję.
Moja konwencja polega na tym, że każdy poziom głębokości w URI opisuje interakcję z zasobem nadrzędnym, a pełny URI powinien pośrednio opisywać to, co jest pobierane.
Załóżmy, że mamy następujący model.
Gdybym musiał udostępnić zasób, który pozwala klientowi uzyskać menedżera określonego znajomego określonego użytkownika, mogłoby to wyglądać mniej więcej tak:
GET /users/{id}/friends/{friendId}/manager
Oto kilka innych przykładów:
GET /users
- wymień zasoby użytkowników w globalnej kolekcji użytkownikówPOST /users
- utwórz nowego użytkownika w globalnej kolekcji użytkownikówGET /users/{id}
- pobierz określonego użytkownika z globalnej kolekcji użytkownikówGET /users/{id}/manager
- uzyskaj menedżera określonego użytkownikaGET /users/{id}/friends
- zdobądź listę przyjaciół użytkownikaGET /users/{id}/friends/{friendId}
- zdobądź określonego przyjaciela użytkownikaLINK /users/{id}/friends
- dodaj powiązanie znajomego do tego użytkownikaUNLINK /users/{id}/friends
- usuń powiązanie znajomego z tym użytkownikiemZwróć uwagę, w jaki sposób każdy poziom jest mapowany na rodzica, na którym można działać. Używanie różnych rodziców dla tego samego obiektu jest sprzeczne z intuicją. Pobieranie zasobu w
GET /resource/123
nie pozostawia żadnych wskazówek, że należy utworzyć nowy zasób wPOST /resources
źródło
Wiem, że większość ludzi decyduje, czy użyć liczby mnogiej czy pojedynczej. Problem, który nie został tutaj rozwiązany, polega na tym, że klient musi wiedzieć, którego używasz, i zawsze może popełnić błąd. Stąd moja sugestia.
Co powiesz na oba? I przez to mam na myśli użycie liczby pojedynczej dla całego API, a następnie utworzenie tras do przekazywania żądań złożonych w liczbie mnogiej do formy pojedynczej. Na przykład:
Dostajesz obraz. Nikt się nie myli, minimalny wysiłek, a klient zawsze dobrze to zrobi.
źródło
/resources
i zawsze/resource
zostajesz przekierowany , zrobiłeś to źle. Jeśli ktoś inny korzysta z Twojego API, może albo użyć poprawnego adresu URL bezpośrednio, albo zostać przekierowanym (co działa, ale jest złe) i to Ty otworzyłeś niewłaściwy sposób.Nie lubię, gdy
{id}
część adresów URL pokrywa się z podrzędnymi zasobamiid
teoretycznie może to być cokolwiek i byłoby niejednoznaczne. Łączy różne pojęcia (identyfikatory i nazwy pod-zasobów).Podobne problemy są często postrzegane w
enum
stałych lub folder struktur, gdzie różne koncepcje są mieszane (na przykład, gdy masz folderyTigers
,Lions
aCheetahs
, a następnie również folder o nazwieAnimals
na tym samym poziomie - to nie ma sensu, jak ktoś jest podzbiorem inny).Ogólnie rzecz biorąc, myślę, że ostatnia nazwana część punktu końcowego powinna być pojedyncza, jeśli dotyczy ona pojedynczego elementu na raz, i liczba mnoga, jeśli dotyczy listy elementów.
Punkty końcowe, które dotyczą jednego użytkownika:
Następnie istnieje osobny zasób do wykonywania zapytań na użytkownikach, które zazwyczaj zwracają listę:
A oto kilka przykładów pod-zasobu, który zajmuje się konkretnym użytkownikiem:
Zaprzyjaźnij się (link wiele do wielu):
Nigdy nie ma dwuznaczności, a mnoga lub pojedyncza nazwa zasobu jest wskazówką dla użytkownika, czego może się spodziewać (lista lub obiekt). Nie ma żadnych ograniczeń dotyczących
id
s, teoretycznie umożliwiając posiadanie użytkownika o identyfikatorzenew
bez nakładania się na (potencjalnie przyszłą) nazwę pod-zasobu.źródło
Użyj liczby pojedynczej i skorzystaj z angielskiej konwencji, np. W „Business Directory”.
Wiele rzeczy czyta się w ten sposób: „Book Book”, „Dog Pack”, „Art Gallery”, „Festival Film”, „Car Lot” itp.
To wygodnie dopasowuje ścieżkę adresu URL od lewej do prawej. Typ elementu po lewej stronie. Ustaw typ po prawej stronie.
Czy
GET /users
naprawdę kiedykolwiek pobiera zestaw użytkowników? Zazwyczaj nie. Pobiera zestaw kodów pośredniczących zawierających klucz i być może nazwę użytkownika. Tak czy/users
inaczej tak naprawdę nie jest . Jest to indeks użytkowników lub „indeks użytkowników”, jeśli wolisz. Dlaczego nie nazwać tego tak? Jest to/user/index
. Ponieważ nazwaliśmy typ zestawu, możemy mieć wiele typów pokazujących różne prognozy użytkownika bez uciekania się do parametrów zapytania np .user/phone-list
Lub/user/mailing-list
.A co z użytkownikiem 300? Nadal jest
/user/300
.Na zakończenie HTTP może mieć tylko jedną odpowiedź na pojedyncze żądanie. Ścieżka zawsze odnosi się do pojedynczego czegoś.
źródło
Dla mnie liczba mnoga manipuluje kolekcją , podczas gdy liczba pojedyncza manipuluje przedmiotem w tej kolekcji.
Kolekcja pozwala na metody GET / POST / DELETE
Pozycja pozwala na metody GET / PUT / DELETE
Na przykład
POST na / uczniowie dodadzą nowego ucznia do szkoły.
USUŃ włączone / uczniowie usuną wszystkich uczniów w szkole.
USUŃ na / student / 123 usunie ucznia 123 ze szkoły.
Może to wydawać się nieistotne, ale niektórzy inżynierowie czasami zapominają o identyfikatorze. Jeśli trasa była zawsze w liczbie mnogiej i wykonano operację USUŃ, możesz przypadkowo wyczyścić swoje dane. Podczas gdy brak identyfikatora w liczbie pojedynczej zwróci trasę 404, nie znaleziono.
Aby dalej rozwinąć przykład, jeśli API miałoby ujawniać wiele szkół, to coś w tym rodzaju
USUŃ na / school / abc / students usunie wszystkich uczniów w szkole
abc
.Wybór właściwego słowa czasami stanowi wyzwanie sam w sobie, ale lubię zachować wiele kolekcji. Np.
cart_items
Lubcart/items
czuje się dobrze. W przeciwieństwie do usuwaniacart
, usuwa sam obiekt koszyka, a nie elementy w koszyku;).źródło
Co powiesz na:
/resource/
(nie/resource
)/resource/
oznacza, że folder zawiera coś o nazwie „zasób”, jest to folder „resouce”.Myślę też, że konwencja nazewnictwa tabel bazy danych jest taka sama, na przykład tabela o nazwie „użytkownik” jest „tabelą użytkownika”, zawiera coś zwanego „użytkownikiem”.
źródło
Wolę używać zarówno liczby mnogiej (
/resources
), jak i pojedynczej (/resource/{id}
), ponieważ uważam, że bardziej wyraźnie oddziela logikę między pracą nad kolekcją zasobów a pracą nad pojedynczym zasobem.Jako ważny efekt uboczny tego, może również pomóc w zapobieganiu niewłaściwemu użyciu API. Rozważmy na przykład przypadek, w którym użytkownik błędnie próbuje uzyskać zasób, określając identyfikator jako parametr w następujący sposób:
W tym przypadku, gdy używamy liczby mnogiej, serwer najprawdopodobniej zignoruje parametr Id i zwróci listę wszystkich zasobów. Jeśli użytkownik nie będzie ostrożny, pomyśli, że połączenie się powiodło, i użyje pierwszego zasobu na liście.
Z drugiej strony, gdy używasz formy pojedynczej:
serwer najprawdopodobniej zwróci błąd, ponieważ identyfikator nie jest określony we właściwy sposób, a użytkownik będzie musiał zrozumieć, że coś jest nie tak.
źródło