Optional - często go używacie?

2

Siema. Interesuje mnie, czy zawsze, w każdym możliwym przypadku NPE używacie Optionala? Czy jednak nie? Jeśli mamy linijkę np

object.getA().getB().getC();

to tych potencjalnych NPE jest sporo, ale użycie Optionala tutaj doda kolejny narzut kodu. Wiadomo, lepiej mieć kilka linijek więcej i mieć gwarancję że akurat NPE nam nie wy3.14eprzy działania programu.

Co też myślicie o następującej sytuacji - mamy sobie publiczną metodę X, która jako argument przyjmuje jakiś skomplikowany obiekt i wewnątrz tej metody jest taki łańcuch getów jak wyżej. Natomiast wiemy doskonale, że tej metody użyliśmy jedynie w 2 -3 miejscach i tam mamy pewność, że obiekt te wszystkie swoje pola i podpola ma. Czy fakt, że do danej metody ma się dostęp w obrębie całej aplikacji, powoduje konieczność "handlowania" potencjalnymi nullami (już pomińmy inne przypadki brzegowe)? Czy też przenosimy odpowiedzialność na użytkownika - wpakował nulla, to dostaje NPE na twarz i elo.

Zachęcam do wypowiadania się @Shalom @jarekr000000 @Koziołek @scibi92 @Krolik @katelx

3

Przykład który podałeś łamie Law of Demeter ;)

0

preferuje uzywanie null object pattern w wiekszosci miejsc gdzie optional moglby byc jakims rozwiazaniem.
btw, imo zwykle robienie czegos takiego jak object.getA().getB().getC() w metodzie swiadczy o innych zlych praktykach np. czemu nie przekazac do metody tego co zwraca getC() zamiast robic taki lancuch wywolan (poza uzywaniem fluent interface, no ale wtedy to raczej ciezko o NPE ;))

3

@Pinek odpowiadajac na pytanei z komentarza, chodzi mi o to ze lepiej wyglada powiedzmy:

class Country {
    private Age adultAge;
    boolean isAdult(Age age) {
        return age.value() >= adultAge.value();
    }
}

niz

boolean isAdult(StaticDataEntry data) {
    return data.getPerson().getAge().value() > data.getPerson().getCountryOfResidence().getAdultAge().value();
}

oczywiscie zamodelowanie aplikacji tak zeby mozliwe bylo uzycie isAdult z przykladu 1) wymaga wiecej wysiku ale zwraca sie wlasnie przy obsludze bledow

2

@Pinek nigdy nie masz pewności że ktoś tam kiedyś da nulla, a jeśli tak postanowi to powinien wtedy automatycznie zmienić sugnaturę metody na Optional i obsłużyć w kodzie przypadek kiedy nie ma wartości. Nie należy wszystkiego opakować Optionalem, bo to bez sensu. Należy dać Optional wtedy kiedy widzimy że możemy / chcemy zwracać "pustą" wartość.
Poza taka wiązanka get.get.get to tragedia i klasyczne przeciekające warstwy/gwałt na enkapsulacji. Jeśli coś takiego występuje to rób delegacje tak żeby finalnie mieć tylko x.get() a reszta ukryta pod spodem.

1

Tutaj nie NPE jest problemem tylko to że nie masz informacji co może być nullem a co nie.

W podejściu:

object.getA().getB().getC();

rozumiem że każdy z tych elementów to po prostu uniwersalny getter wykorzystywany różnie w wielu miejscach i kontekstach.

W podejściu:

object.getCOfBInA(); 

masz w miarę dokładny cel wywołania A i B, w związku z tym możesz określić czy chcesz w tej sytuacji się wywalić "NoDataFound!" czy zwrócić po prostu null (i opisać to w JavaDoc lub zastosować Optional).

0

@vpiotr:

Okej, wszystko co napisałeś jest fajne i zgodne ze sztuką. Ale w praktyce siadasz do projektu w pracy i np masz model z 15 polami, więc już samych getterów/setterów jest 30. A te pola to nie zwykłe prymitywy, tylko kolejne obiekty modelowe. Dołożenie tylu kombinacji spowodowałoby 70-100 metod getterowych w klasie modelu :( I cóż wtedy zaradzić?

0

@Pinek nowy kod pisac juz dobrze, stary powoli zmieniac przy okazji :)

5

Pomijając uwagi jak powyżej to piszem tak:

object.getA().flatMap(a -> a.getB()).flatMap(b ->b.getC()).forEach( c ->  zrobCosTam(c));

i jakoś idzie z tymi optionalami.

A co do nulli - ja tam lubie ludzi częstować NPE jeśli zasłużyli. Dajesz nulla do moje metody to witaj się z NPE.
Jakbym napisał, że przyjmuje nulla to móglbyś dawać (ale przecież bym nie napisał tylko powiedzieł, że argument jest Optional).
Generalnie wszelkiego rodzaju asserty, predykaty sprawdzające czy coś jest nullem akceptuje, czasem robię.
Fajne jest np. Objects.requireNonNull()
Ale najczęściej nie wrzucam nawet takich asercji . (Zależy w jakim kodzie). Bo to z pewnością ułatwia znalezienie błędu, ale z drugiej strony jest to szum informacyjny - potem metoda ma 2 linijki sensownego kodu plus dodatkowe 5 z assertami. Nie warto wszędzie śmiecić.

Wszelkiego rodzaju if( x != null) w logice to już zalążek zła.
No a najgorsze zło, które często spotykam w kodzie różnych firm i "konsultantów" to to:

public T method1(Type arg1)  {
   if ( arg1 != null ) { 
   .... bla bla bla that's just code
  } else {
   return null;
  }
}

Powinien być specjalny krąg piekiełka programistycznego dla tych co tak piszą.

9

U mnie w firmie był szał na Optionale i niestety wyglądało to tak, że były wypchane wszędzie. Na przykład można było się spotkać z takim czymś:

jakisOptional.orElse(null)

Generalnie trzeba używać tego z głową, ale to chyba jak wszystkiego :)

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