Twoim głównym błędem jest to, że nadal myślisz w kategoriach proceduralnych. To nie jest krytyka ciebie jako osoby, to tylko spostrzeżenie. Myślenie bardziej funkcjonalnymi terminami wiąże się z czasem i praktyką, dlatego metody są prezentowane i wyglądają jak najbardziej oczywiste, poprawne rzeczy, do których można zadzwonić. Twoim drugorzędnym drobnym błędem jest utworzenie Opcjonalnej w ramach metody. Opcjonalny ma na celu pomóc udokumentować, że coś może, ale nie musi, zwrócić wartość. Możesz nic nie dostać.
Doprowadziło to do napisania doskonale czytelnego kodu, który wydaje się całkowicie rozsądny, ale uwiodły cię podłe, kuszące bliźniaczki, które dostały i są obecne.
Oczywiście szybko pojawia się pytanie „dlaczego są obecne i nawet się tam dostać?”
Wielu ludzi tutaj tęskni za tym, że isPresent () jest to, że nie jest to coś, co zostało stworzone dla nowego kodu napisanego przez ludzi w pełni zaangażowanych w to, jak cholernie przydatne są lambdas i którzy lubią funkcjonalność.
Daje nam jednak kilka (dwóch) dobrych, wspaniałych, uroczych (?) Korzyści:
- Ułatwia przejście starszego kodu w celu korzystania z nowych funkcji.
- Ułatwia krzywe uczenia Opcjonalne.
Pierwszy jest raczej prosty.
Wyobraź sobie, że masz interfejs API, który wyglądał tak:
public interface SnickersCounter {
/**
* Provides a proper count of how many snickers have been consumed in total.
*/
public SnickersCount howManySnickersHaveBeenEaten();
/**
* returns the last snickers eaten.<br>
* If no snickers have been eaten null is returned for contrived reasons.
*/
public Snickers lastConsumedSnickers();
}
I miałeś klasę klasyczną, używając tego jako takiego (wypełnij puste pola):
Snickers lastSnickers = snickersCounter.lastConsumedSnickers();
if(null == lastSnickers) {
throw new NoSuchSnickersException();
}
else {
consumer.giveDiabetes(lastSnickers);
}
Na pewno wymyślony przykład. Ale bądźcie ze mną tutaj.
Java 8 została uruchomiona i staramy się wejść na pokład. Jedną z rzeczy, które robimy, jest zamiana naszego starego interfejsu na coś, co zwraca Opcjonalne. Dlaczego? Ponieważ, jak ktoś już wspominał łaskawie:
eliminuje to zgadywanie, czy coś może być zerowe
. Inni zwracali już na to uwagę. Ale teraz mamy problem. Wyobraźmy sobie, że mamy (przepraszam, gdy nacisnąłem Alt + F7 przy niewinnej metodzie), 46 miejsc, w których ta metoda jest wywoływana w dobrze przetestowanym starszym kodzie, który w przeciwnym razie świetnie sobie radzi. Teraz musisz zaktualizować je wszystkie.
TO jest, gdzie isPresent świeci.
Ponieważ teraz: Snickers lastSnickers = snickersCounter.lastConsumedSnickers (); if (null == lastSnickers) {wyrzuć nowy NoSuchSnickersException (); } else {Consumer.giveDiabetes (lastSnickers); }
staje się:
Optional<Snickers> lastSnickers = snickersCounter.lastConsumedSnickers();
if(!lastSnickers.isPresent()) {
throw new NoSuchSnickersException();
}
else {
consumer.giveDiabetes(lastSnickers.get());
}
Jest to prosta zmiana, którą możesz dać nowemu juniorowi: może zrobić coś pożytecznego, a jednocześnie będzie mógł eksplorować bazę kodów. win-win. W końcu coś podobnego do tego wzoru jest dość rozpowszechnione. A teraz nie musisz przepisywać kodu, aby używać lambd lub czegokolwiek. (W tym konkretnym przypadku byłoby to trywialne, ale zostawiam wymyślanie przykładów, w których byłoby to trudne dla czytelnika).
Zauważ, że oznacza to, że sposób, w jaki to zrobiłeś, jest zasadniczo sposobem radzenia sobie ze starszym kodem bez wykonywania kosztownych przeróbek. A co z nowym kodem?
W twoim przypadku, gdy chcesz po prostu coś wydrukować, po prostu zrobiłbyś:
snickersCounter.lastConsumedSnickers (). ifPresent (System.out :: println);
Co jest dość proste i całkowicie jasne. Problem, który powoli wypływa na powierzchnię, polega na tym, że istnieją przypadki użycia dla get () i isPresent (). Służą do mechanicznej modyfikacji istniejącego kodu w celu użycia nowszych typów bez zbytniego zastanawiania się nad tym. To, co robisz, jest zatem mylone na następujące sposoby:
- Wywołujesz metodę, która może zwrócić null. Prawidłowym pomysłem byłoby to, że metoda zwraca null.
- Używasz starszych metod bandaid, aby poradzić sobie z tym opcjonalnym, zamiast używać smacznych nowych metod, które zawierają wściekłość lambda.
Jeśli chcesz użyć Opcjonalnego jako prostej kontroli bezpieczeństwa zerowego, powinieneś to zrobić po prostu:
new Optional.ofNullable(employeeServive.getEmployee())
.map(Employee::getId)
.ifPresent(System.out::println);
Oczywiście dobrze wyglądająca wersja tego wygląda następująco:
employeeService.getEmployee()
.map(Employee::getId)
.ifPresent(System.out::println);
Nawiasem mówiąc, chociaż nie jest to w żaden sposób wymagane, zalecam użycie nowej linii na operację, aby łatwiej było ją odczytać. Łatwy do odczytania i zrozumienia bije zwięzłość każdego dnia tygodnia.
Jest to oczywiście bardzo prosty przykład, w którym łatwo zrozumieć wszystko, co próbujemy zrobić. W życiu nie zawsze jest to takie proste. Ale zauważ, jak w tym przykładzie wyrażamy nasze intencje. Chcemy UZYSKAĆ pracownika, UZYSKAĆ jego identyfikator i, jeśli to możliwe, wydrukować go. To druga duża wygrana z Opcjonalnym. Pozwala nam tworzyć wyraźniejszy kod. Myślę też, że robienie rzeczy takich jak tworzenie metody, która robi mnóstwo rzeczy, aby można było nakarmić ją mapą, jest ogólnie dobrym pomysłem.