Optionale są terminem z FP.
Nie są terminem z FP, ale są z FP bardzo kojarzone. Przede wszystkim w FP mamy typy wyższych rzędów oraz metody na nich operujące, więc potrzebujemy typów które można zagnieżdżać. Dla przykładu możemy mieć metodę flatten
która spłaszcza monady, z M<M<A>>
robi M<A>
czyli np z List<List<String>>
robi List<String>
, a z Optional<Optional<String>>
robi Optional<String>
. Nullable types się tutaj nie sprawdzą, bo nie ma wspólnego mianownika między nullable-types a kolekcjami czy innymi monadami. Nie ma String??
którego dałoby się spłaszczyć do String?
.
Jak zapisujesz coś do DB, to to jest bardzo nie FP.
Jeżeli nie robisz żadnych efektów ubocznych to program efektywnie nic nie robi :] W FP efekty uboczne są, ale zawsze opakowane w coś.
Jeśli opierasz program o monady IO (tzn każdy efekt uboczny opakowujesz w monadę IO) to oczywiście musisz te wszystkie monady z sobą spiąć (flatMapem/ bindem zwykle) i zwrócić z metody, a potem pchać do góry aż do metody wejściowej.
Pytanie jak bardzo chcesz iść w "czystość" FP. Jeśli chcesz cały program oprzeć o monady IO to będziesz pisał Haskella w Javie. Bardziej opłaca się pisać Haskella w Haskellu. W językach które mieszają paradygmaty funkcyjne i obiektowe najlepiej jest rozdzielić kod imperatywny od kodu funkcyjnego, czyli mieć szeroki zbiór klas niemutowalnych (i bez efektów ubocznych) oraz część klas, które zarządzają wewnętrznym mutowalnym stanem i wywołują też inne efekty uboczne. W Scali bardzo często takim miejscem na efekty uboczne jest Akkowy aktor, który ma szereg fajnych właściwości - jednowątkowe przetwarzanie wiadomości w obrębie jednego aktora (a więc odpada sporo zabawy z synchronizacją), wiele aktorów działających naraz, hierarchiczna obsługa błędów, bardzo silna enkapsulacja (trzeba się sporo natrudzić i nahakować by z ActorRefa dostać się do lokalnej instancji aktora o ile takowa istnieje), itd
Klasy czysto funkcyjnie nie mogą korzystać z klas imperatywnych, ale klasy imperatywne już mogą i powinny jak najszerzej korzystać z klas czysto funkcyjnych. Czasami może się jednak zdarzyć iż np lokalna mutowalna mapa znacznie upraszcza kod, a efekty uboczne nie są obserwowalne z zewnątrz, więc taka lokalna optymalizacja jest akceptowalna - innymi słowy: nie zawsze warto pisać funkcyjnie tylko dlatego, że się da. Ważne jest jednak by unikać mutowalnego stanu nad którym ciężko zapanować, a więc przede wszystkim globalnego mutowalnego stanu. W Scali dla przykładu używanie niemutowalnych kolekcji jest zwykle przyjemniejsze niż używanie tych mutowalnych, więc to jest świetna zachęta do maksymalizowania funkcyjnej czystości w programie.