Witam wszystkich,
tytułem wstępu przedstawię się, jestem Jeffdot i od 3 lat pracuję jako programista .NET. Jest to mój pierwszy post, ale samo forum śledzę już od kilku lat.
Zwracam się do Was z problemem, dotyczącym obsługi błędów w aplikacji oraz późniejszym zwracaniem komunikatów w odpowiednim języku do użytkownika końcowego.
Żeby lepiej zrozumieć zagadnienie poniżej zamieszczam informację o tym, jak w mojej pracy wygląda podział na warstwy aplikacji:
-
**Model ** - encje, których kształt oddaje bazę danych 1 do 1. Niewiele jest tutaj logiki, czyli każdy produkt mimo tego, że jest osobnym bytem, i ma swoją logikę, wrzucany jest do jednej globalnej tabeli. Encje mapowane są przez EF.
-
**Application **- Command/Query handlery - MediatR
-
**Calculator **- tutaj bardziej skomplikowana logika dotycząca wyliczania kwoty konkretnej usługi (to jest core naszej aplikacji, cała istotna logika dotycząca poszczególnych produktów jest tutaj)
-
**API **- REST API kontrolery - nasze wewnętrzne API, tworzy Command/Query i przez MediatR deleguje go do warstwy Application
-
Front
Niestety aplikacja ma już pare lat, nie ma Bounded Contextów, a przy dodawania obsługi nowego produktu, umieszczane wszystko jest w tych globalnych layerach w postaci nowych folderów z nazwą pakietu/produktu.
Początkowo logika była sterowana exceptionami, na szczęście zespół przystał na moją propozycję, by zamiast exceptionów zwracać klasę
public class Result<T>
{
public bool Success { get; private set; }
public IEnumerable<ErrorCode> Errors { get; private set; }
public T Value {get; private set;}
}
ErrorCode to enum, np. ErrorCode.EMAIL_EMPTY
W warstwie API, błędy są tłumaczone na odpowiedni język, przez szukanie w Resources komunikatu o takiej samej nazwie co ErrorCode. Testy jednostkowe sprawdzają, czy nie brakuje odpowiedniego komunikatu ErrorCodu.
Przejdźmy teraz do pytań:
-
Czy ErrorCode enum, może być współdzielony między warstwami? Błąd może wystąpić zarówno w warstwie aplikacji, warstwie model, jak i w warstwie Calculator. Tworzenie osobnych błędów dla każdej warstwy i mapowanie ich w moim przypadku wydaje się być karkołomne.
-
Czy w ogóle sam pomysł posługiwania się ErrorCodem i tłumaczeniem go w warstwie API/FRONT, jest ok? Pytam ponieważ, ostatnio jeden z seniorów stwierdził, że tutaj jest niepotrzebnie podwójna robota, ponieważ każdy błąd trzeba dodać do ErrorCode, oraz komunikaty w odpowiednich językach do Resources. Kolegi propozycja była, żeby przesyłać od razu komunikat z Resources, ale stwierdziłem, że to zły pomysł, ponieważ inne warstwy nie powinny zajmować się tłumaczeniem komunikatów na przyjazne dla użytkownika, to powinno dziać się na samym końcu.
-
W jakich sposób zwracacie z API konkretny HTTP Status Code dla konkretnego błędu. U mnie odbywa się to przez tłumaczenie ErrorCode na odpowiedni resposne, np.
ErrorCode.NOT_FOUND => HTTP 404 (Not Found);
ErrorCode.SERVICE_UNAVAILABLE => HTTP 503 (Service Unavailable);
pozostałe => HTTP 400 (BadRequest).
Zapraszam do dyskusji i jak już wcześniej wspomniałem, od dawna śledzę forum, dlatego bardzo liczę na odpowiedzi od: @somekind, @Shalom, @jarekr000000, @neves