Czy dobrą praktyką jest używanie ostrzeżeń pomijanych w kodzie?

11

Używam @SuppressWarnings("unchecked")i @SuppressWarnings("null")głównie powyższych metod, aby umożliwić kompilację kodu bez ostrzeżeń, ale mam wątpliwości. Znaleziono to pytanie Stackoverflow . Jon Skeet napisał odpowiedź , która wydaje mi się intrygująca.

Według niego,

Czasami ogólne elementy języka Java po prostu nie pozwalają ci robić tego, co chcesz, i musisz skutecznie powiedzieć kompilatorowi, że to, co robisz, będzie legalne w czasie wykonywania.

Ale co, jeśli istnieje szansa, że ​​zostanie zgłoszony wyjątek? Czy więc tłumienie ostrzeżeń nie jest złym pomysłem? Czy nie powinienem zdawać sobie sprawy z miejsc, w których mogą pojawić się problemy?

A co, jeśli ktoś inny zmodyfikuje mój kod później i doda wątpliwą funkcjonalność bez usuwania SuppressWarnings? Jak można tego uniknąć i / lub czy istnieje jakaś inna alternatywa?

Czy powinienem używać @SuppressWarnings("unchecked")i @SuppressWarnings("null")?


Aktualizacja nr 1

Jeśli chodzi o rzutowanie typu niezaznaczonego, zgodnie z tą odpowiedzią (wskazaną przez @gnat w komentarzach poniżej) konieczne jest ukrycie tych ostrzeżeń.

Wiele niezbędnych bibliotek Java nigdy nie zostało zaktualizowanych w celu wyeliminowania potrzeby tworzenia niebezpiecznych typecastów. Tłumienie tych ostrzeżeń jest konieczne, aby inne ważniejsze ostrzeżenia zostały zauważone i poprawione.

W przypadku zniesienia innych ostrzeżeń nadal znajduje się w nieco szarym obszarze.


Aktualizacja nr 2

Zgodnie z dokumentami Oracle Docs (wspomnianymi również w niektórych odpowiedziach poniżej):

Ze względu na styl programiści powinni zawsze używać tej adnotacji na najgłębiej zagnieżdżonym elemencie, gdzie jest skuteczny. Jeśli chcesz ukryć ostrzeżenie w określonej metodzie, powinieneś opisać tę metodę, a nie jej klasę.

Bilesh Ganguly
źródło
@gnat Nie rozmawiają o odlewach niezaznaczonych‽
Bilesh Ganguly
1
robią : „Wiele niezbędnych bibliotek Java nigdy nie zostało zaktualizowanych w celu wyeliminowania potrzeby tworzenia niebezpiecznych typów czcionek. Tłumienie tych ostrzeżeń jest konieczne, aby inne ważniejsze ostrzeżenia zostały zauważone i poprawione”.
komar
2
Myślę, że problem z tym duplikatem polega na tym, że chodzi o C # - istnieją pewne specyficzne dla Javy przyczyny, które różnią się od ogólnej idei tłumienia ostrzeżeń kompilatora.

Odpowiedzi:

26

Dla mnie głównym celem tłumienia ostrzeżeń jest utrzymanie „czystej karty zdrowia” dla twojego projektu. Jeśli wiesz, że cała podstawa kodu kompiluje się czysto, natychmiast staje się oczywiste, gdy ktoś zrobi coś złego, co spowoduje pojawienie się pierwszego ostrzeżenia na liście problemów. Następnie możesz naprawić błąd lub go pominąć, jeśli możesz udowodnić, że jest fałszywy.

Ale jeśli masz na początku 21 ostrzeżeń, o wiele bardziej prawdopodobne jest, że przeoczysz 22. ostrzeżenie, gdy ktoś je spowoduje, i nie sprawdzisz, czy jest nieszkodliwe. Oznacza to, że problemy mogą wkraść się do twojej bazy kodu i nigdy tego nie zauważysz.

Ostrzeżenia to przydatne informacje. Uważaj na tych, którzy mówią prawdę, i odfiltrowuj tych, którzy nie mówią. Nie pozwól ludziom łączyć tych dwóch rodzajów, abyś stracił swój system wczesnego ostrzegania.

Edytować

Powinienem chyba wyjaśnić, że tłumienie ostrzeżenia, które ma sens, jest głupotą. Czysta karta zdrowia uzyskana przez oszustwo jest oczywiście bezwartościowa. Biorąc pod uwagę wybór, zawsze powinieneś naprawić problem zauważony przez kompilator, a nie tylko zamknąć na niego oczy. Istnieją jednak obszary, w których kompilator nie może być pewien, czy coś będzie stanowić problem, czy nie (generyczne elementy Javy są jednym z takich obszarów), i tam lepszym wyborem jest przejrzenie każdej takiej instancji, a następnie zniesienie ostrzeżenia w tym konkretnym miejscu niż całkowite wyłączenie tej klasy ostrzeżeń i potencjalne pominięcie prawdziwej.

Kilian Foth
źródło
1
Zgadzam się częściowo, że począwszy od „czystej” tabliczki pomaga złapać późniejsze ostrzeżenia, faktem jest, że kod, który kompiluje się poprawnie, może nie działać poprawnie.
user949300
Problem, który mam w pracy polega na tym, że często spotykam się z ostrzeżeniami, które ktoś tłumił, ponieważ nie rozumieli, co on mówi. Sądzę więc, że ostrzeżenie ma sens, jest sprawą subiektywną. : /
Trejkaz
16

Tłumienie ostrzeżeń należy wykonywać z najwyższą ostrożnością.

Ostrzeżenie oznacza: kompilator znalazł coś, co wygląda podejrzanie. Nie oznacza to, że jest podejrzany, po prostu wygląda to na kompilator. Czasami masz kod, który jest w porządku i daje ostrzeżenie. Czasami naprawiasz to przez nieznaczną modyfikację kodu. Czasami kompilator ma jakąś funkcję specjalnie do tego celu. Na przykład gdzie

if (x = someFunction ()) { ... }

daje ostrzeżenie, ale

if ((x = someFunction ())) { ... }

nie. W pierwszym przypadku ostrzeżenie, że prawdopodobnie miałeś na myśli == a nie =. W drugim przypadku brak ostrzeżenia, ponieważ dodatkowe nawiasy mówią kompilatorowi „Wiem, co robię”. Lepiej byłoby oczywiście

if ((x = someFunction ()) != 0) { ... }

lub używając dwóch linii.

Czasami bardzo rzadko zdarzają się przypadki, gdy Twój kod jest w porządku, ale nie możesz napisać go w sposób zaakceptowany bez ostrzeżenia. W tym bardzo rzadkim przypadku wyłączasz ostrzeżenie dla tego oświadczenia i włączasz je natychmiast potem. To ostateczność. Wyłączasz tylko to ostrzeżenie, żadnych innych.

Jednak niektóre osoby po prostu wyłączają ostrzeżenia, aby pozbyć się ostrzeżeń, ponieważ są zbyt leniwe, aby najpierw znaleźć i ustalić przyczynę uzasadnionego ostrzeżenia. Lub nawet nie próbują pisać kodu wolnego od ostrzeżeń. To bardzo niezdrowa rzecz do zrobienia.

gnasher729
źródło
2
Myślę, że w drugim i trzecim przykładzie brakuje ci nawiasu zamykającego.
8bittree,
1
Idealnie zgodził się z ostatnim zdaniem
usr-local-ΕΨΗΕΛΩΝ
7

Pomijanie ostrzeżenia dla całej metody jest podejrzane. Lepiej ukryć ostrzeżenia dla określonej linii z komentarzem . na przykład

@SuppressWarnings("unchecked") Foo foo = (Foo)object; // Using old library requires this cast

użytkownik949300
źródło