Piszę usługę internetową w Javie i próbuję znaleźć najlepszy sposób definiowania kodów błędów i powiązanych z nimi ciągów błędów . Muszę mieć zgrupowany numeryczny kod błędu i ciąg błędu. Zarówno kod błędu, jak i ciąg błędu zostaną wysłane do klienta uzyskującego dostęp do usługi internetowej. Na przykład, gdy wystąpi SQLException, mogę chcieć wykonać następujące czynności:
// Example: errorCode = 1,
// errorString = "There was a problem accessing the database."
throw new SomeWebServiceException(errorCode, errorString);
Program kliencki może zobaczyć komunikat:
„Wystąpił błąd nr 1: Wystąpił problem z dostępem do bazy danych”.
Moją pierwszą myślą było użycie jednego Enum
z kodów błędów i zastąpienie toString
metod zwracania ciągów błędów. Oto co wymyśliłem:
public enum Errors {
DATABASE {
@Override
public String toString() {
return "A database error has occured.";
}
},
DUPLICATE_USER {
@Override
public String toString() {
return "This user already exists.";
}
},
// more errors follow
}
Moje pytanie brzmi: czy istnieje lepszy sposób na zrobienie tego? Wolałbym rozwiązanie w kodzie, zamiast czytać z zewnętrznego pliku. Używam Javadoc w tym projekcie i możliwość udokumentowania kodów błędów w linii i automatycznego ich aktualizacji w dokumentacji byłaby pomocna.
Odpowiedzi:
Cóż, z pewnością jest lepsza implementacja rozwiązania wyliczeniowego (co jest ogólnie całkiem przyjemne):
Możesz zastąpić toString (), aby zamiast tego po prostu zwrócił opis - nie jestem pewien. W każdym razie głównym celem jest to, że nie musisz nadpisywać osobno dla każdego kodu błędu. Zwróć również uwagę, że wyraźnie określiłem kod zamiast używać wartości porządkowej - ułatwia to późniejszą zmianę kolejności i dodawanie / usuwanie błędów.
Nie zapominaj, że to wcale nie jest umiędzynarodowione - ale jeśli twój klient usługi sieciowej nie wyśle ci opisu lokalizacji, i tak nie możesz łatwo umiędzynarodowić go samodzielnie. Przynajmniej będą mieli kod błędu do użycia dla i18n po stronie klienta ...
źródło
Jeśli o mnie chodzi, wolę uzewnętrznić komunikaty o błędach w plikach właściwości. Będzie to bardzo pomocne w przypadku internacjonalizacji aplikacji (jeden plik właściwości na język). Łatwiej jest także zmodyfikować komunikat o błędzie i nie będzie potrzebna żadna ponowna kompilacja źródeł Java.
W moich projektach generalnie mam interfejs, który zawiera kody błędów (ciąg znaków lub liczba całkowita, to nie obchodzi), który zawiera klucz w plikach właściwości dla tego błędu:
w pliku właściwości:
Kolejnym problemem związanym z twoim rozwiązaniem jest łatwość konserwacji: masz tylko 2 błędy i już 12 linii kodu. Wyobraź sobie więc plik wyliczenia, kiedy będziesz miał setki błędów do zarządzania!
źródło
Przeciążanie metody toString () wydaje się nieco nieprzyjemne - wydaje się to trochę naciągnięciem normalnego użycia metody toString ().
Co powiesz na:
wydaje mi się dużo czystszy ... i mniej szczegółowy.
źródło
W mojej ostatniej pracy poszedłem trochę głębiej w wersji enum:
@Error, @Info, @Warning są zachowywane w pliku klasy i są dostępne w czasie wykonywania. (Mieliśmy też kilka innych adnotacji, które pomogły w opisie dostarczania wiadomości)
@Text to adnotacja w czasie kompilacji.
Napisałem do tego procesor adnotacji, który wykonał następujące czynności:
Napisałem kilka programów narzędziowych, które pomogły w rejestrowaniu błędów, opakowywaniu ich jako wyjątków (w razie potrzeby) i tak dalej.
Próbuję sprawić, by pozwolili mi to otworzyć ... - Scott
źródło
Polecam zapoznać się z java.util.ResourceBundle. Powinieneś przejmować się I18N, ale warto, nawet jeśli nie masz. Eksternalizacja wiadomości to bardzo dobry pomysł. Przekonałem się, że warto było dać przedsiębiorcom arkusz kalkulacyjny, który pozwoliłby im na wprowadzenie dokładnego języka, który chcieli zobaczyć. Napisaliśmy zadanie Ant, aby wygenerować pliki .properties w czasie kompilacji. To sprawia, że I18N jest trywialny.
Jeśli używasz także Springa, tym lepiej. Ich klasa MessageSource jest przydatna do tego rodzaju rzeczy.
źródło
Tylko po to, by dalej chłostać tego konkretnego martwego konia - dobrze wykorzystaliśmy numeryczne kody błędów, gdy błędy są wyświetlane klientom końcowym, ponieważ często zapominają lub błędnie odczytują faktyczny komunikat o błędzie, ale czasami mogą zachować i zgłosić wartość liczbową, która może dać masz wskazówkę, co się właściwie wydarzyło.
źródło
Istnieje wiele sposobów rozwiązania tego problemu. Moim preferowanym podejściem jest posiadanie interfejsów:
Teraz możesz zdefiniować dowolną liczbę wyliczeń, które dostarczają wiadomości:
Teraz masz kilka opcji, aby zamienić je w ciągi. Możesz skompilować ciągi do swojego kodu (używając adnotacji lub parametrów konstruktora wyliczenia) lub możesz je odczytać z pliku config / property lub z tabeli bazy danych lub ich mieszaniny. To drugie jest moim preferowanym podejściem, ponieważ zawsze będziesz potrzebować wiadomości, które możesz zamienić na tekst bardzo wcześnie (np. Podczas łączenia się z bazą danych lub czytania konfiguracji).
Używam testów jednostkowych i struktur odbicia, aby znaleźć wszystkie typy, które implementują moje interfejsy, aby upewnić się, że każdy kod jest gdzieś używany i że pliki konfiguracyjne zawierają wszystkie oczekiwane komunikaty itp.
Korzystając z frameworków, które mogą analizować Javę, takich jak https://github.com/javaparser/javaparser lub ten z Eclipse , możesz nawet sprawdzić, gdzie są używane wyliczenia i znaleźć nieużywane.
źródło
Ja (i reszta naszego zespołu w mojej firmie) wolę zgłaszać wyjątki zamiast zwracać kody błędów. Kody błędów muszą być sprawdzane wszędzie, przekazywane i powodują, że kod staje się nieczytelny, gdy ilość kodu staje się większa.
Klasa błędu definiowałaby wtedy komunikat.
PS: a właściwie również dbaj o internacjonalizację!
PPS: możesz również przedefiniować metodę podnoszenia i dodać logowanie, filtrowanie itp. W razie potrzeby (przynajmniej w środowiskach, w których klasy Exception i przyjaciele są rozszerzalne / zmienialne)
źródło
Trochę późno, ale szukałem dla siebie ładnego rozwiązania. Jeśli masz inny rodzaj błędu wiadomości, możesz dodać prostą, niestandardową fabrykę wiadomości, aby określić więcej szczegółów i format, który chcesz później.
EDYCJA: ok, użycie wyliczenia tutaj jest trochę niebezpieczne, ponieważ zmieniasz dane wyliczenie na stałe. Myślę, że lepiej byłoby zmienić klasę i użyć pól statycznych, ale nie możesz już używać '=='. Więc myślę, że to dobry przykład czego nie robić (lub robić to tylko podczas inicjalizacji) :)
źródło
wyliczenie dla definicji kodu / komunikatu błędu jest nadal dobrym rozwiązaniem, chociaż ma obawy i18n. Właściwie możemy mieć dwie sytuacje: kod / komunikat jest wyświetlany użytkownikowi końcowemu lub integratorowi systemu. W drugim przypadku I18N nie jest potrzebny. Myślę, że usługi internetowe są najprawdopodobniej późniejszym przypadkiem.
źródło
Używanie
interface
jako stałej wiadomości jest generalnie złym pomysłem. Wyciek na stałe do programu klienta jako część eksportowanego API. Kto wie, że późniejsi programiści mogą analizować te komunikaty o błędach (publiczne) jako część swojego programu.Będziesz na zawsze zablokowany, aby to obsługiwać, ponieważ zmiany w formacie ciągu mogą / mogą uszkodzić program klienta.
źródło
Postępuj zgodnie z poniższym przykładem:
};
W swoim kodzie nazwij to tak:
źródło
Używam PropertyResourceBundle do definiowania kodów błędów w aplikacji korporacyjnej do zarządzania lokalnymi zasobami kodów błędów. Jest to najlepszy sposób obsługi kodów błędów zamiast pisania kodu (może się sprawdzać w przypadku kilku kodów błędów), gdy liczba kodów błędów jest ogromna i uporządkowana.
Więcej informacji na temat PropertyResourceBundle można znaleźć w dokumentacji java
źródło