Rzucanie nulli w Kotlinie

Odpowiedz Nowy wątek
2019-05-09 12:51
eL
0

W Javie żeby nie rzucać nullami i łatwiej je przetwarzać powstała klasa Optional. W Kotlinie takiej klasy nie ma i by default wszystko jest null safety. Czasami jednak zdarza się że chcemy pobrać jakąś wartość (np. z bazy) której nie ma. Oczywiście możemy rzucać Either i inne tego typu pokroju obiekty ale pytanie czy rzucanie nullem w Kotlinie ma sens? Jakby tak podejść do tematu generycznie to pewnie jest to bezsensu bo null to nadal null ale z drugiej strony w kotlinie przetwarzanie nulli w stylu np.:

    value?.let { doSomething } 

jest poniekąd podobne do tego co robimy z Optionalem w Javie (np. map).

Pytanie więc. Rzucanie nulli w Kotlinie jest akceptowalne czy raczej bee?

Pozostało 580 znaków

2019-05-09 13:33
0

Ja bym powiedział, że dopóki nie używasz non-null assertion w kodzie (!!) i nie masz wielokrotnie zagnieżdżonych let albo innych dziwnych baboli, to jest ok. Jak zaczyna się robić gmatwanina z powodu obsługi nulli to wtedy nie ma wyjścia, refaktor żeby to uprościć.

W sumie najgorzej jest, gdy jakaś biblioteka Javowa pakuje nulle do typu non-null przez refleksje. Wtedy toto już nawet NPE nie rzuca.


Prosząc o pomoc w wiadomości prywatnej odbierasz sobie szansę na otrzymanie pomocy od kogoś bardziej kompetentnego :)

Pozostało 580 znaków

2019-05-09 13:37
1

Kotlinowe ? to po prostu odpowiednik Optional z javy, tylko lepsze. Poza tym zobacz ze tu sytuacja jest zupełnie odwrotna niz w javie. W javie jesli widzisz ze metoda zwraca Object to spodziewasz się dostać Object a czasem niespodziewanie dostaniesz nulla. Jesli masz Optional to wiesz ze mozesz miec "null". W kotlinie domyślnie nie mozesz miec null więc na pewno dostaniesz Object. Jeśli w sygnaturze masz Object? no to z góry wiesz, że musisz to obsłużyć (kompilator Ci chyba nawet nie pozwoli inaczej).

Więc podsumowując: używanie null w kotlinie to tak na prawdę dziania podobne jak używanie Optonal. No chyba, że każda metoda zwraca ? no ale to juz lekka patologia


Spring? Ja tam wole mieć kontrole nad kodem ᕙ(ꔢ)ᕗ
Kompilator strzela blachę w potylicę za nieobsłużenie nullable :] - superdurszlak 2019-05-09 14:12

Pozostało 580 znaków

2019-05-09 13:38
0

Niestety nie rozumiem stwierdzenia "Rzucanie nulli". Czy masz na myśli rzucanie wyjątku NullPointerException czy przepychanie nulla jako wartość?
Według paradygmatu programowania fukcyjnego rzucanie wyjątków jest złe. Więc jeśli chcesz przepychać nulla możesz albo użyć notacji ze znakiem zapytania (jak w twoim przykłądzie) albo użyć bibliotekę Arrow-kt zawierającą klasę Option.
Dobrze użyta biblioteka Arrow-kt robi z Kotlina funkcyjny język podobny do Haskella. Rezultat jest podobny do użycia bibliotek ScalaZ/Cats dla Scali.


Pokaż pozostałe 15 komentarzy
@Krolik: chciałby tu jeszcze dodać, że osobiście wolę pisać w Scali, ale IMO wielu Scalowców nie widzi , że kotlin bywa blisko Scali. Jak ktoś nie jedzie ostro po type systemie i nie programuje czysto, to na kiego grzyba mu ta Scala? Naprawdę takie bazowe FP jakie daje kotlin to już nieźle. I z drugiej strony to dużo więcej niż to co jest w javie - bo to nie chodzi o lambdy tylko o wspomaganie immutable. A to kotlin robi całkiem nieźle. Widziałem dużą zmianę w javowcah po przejściu na kotlin. Generalnie język - straszny kompromis, ale naprawdę nie jest taki zły. - jarekr000000 2019-05-13 19:50
Ten dotty null podoba mi się bardziej od Kotlinowego. Już tu narzekałem, że wkurza mnie tego T? wyjątkowość / jednorazowość. Załatwienie problemu przez union type jest dużo bardziej generyczne i eleganckie. - jarekr000000 2019-05-13 19:52
To prawda, że Kotlin bywa blisko Scali (trudno żeby nie, jeśli ściągnął połowę ficzerów) i w sumie też wolałbym programować w Kotlinie niż w czystej Javie, jeżeli nie mógłbym w Scali. Jednak pod względem zaawansowania systemu typów czy właśnie rozwoju dziedziny to jednak Kotlin obok Scali nie stał (mam na myśli właśnie implicity czy makra; które są naprawdę potężnymi mechanizmami, tylko oczywiście trzeba się nauczyć z nich odpowiedzialnie korzystać). Te języki mają zupełnie inną filozofię: Scala stara się być minimalistyczna i abstrakcyjna, Kotlin idzie w specjalizację. - Krolik 2019-05-14 09:41
tylko oczywiście trzeba się nauczyć z nich odpowiedzialnie korzystać to akurat byłaby potężna wada. Bo dlatego właśnie nie korzystam z C++ już. Templatami można było wiele... tylko trzeba było odpowiedzialnie, nawet wskaźniki miały jakieś marginalne zastosowanie. Ale jednak za dużo ludzi z tego korzystało->nieodpowiedzialnie. W Scali IMO jest dużo lepiej - implicity to chłopaki do bicia, i ciągle Oderski chce poprawić (co to ma być w dotty w końcu ?instance ? :-) ). Ale faktycznie zwykle najgorsza rzecz co się zdarza to kryptyczny błąd kompilacji. Spoko 1/2 - jarekr000000 2019-05-14 17:21
Lepiej mieć kryptyczny błąd kompilacji niż heisenbug na produkcji. Makra też idealne nie są i też w dotty mają być zmiany. Zaletą Scali jest to, że faktycznie nie trzeba sie prawie nigdy do makr zniżać. IMO w Haskellu jest więcej rzeczy robionych na TemplateHaskell (koncepcyjnie podobne do scalowych makra, ale nie znam się dobrze - jednych i drugich ciągle udaje i się unikać (w pisaniu, korzystam biernie)). 2/2 - jarekr000000 2019-05-14 17:26

Pozostało 580 znaków

2019-05-09 14:29
3

Wg mnie, wykorzystywanie null w jakiejkolwiek logice powinno być uznawane za bad design.

Jeśli Ci się chce, zerknij sobie tu (lub znajdź sobie jakieś streszczenie tej prezentacji) - Tony Hoare - Null References: The Billion Dollar Mistake.

edytowany 1x, ostatnio: catom, 2019-05-09 14:30

Pozostało 580 znaków

2019-05-09 14:45
0

@catom: tylko jak w kotlinie masz metodę która zwraca Object? i zwrócisz tam null to jest to odpowiednik metody javowej w która zwraca Optional<Object> i zwracasz Optional.empty() Po prostu inna składnia


Spring? Ja tam wole mieć kontrole nad kodem ᕙ(ꔢ)ᕗ

Pozostało 580 znaków

2019-05-09 15:09
2
danek napisał(a):

Kotlinowe ? to po prostu odpowiednik Optional z javy, tylko lepsze.

Nie jestem tego 100% pewny. Rozpatrywane w izolacji T? jest ładniejsze od Optional<T>.
Ale fakt, że mamy jeszcze Either<E,T>, Try<T>, Future<T> i tony innych M<T> powoduje pytanie czy nie lepiej by było gdyby była składnia do obsługi dowolnych M<T> (poodstawa to tzw. do notation ).
Możliwe, że będą sobie pluć w brodę za jakiś czas.

Z drugiej strony nie jestem też pewny, że wybrali złe rozwiązanie. Po prostu widzę problem, ale nie wiem jak z tego wybrnąć dobrze i praktycznie. Ich rozwiązanie jakoś działa, ale poza obsługą nulli z javy i framorków nie stosuję T? tylko Option<T>. Co więcej nie mam przekonania, że dobrze robię...
(ale drażnią mnie trochę takie wyjątki w języku).


Bardzo lubie Singletony, dlatego robię po kilka instancji każdego.
edytowany 2x, ostatnio: jarekr000000, 2019-05-09 15:17
jeśli ma się dostępne Either, Try itp to wygodniej korzystać z nich, gorzej jak się ich nie ma :< - danek 2019-05-09 15:49

Pozostało 580 znaków

2019-05-09 15:40
0

Odpowiem z perspektywny Androida, ale wydaje mi się, że pasuje to do wszystkich frameworków. Rzeczy typu !! albo requireNotNull() powinny być używane tylko wtedy, kiedy framework za nas coś tworzy, przekazujemy potem tam jakiś parametr i w pewnym momencie chcemy go użyć, a jego brak oznaczałby błąd programu. Wtedy !! wywala nam apkę i od razu pokazuje, gdzie mamy błąd, który musimy naprawić. Czasami może być to błąd frameworka, więc trzeba go zgłosić i tymczasowo korzystać z jakiegoś obejścia do czasu naprawy. W normalnym kodzie uważam, że nigdy nie powinno wystąpić !! czy requireNotNull().

catom napisał(a):

Wg mnie, wykorzystywanie null w jakiejkolwiek logice powinno być uznawane za bad design.

Jeśli Ci się chce, zerknij sobie tu (lub znajdź sobie jakieś streszczenie tej prezentacji) - Tony Hoare - Null References: The Billion Dollar Mistake.

Nie zgadzam się z tym popularnym stwierdzeniem. null sam w sobie nie jest problemem. Problemem jest niemożność rozpoznania nulla na etapie kompilacji przez większość języków. Jeśli mamy brak wartości, to śmiało możemy używać nulli, jeśli pozwala nam na to system typów i ma to sens z perspektywy modelowania.

jarekr000000 napisał(a):

Z drugiej strony nie jestem też pewny, że wybrali złe rozwiązanie. Po prostu widzę problem, ale nie wiem jak z tego wybrnąć dobrze i praktycznie. Ich rozwiązanie jakoś działa, ale poza obsługą nulli z javy i framorków nie stosuję T? tylko Option<T>. Co więcej nie mam przekonania, że dobrze robię...
(ale drażnią mnie trochę takie wyjątki w języku).

Ja mam w drugą stronę. Stosuję T? a wydaje mi się, że bardziej eleganckie byłoby Option<T>. Na Androidzie mogę sobie jeszcze to tłumaczyć tym, że khem, kehm wydajność, ale to trochę oszukiwanie samego siebie. Option<T> ma natomiast ogromną przewagę w przypadku korzystania z Reactive Streams. Specyfikacja tego po prostu zabrania i choćbym nie wiadomo jak tego chciał, to muszę to opakować w jakiś kontener. Z drugiej strony teraz pojawiło się Flow w Kotlinie, więc pewnie będzie za jakiś czas de-facto standardem i problem zniknie.

edytowany 3x, ostatnio: Michał Sikora, 2019-05-09 15:50

Pozostało 580 znaków

2019-05-11 15:42
1
Michał Sikora napisał(a):

Jeśli mamy brak wartości, to śmiało możemy używać nulli, jeśli pozwala nam na to system typów i ma to sens z perspektywy modelowania.

Jeśli mamy brak wartości, to zdecydowanie wolę to jawnie zakomunikować używając monady maybe / option. Oczywiście, nie czepiałbym się nulli w np. RDBMS, ale przy mapowaniu ich struktur na odpowiednie struktury języka obiektowego / funkcyjnego, zdecydowanie wolę, gdy wszystkie nullowalne wartości jawnie to w takim języku deklarują.

Aż mi się przypomniał jeden projekt, który miałem przyjemność utrzymywać, gdzie co 5 linii było wyrażenie typu if(service.calculateSomething(attribute) != null) {...} itd. Analiza takiego kodu naprawdę nie należy do najprzyjemniejszych.

edytowany 3x, ostatnio: catom, 2019-05-11 15:44

Pozostało 580 znaków

2019-05-11 15:46
0

Aż mi się przypomniał jeden projekt, który miałem przyjemność utrzymywać, gdzie co 5 linii było wyrażenie typu if(service.calculateSomething(attribute) != null) {...} itd. Analiza takiego kodu naprawdę nie należy do najprzyjemniejszych.

A czy był to język, który pozwalał na rozpoznawanie nulli w typie?

edytowany 1x, ostatnio: Michał Sikora, 2019-05-11 15:47

Pozostało 580 znaków

2019-05-11 18:00
0

Właśnie kotlin po przez ? sygnalizuje możliwość nulla


Spring? Ja tam wole mieć kontrole nad kodem ᕙ(ꔢ)ᕗ

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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