Dlaczego konwencja mówi, że nazwy tabel DB powinny być pojedyncze, a zasoby RESTful w liczbie mnogiej?

27

Jest to dość ugruntowana konwencja, że ​​nazwy tabel bazy danych, przynajmniej w SQL, powinny być pojedyncze. SELECT * FROM user;Zobacz to pytanie i dyskusję .

Jest to również dość popularna konwencja, że ​​nazwy zasobów interfejsu API RESTful powinny być w liczbie mnogiej. GET /users/123i POST /userszobacz to .

W najprostszym API opartym na bazie danych nazwą zasobu w adresie URL byłaby tabela, a elementy danych w adresie URL i treściach żądania / odpowiedzi byłyby mapowane bezpośrednio na kolumny w DB. Pod względem koncepcyjnym nie widzę różnicy między operowaniem na danych za pośrednictwem tego teoretycznego interfejsu API a operowaniem na nich bezpośrednio za pomocą SQL. Z tego powodu różnica w konwencjach nazewnictwa między useri usersnie ma dla mnie sensu.

Jak można uzasadnić różnicę w liczbie mnogiej, gdy koncepcyjnie interfejs API REST i SQL robią to samo?

smitelli
źródło
3
Nie ma jednej konwencji nazywania tabel DB ani nazywania zasobów RESTful, którą wszyscy przestrzegają. Przeciwnie, może być wiele konwencji. Nic dziwnego, że niektórzy mogą się ze sobą kłócić.
Eric King,
13
Nie ma takiej ustalonej konwencji. Zawsze używałem nazw tabel w liczbie mnogiej. użytkownicy , konta itp., ponieważ przechowują więcej niż jedną z tych rzeczy.
GrandmasterB
2
@GrandmasterB Konwencja istnieje i wywodzi się z modelu relacyjnego Codda, w którym „relacje” (które stają się tabelami, aby nie pomylić się z relacjami) mają pojedyncze nazwy, ponieważ relacja jest listą rzeczy, a nie kilkoma listami rzeczy. Każda relacja to jedna lista. Jednostki domeny modelu relacji. Nazwy jednostek są osobliwe w modelu relacyjnym Codda. Istnieje wiele literatury na ten temat, która mówi, że nie istnieje. Ale możesz używać liczby mnogiej, jeśli chcesz.
Tulains Córdova,
4
@ user61852 Są ludzie, którzy mogą z niego korzystać zgodnie z konwencją. Ale w żadnym wypadku nie jest to szeroko stosowana konwencja branżowa przedstawiona w tym pytaniu w sposób, powiedzmy, że jest to camelCase lub MarkDown.
GrandmasterB
4
Należy również pamiętać, że REST nie jest protokołem dostępu do bazy danych. Nie ma powodu, dla którego konwencje nazewnictwa DB (z którymkolwiek wybierasz) i konwencje nazewnictwa URL (z którymkolwiek wybierasz) powinny być podobne, nie mają ze sobą nic wspólnego. Dwie bardzo różne domeny. Nie ma sensu zastanawiać się, dlaczego bazy danych używają liczby pojedynczej, a adresy URL używają liczby mnogiej, niż zastanawiać się, dlaczego bazy danych używają liczby pojedynczej, ale mój administrator systemu nazwał swoje katalogi systemu plików liczbą mnogą. Źle zaprojektowane frameworki internetowe sprawiają, że ludzie myślą, że REST ma związek z dostępem do bazy danych, ale tak nie jest.
Cormac Mulhall,

Odpowiedzi:

12

Specyfikacja REST (niezależnie od poziomu, z którym chcesz przejść) nie została zaprojektowana jako dostęp do bazy danych. Stara się doprowadzić do standaryzacji dostępu do interfejsu API. Wspomniane konwencje SQL (czy chcesz ich używać, czy nie) nie zostały zaprojektowane z myślą o dostępie do API. Służą do pisania zapytań SQL.

Problemem do rozpakowania jest tutaj koncepcyjne zrozumienie, że interfejs API mapuje bezpośrednio na bazę danych. Możemy to znaleźć jako anty-wzór, przynajmniej od 2009 roku .

Czy główny powód jest zły? Kod opisujący „jak ta operacja wpływa na moje dane?” staje się kodem klienta .

Ma to dość okropny wpływ na API. (nie wyczerpująca lista)

Utrudnia to integrację z API

Wyobrażam sobie kroki, aby utworzyć nowego użytkownika udokumentowanego jako coś takiego:

  1. POST /users { .. }
  2. POST /usersettings { .. } z pewnymi wartościami domyślnymi
  3. POST /confirmemails { .. }

Ale jak sobie poradzić z niepowodzeniem kroku # 2? Ile razy ta sama logika obsługi kopiuje makaron innym klientom interfejsu API?

Te operacje na danych są często łatwiejsze do sekwencjonowania po stronie serwera, a inicjowane są przez klienta jako pojedyncza operacja. Np POST /newusersetup. DBA mogą rozpoznać to jako procedurę przechowywaną, ale działanie interfejsu API może mieć skutki wykraczające poza samą bazę danych.

Zabezpieczenie API staje się czarną dziurą rozpaczy

Powiedzmy, że musisz połączyć dwa konta użytkowników.

  1. GET /users/1
  2. PUT /users/2 { .. }
  3. DELETE /users/1

Jak zamierzasz skonfigurować uprawnienia użytkownika, aby zezwolić na funkcję scalania, a jednocześnie nie zezwala na usunięcie użytkownika? Czy usunięcie użytkownika jest nawet sprawiedliwie reprezentowane przez, DELETE /users/1kiedy /usersettingsrównież istnieje?

Operacje API należy traktować jako operacje na wyższym poziomie (niż baza danych), które mogą powodować wiele zmian w systemie.

Konserwacja staje się trudniejsza

... ponieważ Twoi klienci są zależni od struktury bazy danych.

Na podstawie mojego doświadczenia z tym scenariuszem:

  • Nie można zmienić nazwy ani usunąć istniejących tabel / kolumn. Nawet jeśli są niepoprawnie nazwane dla swoich funkcji lub nie są już używane. Klienci się zepsują.
  • Nowe funkcje nie mogą zmienić istniejących struktur danych, więc ich dane i funkcje są często sztucznie oddzielone, nawet jeśli całościowo należą do istniejącej funkcji.
  • Baza kodu staje się coraz trudniejsza do zrozumienia ze względu na fragmentację, mylące nazwy i resztki bagażu, których nie można bezpiecznie usunąć.
  • Wszystkie zmiany oprócz trywialnych stają się coraz bardziej ryzykowne i czasochłonne.
  • System zastyga i ostatecznie zostaje wymieniony.

Nie ujawniaj struktury bazy danych bezpośrednio klientom ... zwłaszcza klientom, nad którymi nie masz kontroli rozwojowej. Użyj interfejsu API, aby zawęzić klienta do prawidłowych operacji.

Więc jeśli używasz API jako interfejsu bezpośrednio do bazy danych, pluralizacja jest najmniejszym zmartwieniem. W przypadku eksperymentu innego niż jednorazowe sugeruję poświęcić trochę czasu na określenie operacji wyższego poziomu, które powinien reprezentować interfejs API. A kiedy spojrzysz na to w ten sposób, nie ma konfliktu między pluralizowanymi nazwami encji API a pojedynczymi nazwami encji SQL. Są tam z różnych powodów.

Kasey Speakman
źródło
1
Odpowiada na inne pytanie. OP nie oznacza bezpośredniego powiązania jednostek API i DB, tylko obecność niektórych jednostek w obu kontekstach.
Basilevs,
2
Zachęcamy do opublikowania odpowiedzi na pytanie, które według Ciebie jest zadawane.
Kasey Speakman
4
@Basilevs Właściwie myślę, że to odpowiada na pytanie. Czasami odpowiedzi mogą wydawać się pośrednie, gdy pytanie jest sformułowane wokół błędnych założeń. „Obecność niektórych podmiotów w obu kontekstach” oznacza, że są te same podmioty, co oznacza 1 do 1 korespondencji między niektórymi, a nie innych. Taka zgodność interfejsu API w złożonym modelu danych implikuje wadliwy projekt.
Aluan Haddad
Wśród nich jest wiele powodów, dla których przestałem używać Spring Data Rest.
Sebastiaan van den Broek
4

Interfejs API REST i SQL NIE „robią tego samego”

OP pyta:

Jak można uzasadnić różnicę w liczbie mnogiej, gdy koncepcyjnie interfejs API REST i SQL robią to samo?

Ach, ale konik polny, może się wydawać, że interfejs RESTful i tabele SQL „robią to samo”, ale dobra higiena programowania mówi nam, że zawsze istnieje warstwa pośrednia, która pośredniczy między interfejsem API REST a bazą danych. Zignorowanie tego punktu oznacza zejście ze ścieżki do oświecenia programowego! :)

Dzięki temu interfejsy API RESTful i tabele SQL mogą z radością przestrzegać własnych idiomatycznych konwencji nazewnictwa, które są dobrze udokumentowane i szczegółowo omówione w innym miejscu.

nieustraszony głupiec
źródło