Pułapki transakcji Springa dla programistów Kotlina

Wydaje się, że Spring i Kotlin to dobre połączenie. Z jednej strony najbardziej popularny framework dla Javy, ale deklarujący wsparcie dla języka od JetBrains. Z drugiej Kotlin został zaprojektowany dla jak największej kompatybilności z Javą. Na papierze i w ogłoszeniach na social mediach wszystko gra. Tyle że w rzeczywistości można bardzo nieprzyjemnie się zaskoczyć, niestety zazwyczaj dopiero na produkcji.

Problem będący głownym bohaterem tego artykułu leży w różnym podejściu do wyjątków w obu światach.

Pisząc w Kotlinie można zapomnieć o dyskusjach programistów Javy, czy wyjątek ma być checked czy nie. Jeśli w repozytorium piszemy wyłącznie w jednym języku, wszystko nam jedno i nie trzeba sobie tym zawracać głowy. Chyba że kod działa w Springu. Wtedy brak uwagi kończy się zobaczeniem UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only. Zgodnie ze słowami 'unexpected’ i 'silent’, jest to sytuacja zaskakująca, a do tego upierdliwa w zdiagnozowaniu.

Czytaj dalej „Pułapki transakcji Springa dla programistów Kotlina”

Funkcyjna obsługa błędów w Kotlinie i Javie

Czasem obsługa błędów jest prosta, „zerojedynkowa”: albo operacja się powiedzie, albo rzuci wyjątkiem. Mamy jednak też sytuacje, gdy od strony biznesowej podejście „wszystko albo nic” nie ma sensu i oczekiwane jest działanie w trybie „best effort”. Na wejściu jest zestaw danych, wykonujemy na nich operacje, jeśli w trakcie pojawiają się błędy, to po prostu idziemy dalej i próbujemy doprowadzić do końca tak wiele, jak się da, nie wycofując się z niczego. Nie mówimy o beztroskim ignorowaniu błędów: nawet jeśli zgadzamy się na częściowe niepowodzenie, dobrze jest wiedzieć, które z danych były przetworzone pomyślnie, a które z błędem. Jak zaprogramować takie podejście w sposób czytelny i jasno przekazujący intencję?

Imperatywne podejście (try-catch) w naturalny sposób modeluje sytuację zerojedynkową. Żeby zamodelować wersję „best effort” musimy myśleć w sposób bardziej funkcyjny, potraktować zarówno operację do wykonania jak i błąd jako byty na równi z danymi. Będziemy „kolekcjonować” błędy, żeby móc później zanalizować, ile ich było.

Języki nastawione na programowanie funkcyjne ułatwiają tu sprawę, ponieważ mają sprawdzone i dobrze opisane rozwiązania. Przykładowo Scala ma w bibliotece standardowej typ Try. Kotlin i Java nie są językami tradycyjnie wykorzystywanymi w sposób funkcyjny — nie oznacza to, że nie da się działać w nich w analogiczny sposób, jedynie to, że może być trudno znaleźć odpowiedź, jak do tego podejść.

Czytaj dalej „Funkcyjna obsługa błędów w Kotlinie i Javie”
Creative Commons License
Except where otherwise noted, the content by Piotr Kubowicz is licensed under a Creative Commons Attribution 4.0 International License.