Czy jest sens używać liczbowych error codów w dzisiejszych czasach?

0

Jak w temacie. Jeśli uznamy, że wpływ na performance jest pomijalny to czy ma to jakikolwiek sens w przypadku typowego backendowego API?

Zalety liczb jakie widzę: performance, mniej zajmowanego miejsca, jak nie lubimy/nie chcemy użyć angielskiego to liczby mogą być złotym środkiem
Wady: słabe discoverability, w zasadzie nie wiem czemu tak się robi.

Jeśli argumentem jest możliwość grupowanie po rodzaju (w przypadku HTTP x / 100) to można użyć prefiksu np. HTTP 4** -> client_error.*** a HTTP 5** -> server_error.***

1

Rozwiń ta myśl

Wady: słabe discoverability,

7

Robiąc backend nie zawsze masz świadomość / wiedzę na temat aplikacji forntendowych, które z tego backendu będą korzystać. Robiąc słownik kodów błędów dajesz developerom frontendowym wprowadzenie np wielojęzyczności w ich aplikacjach. Przykład z życia wzięty klient polski korzysta z aplikacji napisanej w delphi natomiast rynek czeski korzysta z WWW. Obie aplikacje działają na tej samej bazie, a dzięki kodom błędów developerzy poszczególnych frontów sami sobie komunikaty ogarniają ;)

7

Dla mnie chodzi o standaryzację. Widzę 404 i wiem od razu o co chodzi. Wyobraź sobie teraz że 100 pomysłowych developerów pisze sobie wszelkie komunikaty ręcznie według własnego uznania. Nagle server error może już nie być tym samym błędem. Ile już tu jest dyskusji było jaki kod rzucić kiedy. Po coś te RFC tworzą chyba.
No i pewnie zabrakłoby czajniczka.

0

Rozwiń ta myśl

@axelbest: widzę 4320 i wiem, że nic nie wiem. Widzę invalid_input.bad_email i nawet nie muszę szukać w słowniku dlaczego mój request się nie powiódł

Robiąc backend nie zawsze masz świadomość / wiedzę na temat aplikacji forntendowych, które z tego backendu będą korzystać. Robiąc słownik kodów błędów dajesz developerom frontendowym wprowadzenie np wielojęzyczności w ich aplikacjach. Przykład z życia wzięty klient polski korzysta z aplikacji napisanej w delphi natomiast rynek czeski korzysta z WWW. Obie aplikacje działają na tej samej bazie, a dzięki kodom błędów developerzy poszczególnych frontów sami sobie komunikaty ogarniają ;)

@woolfik: ale ja nie mówię o używaniu human readable description tylko o przedstawianiu typu błędów za pomocą stringów. Niezależnie od języka i szczegółów dany typ błędu zawsze będzie przypisany do tego samego stringa

Dla mnie chodzi o standaryzację. Widzę 404 i wiem od razu o co chodzi. Wyobraź sobie teraz że 100 pomysłowych developerów pisze sobie wszelkie komunikaty ręcznie według własnego uznania. Nagle server error może już nie być tym samym błędem. Ile już tu jest dyskusji było jaki kod rzucić kiedy. Po coś te RFC tworzą chyba.

@jurek1980: 404 i wiesz o co chodzi, bo się tego nauczyłeś. Nie widzę powodu dlaczego błąd w stylu client_error.not_found albo not_found byłby trudniejszy do zapamiętania

Wyobraź sobie teraz że 100 pomysłowych developerów pisze sobie wszelkie komunikaty ręcznie według własnego uznania

@jurek1980: to samo masz w kodach: ktoś może uznać, że pierwsza cyfra to rodzaj błędu a ktoś np. że pierwsza to rodzaj a druga to węższa grupa danego rodzaju. A jeszcze ktoś inny może wcale nie grupować tych błędów (np. błędy w jądrze linuxa). Jakbyś miał zapisane w RFC, że dane błędy są przypisane do określonego, specyficznego stringa to nie byłoby problemu

0

Ja nie do końca chyba rozumiem o co ty pytasz ... zobacz tu:
XML - dobranie się do błędu
w rozwiązaniach SOAP masz gotową strukturę z błędami gdzie masz kod i opis. To pomaga usprawnić komunikaty dla użytkownika, a nie tylko dla developera. 404 jest dla nas wiadomwe ale użytkownika np to co powyżej:
<errorCode>1201</errorCode>
dzięki czemu developer może po kodzie błędu wyświetlić userowi:
<errorMessage>Brak w rejestrze klienta o numerze 2778704</errorMessage>
lub przetłumaczyć to np na język ukraiński :)

0

@woolfik: zamiast

<errorCode>1201</errorCode>
<errorMessage>Brak w rejestrze klienta o numerze 2778704</errorMessage>

chcę

<errorCode>client_not_found</errorCode>
<errorMessage>Brak w rejestrze klienta o numerze 2778704</errorMessage>

Zauważ, że moje pytanie to "czy jest sens używać LICZBOWYCH error codów" a nie "czy jest sens używać jakichkolwiek error codów"

3

tak ma sens bo w przypadku liczb nie masz problemu np z kodowaniem, formatowaniem, uppercase, lowercase, uristring itd ..., że już o ilości przesyłanych danych nie wspomnę :P Ogólnie jako developer robiący backend możesz sobie zrobić errorCode jako stringa ale potem we froncie będziesz miał:

if utf8(lowercase(errorCode)) = 'client_not_found' then
  ..
else if utf8(lowercase(errorCode)) = 'client inactive' then
  ..

a tak masz

case when errorCode of 
1201: ...
1202: ...
end
0

@woolfik: nie rozumiem. Error cody to forma umowy. Jak napiszę że błąd bla_bla_bla będzie oznaczał błąd A a błąd x_d_d_d błąd B to tak ma być. Jeśli to nie jest oczywiste to warto to napisać w dokumentacji, ewentualnie wyrazić regexem w stylu [a-z_\.]+. Dodatkowo snake_case albo SCREAMING_SNAKE_CASE wyglądają w taki sposób, że od razu widać, że nie ma sensu nic ujednolicać. Liczby też mogę przesyłać na różne sposoby np. JSON 404 i 404.0: w zależności od biblioteki i języka, którego używam mogę dostać true lub type error

1

My jako regule tez uzywamy jakis human readable error code, typu: "MISSING_VERIFICATION_CODE" od razu zaleznie od contextu wiadomo o co chodzi.
Tak jak ze wszystkim mamy standard czyli zawsze pole nazywa sie tak samo w response, jest to snake case (cos ala constants czyli zawsze uppercase).
Takze to sie sprawdza a tak jak ktos wspomnial potem latwo jest przetlumaczyc rozne error code'y.

6

Odpowiadając na pytanie. I dziś i za 10 lat będzie sens używania tych kodów.

1
woolfik napisał(a):

w rozwiązaniach SOAP masz gotową strukturę z błędami gdzie masz kod i opis. To pomaga usprawnić komunikaty dla użytkownika, a nie tylko dla developera. 404 jest dla nas wiadomwe ale użytkownika np to co powyżej:
<errorCode>1201</errorCode>
dzięki czemu developer może po kodzie błędu wyświetlić userowi:
<errorMessage>Brak w rejestrze klienta o numerze 2778704</errorMessage>
lub przetłumaczyć to np na język ukraiński :)

Przy protokołach zrobionych Apache Thrift nawet exception można przekazać przez sieć.

Co jest w moim wdrozeniu BARDZO pozytywne, np znaczna część wyjątków to naruszone reguły biznesowe z czytelnym stosownym komunikatem
Mieć treść na kliencie - bezcenne.

0

Jest sens, bo ten błąd nie zawsze ma być wyłącznie dla człowieka. Klient może chcieć interpretować różne typy błędów "po swojemu".

4

Masakra, większosć nie zrozumiała o co chodzi autorowi xd

2
slsy napisał(a):

Jak w temacie. Jeśli uznamy, że wpływ na performance jest pomijalny to czy ma to jakikolwiek sens w przypadku typowego backendowego API?

Raczej nie.

Wady: słabe discoverability, w zasadzie nie wiem czemu tak się robi.

Z przyzwyczajenia/bo klient tak chce.

2
anonimowy napisał(a):

Masakra, większosć nie zrozumiała o co chodzi autorowi xd

Zrouzumiałem, chociaż autor robi wszystko podając chociażby jako cztero cyfrowy kod błędu HTTP

widzę 4320 i wiem, że nic nie wiem.

Teraz dla niektórych jest jasne, że taki błąd jest z danej klasy i oznacza konkretną akcję bo to kiedyś ustandaryzowano. W momencie zastąpienia kodów tekstem trzeba by albo odwzorować stary standard, co nie ma raczej sensu, albo tworzyć nowy. I nie mówimy tu o tak naprawdę prostej sprawie. Bo jak określimy chociażby statusy typu 301? Obsługa ze strony przeglądarek, bibliotek i tego wszystkiego co już jest musiałby być przepisana. Teraz wyobraźmy sobie jeszcze, że Hindusi i Chińczycy chcą to w swoim języku.
Poza tym nie wiem dlaczego ludzie ciągle myślą, a to tylko kilka bajtów więcej, a jak zsumuje się to i popatrzy w skali internetu?

1
slsy napisał(a):

@woolfik: nie rozumiem. Error cody to forma umowy. Jak napiszę że błąd bla_bla_bla będzie oznaczał błąd A a błąd x_d_d_d błąd B to tak ma być. Jeśli to nie jest oczywiste to warto to napisać w dokumentacji, ewentualnie wyrazić regexem w stylu [a-z_\.]+. Dodatkowo snake_case albo SCREAMING_SNAKE_CASE wyglądają w taki sposób, że od razu widać, że nie ma sensu nic ujednolicać. Liczby też mogę przesyłać na różne sposoby np. JSON 404 i 404.0: w zależności od biblioteki i języka, którego używam mogę dostać true lub type error

No mi właśnie o to chodziło, o prostotę frontu. Jak sam wspomniałeś (uwierz lub nie) regex nie należy do najwydajniejszych. Tak jak Ci podałem w moim przykładzie powyżej zamiast prostego porównania wartości liczbowej kodu błędu forontendowiec będzie zmuszony porównywać tekst 'bla_bla_bla'. Jak użyje czegoś niestandardowego, albo za jakiś czas Twój backend zostanie rozbudowany np o taki kod "BRAK UŻYTKOWNIKA" (bo trafi Ci się student, który zrobi Ctrl+C, Ctrl+V i zmieni tylko bla_bla_bla na swój varchar) to może się okazać, że to co otrzyma będzie w innym kodowaniu i będzie zmuszony dodać odpowiedni kod, który pozwoli mu uzyskać "bla_bla_bla" lub "BRAK UŻYTKOWNIKA". Rozumiesz do czego zmierzam? W przypadku kodu błędu sytuacja jest jasna bo 1 to 1 i wystarczy w słowniku/dokumentacji sprawdzić co oznacza 1 :)

Do tego dochodzi właśnie druga rzecz czyli rozbudowa Twojego słownika kodów błędów. Mówisz bla_bla_bla ale jak się system z biegiem lat będzie rozrastał i będziesz dodawał coraz to nowe komunikaty/błędy to w pewnym momencie okaże się, że trzeba się "głowić" nad nowymi unikalnymi bla_bla_bla, a numerki lecą po kolei natomiast opis robisz sobie w słowniku / dokumentacji słowno-muzyczny jaki Ci pasuje :)

Nie zrozum mnie źle ja nie mówię, że to bla_bla_bla jako kod błędu jest złe po prostu uważam, że ma więcej wad niż zalet (bazując na swoim doświadczeniu w pisaniu zarówno frontów jak i backendów) ;)

1

Teraz dla niektórych jest jasne, że taki błąd jest z danej klasy i oznacza konkretną akcję bo to kiedyś ustandaryzowano. W momencie zastąpienia kodów tekstem trzeba by albo odwzorować stary standard, co nie ma raczej sensu, albo tworzyć nowy. I nie mówimy tu o tak naprawdę prostej sprawie. Bo jak określimy chociażby statusy typu 301? Obsługa ze strony przeglądarek, bibliotek i tego wszystkiego co już jest musiałby być przepisana.

@jurek1980: generalnie piszę o projektowaniu nowego API, nie ma sensu zmieniać coś co działa. W moich przykładach podawałem kody HTTP bo są popularne. Język faktycznie może być problemem (o czym wspomniałem w pierwszy poście). Co do bajtów: marnujemy tyle prądu na parsowaniu tekstowych formatów, lekkie zwiększenie rozmiaru dla błędów to praktycznie nic, jeśli mówimy o typowym backendowym API

No mi właśnie o to chodziło, o prostotę frontu. Jak sam wspomniałeś (uwierz lub nie) regex nie należy do najwydajniejszych.

@woolfik chodziło mi o regex w dokumentacji, tak samo na froncie nikt nie sprawdza, czy liczba to \d+, choć tu akurat wychodzi zaleta liczb jaką jest osobny typ w JSONie.

W przypadku kodu błędu sytuacja jest jasna bo 1 to 1 i wystarczy w słowniku/dokumentacji sprawdzić co oznacza 1 :)

@woolfik zgodzę się, że potencjał na zepsucie jest większy. Z drugiej strony nie potrafię sobie wyobrazić takiej sytuacji. Dodając nowy kod (niezależnie od formatu) i tak musisz zajrzeć do pliku z definicją, zobaczyć czy już nie mamy czegoś podobnego i ewentualnie dodać nowy kod.

Inna sprawa, że samo opisujące się kody mogą sprawić, że ludzie będą je wymyślać ad-hoc bez sprawdzania w słowniku, co faktycznie jest wadą.

0
slsy napisał(a):

@woolfik chodziło mi o regex w dokumentacji, tak samo na froncie nikt nie sprawdza, czy liczba to \d+, choć tu akurat wychodzi zaleta liczb jaką jest osobny typ w JSONie.

dobra to może podam Ci przykład związany z tym konkretnym "BRAK UŻYTKOWNIKA" bo chyba nie możemy się zrozumieć. Mam starsze delphi gdzie muszę ręcznie obsłużyć protokół i dostaję "BRAK U^DZYTKOWNIKA", winą jest kodowanie więc do swojego kodu muszę zrobić właśnie UTF8(errorCode) aby uzyskać "BRAK UŻYTKOWNIKA". Koledzy w javie z pokoju obok obsługują to jakims starym frameworkiem, który nie dość, że urywa im polskie znaki to spacje zmienia na %20 i dostają "brak%20uytkownika" do tego zmierzam. Programista na froncie nie zawsze ma to co chce, czasami musi robić tym co ma i potem boryka się z takimi, a nie innymi problemami. Jak przekażesz mu 1 to zawsze i w każdym języku będzie 1, a on sobie już potem użyje słownika do wygenerowania komunikatu. Natomiast regex w dokumentacji? W dokumentacji możesz wpisać co chcesz ale i tak ktoś kto z tego korzysta będzie to potem musiał przeklepać na swój język, w którym to oprogramowywuje.

4
woolfik napisał(a):

dobra to może podam Ci przykład związany z tym konkretnym "BRAK UŻYTKOWNIKA" bo chyba nie możemy się zrozumieć.

Ale przecież nikt o zdrowych zmysłach nie wysłałby kodu błędu BRAK UŻYTKOWNIKA. Chodzi generalnie o to, by kody błędów nie były w formacie numerów, tylko samoopisujących się tekstów, na przykład user.not_found, czy coś w tym rodzaju. Według mnie jest to lepsze rozwiązanie, niż przesyłanie nic nie znaczących kodów, przy których niezbędne jest zaglądanie do dokumentacji za każdym razem, kiedy chcemy go rozszyfrować.

2

No fajnie, a jak się okaże, że ktoś ma jakiś specjalny parser i dla niego "." jest np zakończeniem stringa lub końcem linii? Nie wiesz tego pisząc backend, a backend powinien być jak najbardziej uniwersalny. Można zrobić tak jak podałem w przykładzie:

<errorCode>1201</errorCode>
<errorMessage>user.not_found</errorMessage>

Jak już wam tak zależy. Zmierzam tylko do tego, że łatwiej jest obsłużyć wartość liczbową niż tekst bo z tekstem zawsze może się coś zadziać czy to przy przesyłaniu, czy to przy odczycie czy to przy parsowaniu.

0

Dobra Panowie bo widzę, że dalej się nie rozumiemy

Pobieramy

<errorCode>BRAK UŻYTKOWNIKA</errorCode>
<errorMessage>user.not_found</errorMessage>

mam klasę

type
  TExceptionData = class
    errorCode: string;
    errorMessage: string;
  end;

W zależności od tego co ustawię w nagłówkach/kodowaniu itd. mogę dostać taki kod:

var
  vGetException: TExceptionData;
begin
  vGetException := GETXMLORJSON;
  if vGetException.errorCode = 'BRAK UŻYTKOWNIKA' then
   //tu mi nie wchodzi
  else 
    //tylko tu
end;

Dzieje się tak ponieważ metoda GETXMLORJSON może być gotowym narzędziem, z którego programista musi skorzystać. W takim wypadku dostajemy w vGetExcception.errorCode wartość np 'brak%20uytkownika' rozumiecie o czym do was piszę teraz?

0

Masakra jakbym gadał do ściany ...

user.not_found powinien być errorCode. Twórcy tych error codów powinni pomyśleć o tym, żeby kody były jak najbardziej idiotoodporne tj. ASCII, brak białych znaków, brak innych znaków poza _

var
  vGetException: TExceptionData;
begin
  try
    vGetException := GETXMLORJSON;
    if vGetException.errorCode = 'user.not_found' then
      //tu mi nie wchodzi
    else 
      //ti mi nie wchodzi
  except
    on e: exception do
      //tu wchodzi bo . w GETXMLORJSON jest traktowana jako koniec lini/stringa i nie można sparsować tego waszego JSON'a lub XML'a
  end;
end;
2

@woolfik: Zacytuję sam siebie:

maszrum napisał(a):

Ale przecież nikt o zdrowych zmysłach nie wysłałby kodu błędu BRAK UŻYTKOWNIKA.

I zaraz pewnie padnie argument:

no ale programista może popełnić błąd i nie zastosować się do reguł, że kody błędów mają być według ustalonego schematu

Dla mnie to żaden argument, bo równie dobrze może użyć ujemnej liczby, albo jakieś spoza zakresu inta.

Przesyłanie dwóch kodów jednocześnie (numer + tekst) przecież jeszcze bardziej zwiększa ryzyko, że coś pójdzie nie tak. Zaletą tekstowych kodów błędów jest to że debugowanie wygląda tak:

  • podglądam Fiddlerem co zostało przesłane,
  • bardzo prawdopodobne, że wiem, co kod oznacza.

A nie:

  • podglądam Fiddlerem co zostało przesłane,
  • jakiś numer, wtf?
  • sprawdzam dokumentację,
  • wiem, co kod oznacza.
7

Przestańcie się skupiać na 404 i user.not_found, bo to jest trywialny i mylący przykład.

Weźmy sobie takie sytuacje, że API zwraca HTTP 400, a tam może być:

  • user.email_already_in_use.
  • user.invalid_email
  • user.name_too_long
  • user.name_too_short
  • 500 innych sytuacji

@jurek1980, @woolfik - będziecie pisali jakieś magiczne numerki do takich sytuacji, a potem podręcznik dla programisty frontendu, żeby wiedział jak ma numerkowy errorCode zmapować na komunikat w UI?
Czemu nie będzie lepiej, jeśli od razu to przeczyta w kodzie błędu?

0

W standardzie HTTP mamy wymuszenie na kody cyfrowe, więc tak czy siak się używa. Stworzone to zostało na pewno z powodu wydajnościowych, w dzisiejszym frontendzie opieranie się o cyfrowy kod nie ma za wielu zalet, z drugiej strony skoro jest to ustandaryzowane i wiadomo co znaczy 2XX, 3XX, 4XX i 5XX to czemu nie korzystac z tego. Preferuje hybrydowe podejscie, gdzie generalnie pierwsza cyfra nam mówi o statusie wiadomości, a później już specyficzny kod tekstowy.

2

Ciekawy temat w sumie, wyglada jak pomysł własny protokół. IMO standaryzacja, dzięki której na start masz jakaś defaultową obsługę błędów. Co jeśli pojawi się jakiś nieznany status, który jest napisem? Musiałbyś mieć jakiś fallback.

Druga sprawa wydajność - to, co proponujesz to trochę debug mode. Cena jaka płacisz, to przesyłanie więcej bajtów + porównywanie stringów (CPU).

Po trzecie, status HTTP jest tez używany w przypadku sukcesu (głównie 200) i redirectów, wiec kilka rzeczy w jednym polu. Oczywiście można by to tez zmapować na napisy.

0

Część osób chyba nie złapało o co w tym wątku chodzi, co zresztą już zostało wypomniane. Nikt nikogo nie zachęca do ignorowania/wykorzystywania kodów HTTP do informowania o błędach. Mowa jest o kodach bardziej specyficznych przesyłanych jako body, np. w JSON.

Przecież to są inne warstwy. TCP też posiada kody błędów i nikt nikogo nie zachęca/zniechęca do wykorzystywania ich jako nośnik informacji o niepowodzeniu. Po prostu to są różne warstwy i niosą informacje o różnym poziomie błędów.

2

@somekind: ok. Tylko widzisz nawet jaki jest tok Twojego myślenia. Zacząłeś od "weźmy 400" bo to Ci samemu mówi o znaczniu błędu.
Co innego rozszerzyć błąd o opis, co innego zastąpić go całkowicie. Dla mnie ciągle mówimy w kontekście API które to powiedzmy z reguły jednak oparte jest o to nieszczęsne HTTP, które w tym wątku traktowane jest jako jakiś nie występujący byt zewnętrzny, który sobie pozmieniamy.
OP sugerował zastąpienie w pełni tych błędów z czym się nie zgadzam.
W innych wątkach nawet kiedyś dyskutowaliśmy czy nie lepiej w niektórych przypadkach nie zrobić tak naprawdę response 200 i zamiast "OK" dać jakiś "error user name to long".

3
somekind napisał(a):

Przestańcie się skupiać na 404 i user.not_found, bo to jest trywialny i mylący przykład.

Weźmy sobie takie sytuacje, że API zwraca HTTP 400, a tam może być:

  • user.email_already_in_use.
  • user.invalid_email
  • user.name_too_long
  • user.name_too_short
  • 500 innych sytuacji

@jurek1980, @woolfik - będziecie pisali jakieś magiczne numerki do takich sytuacji, a potem podręcznik dla programisty frontendu, żeby wiedział jak ma numerkowy errorCode zmapować na komunikat w UI?
Czemu nie będzie lepiej, jeśli od razu to przeczyta w kodzie błędu?

Ktoś tak czy inaczej musi zrobić mapowanie - klient albo serwer. Powiedzmy, że serwer złapał wyjątek. UserException nic nie mówi misiowej oglądającej Youtube. user.name_too_long pewnie też jej nic nie powie. Prędzej po polsku, że "nazwa użytkownika jest za długa - użyj czegoś od 6 do 32 znaków". Ewentualnie po francusku czy innemu, jeśli misia jest z innego kraju.
Wniosek: numerek czy tekst jest nieistotny, jeśli trzeba zamapować to w UI na komunikat w języku odbiorcy. Jeśli ktoś chce się dobrać do błędu, bo debuguje apkę, to pewnie też nie zrobi mu różnicy, bo w google szuka się tak samo. Inna sprawa czy zwracać w kodzie prorgramu numerek czy string. Wtedy dochodzą kwestie wydajnościowe. Ale chyba nie o tym jest dyskusja.

1 użytkowników online, w tym zalogowanych: 0, gości: 1