Gdzie rzucić wyjątkiem?

0

Cześć, mam małą rozkminę i nie daje mi to spokoju. Może to ja czegoś nie rozumiem, może ktoś pomoże ;)

Mam dwie klasy

public class Base {
    private Something sth;

    public void something() {
        sth.setVar(22);
    }
}

public class Something {
    private int var;

    public void setVar(int var) {
        if (var > 20) {
            throw new Exception("error");
        }
        this.var = var;
    }
}

oraz maina

public class Main {
    public static void main(String[] args) {
	    Base b = new Base();
	    b.something();
    }
}

I teraz pytanie, gdzie lepiej rzucić wyjątkiem. Czy zależy to od czegoś? Równie dobrze mógłbym w metodzie something to zrobić.. Jest to prosty przykład i może w bardziej zaawansowanej 'apce' mógłbym coś wywnioskować...Czy wyjątek należy rzucać stricte w tej metodzie, gdzie nie może jakaś sytuacja wystąpić, czy może w metodzie sprawdzić czy wartość jest większa od 20 i tam rzucić wyjątkiem?

0

Powinieneś rzucić wyjątkiem w metodzie która operuje na przesłanych przez Ciebie danych- w twoim przypadku będzie to metoda setVar.
Większy problem jest z tym gdzie powinieneś go obsłużyć. W aplikacjach webowych z reguły wyrzuca się wyjątki niekontrolowane i obsługuje w ExceptionHandler.

1

Albo nie rzuca się wcale, tylko zwraca wynik który mówi o tym że coś się nie powiodło (np. przez Either) albo, jeśli to jest faktycznie coś po czym nie da się łatwo podnieść, rzuca się jakiś runtime exception. Wyjątek jeśli już to oczywiście rzucasz tam gdzie wykryłeś błąd.

Generalnie rzucenie wyjątku sugeruje że chcesz to obsługiwać gdzieś dużo dużo wyżej albo ewentualnie że wywalił się konstruktor.

0

Wyrzuć wyjątek w metodzie, która przyjmuje dane wejściowe od Ciebie. W tym przypadku, w metodzie setVar() masz if który sprawdza argument var.

Jeśli będzie niepoprawny, możesz wyrzucić​ najlepiej jakiś Unchecked Exception np IllegalArgumentException.
Poczytaj o dobrych praktykach wyjątków w Clean Code ;)

0

Generalnie @Shalom pisze prawdę - ale nie całą. Wyjątki checked sa passe i to nieudany ekpseryment Javy.
Czyli albo zdarza się coś w stylu "cholera cały system nie działa i nic nie poradzę" - wtedy rzucasz RuntimeException.
Ale u Ciebie tu chodzi o walidację parametrów... wtedy ..

no kurde nie może być tak, że setVar zwraca void - co to kurde jest void? znaczy, że nic nie robi metoda? Wywal ją :-)
Lepiej jak zrobisz cos w tym stylu:

public Either<Error, Something > setVar(int var) {
        if (var > 20) {
            return Either.left( new WrongValueError(var));
        }
        return Either.right( new Something(var));
    }

Takie podejście zmniejsza błędogenność i ułatwia testowanie.

0

No dobra, ale co kiedy korzystamy z czystej Javy? Tam nie ma Either. Korzystamy z Optional i wywołujemy orElse()?
Może zróbmy na szybko taką bazę:

  • kiedy przekazać wyjątek wyżej? (deklaracja throws)
  • kiedy ręcznie rzucić wyjątkiem (IllegalArgumentException, NullPointerException [np. w kontruktorze])
  • kiedy rzucić RuntimeException?
  • kiedy zwrócić wartość defaultową?
0

Nie będę zakładał nowego wątku, usmażę dwie pieczenie na jednym ogniu ;)

Chciałbym mieć taką sytuację, gdzie mam jakąś klasę i fabrykę, która zwraca obiekt tej klasy, ale chciałbym, żeby tylko poprzez fabrykę (statyczną metodę) była możliwość utworzenia nowego obiektu. Czy jest to w ogóle możliwe? Próbowałem zrobić zagnieżdżenie, i bawić się modyfikatorami dostępu, ale albo da się zwrócić obiekt poprzez fabrykę i poprzez konstruktor, albo wcale...

0

Wyjątki checked sa passe i to nieudany ekpseryment Javy.

Nibyż to czemu?

0
scibi92 napisał(a):

Wyjątki checked sa passe i to nieudany ekpseryment Javy.

Nibyż to czemu?

Według mnie, to checked wyjątki są okej, ale jeśli są bardzo "na dole" - jak otwieramy te połączenie SQLowe albo jakiś stream z/do pliku. Ale wyżej, w logice biznesowej, wymóg obsłużenia wyjątku jest męczący (jeśli sporo metod serwisowych by takowe rzucało)

0

@Smutny Rycerz prywatny konstruktor? ;)
@scibi92 w javie 1.7 to jeszcze jakoś szło, ale w javie 8 to można dostać białej gorączki jak chcesz gdzieś wrzucać method reference zamiast lambdy i protestuje że metoda rzuca wyjątkami ;) Ale generalnie jak rzucasz checked exception to zwykle chcesz go obsługiwać gdzieś bardzo blisko, a to znaczy ze równie dobrze można to zrobić Optionalem czy Either.
@Pinek jw, skoro chcesz obsługiwać to od razu to czemu wyjątek a nie Optional?

Z braku lepszych alternatyw mam zwykle w projekcie własne functional interface które są klonami tych standardowych function, supplier, consumer tylko że deklarują rzucanie wyjątku, więc jak nie mogę tego rzucania zmienić to przynajmniej nadal mogę gdzieś to sobie lambdować.

0
Shalom napisał(a):

@Pinek jw, skoro chcesz obsługiwać to od razu to czemu wyjątek a nie Optional?

@Shalom Chodzi mi o wytłumaczenie istnienia w JDK checked wyjątków, bo napisałeś wcześniej że w ogóle wszędzie są skopane ;) a raczej się dotychczasowych metod do tego nie zmieni. A ja osobiście zawsze rzucam RuntimeException jak już ;)

1

Wyjątki checked istnieją bo kiedyś się to wydawało dobrym pomysłem. Ale ... jakoś ten dobry pomysł nie działa dobrze. 98 % (przyznaje, że z d**y liczba) obsługi wyjatków checked w programach Java to bzdurny rethrow albo jeszcze gorzej - połknięcie wyjątku.

0

@Shalom: no faktycznie, jak na ironie to akurat dzisiaj chciałem monadę ale nie mogłem bo przy mapowaniu był checked exception. Ale na szczęście to bardzo rzadko się zdarza, ostatni raz taki problem miałem kilkaset dni temu :)

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