Zastosowanie Scali w aplikacjach webowych

0

Cześć!

Zastanawiam się nad zaletami i wadami zastosowania Scali w projektach, które są typowymi aplikacjami webowymi.

Po obejrzeniu kilku świetnych filmików z @jarekr000000 (Dzięki za kawał dobrej wiedzy! :D) zwłaszcza o patologii Spring, Jakarta EE oraz wadach adnotacji, a także w oparciu o własne doświadczenie jak magia Springa może przeszkadzać i dlaczego warto używać Hexagonal architecture/Ports&Adapters itp, pomyślałem o tym jakie moga być potencjalne zalety/wady użycia konkretnej kombinacji języka oraz bibliotek/frameworków do aplikacji webowych.

Obecnie pracuję nad aplikacją webową, w której wykorzystuję Java, Spring Boot, Spring Cloud, a same komponenty są podzielone na mikroswerwisy wg Bounded Context w DDD i oczywiście domena w każdym mikroserwisie jest całkowicie odseparowana od jakiejkolwiek frameworka zgodnie z Hexagonal architecture/Ports&Adapters.

Jakie wady/zalety widzielibyście w przepisaniu aplikacji i ogólnie stosowaniu konkretnych poniższych języków/frameworków do typowych aplikacji webowych, ale które mogą okazać się bardziej skomplikowane niż przysłowiowy CRUD?

  1. Scala + Play do budowy mikroserwisów
  2. Kotlin + Spring Boot
  3. Java + Spring Boot jako najbardziej standardowy tech stack + użycie Vavr, co na pewno da większe możliwości

Zastanawiam się nad przepisaniem całej aplikacji na Scale i całkowitej rezygnacji z Javy i Springa, głównie z powodu tego, że Scala daje potężne możliwości, zwłaszcza jeśli chodzi o functional programming, oraz samym znudzeniem Java.

Jak wygląda zastosowanie Scali/Kotlina w aplikacjach webowych nad którymi pracujecie i czy warto użyć zwłaszcza Scali do pisania aplikacji webowych trochę bardziej skomplikowanych niż zwykły CRUD, poza oczywistymi zastosowaniami typu Big Data i Machine Learning?

Z góry dzięki!

4

Jako programista Scali odradzam bo:

  • Oderski ma w d*** wsteczną kompatybilność
  • Idzie Scala 3 ale jeszcze nie doszła, jak już wskakiwać to w nową
  • Mierna jakość bibliotek, albo są niedorobione albo nawpier*** monad i innych zabawek - fajnie dopóki nie dojdziesz do pierwszego problemu
  • Kompilacja wolna jak diabli, IntelliJ z wtyczką do Scali potrafi się zaciąć lub nie wszystkie refactory działają tak dobrze jak w Javie

Kotlin to w mojej opinii najlepszy teraz wybór. Nawet Gradle dodał opcje opisu buildu w Kotlinie.
Jak nie jesteś przywiązany do Springa to teraz jest sporo konkurentów można więc Kotlin + Mikronaut/Quarkus/coś innego.
Dużo jest teraz tych frameworków, nie ma jeszcze nowego ale Spring wymięka - to co zrobili to przysypali ładnym api syf z wersji 4.0 i sprzedają jako SpringBoot. Ja tego nie kupuje, potrzebna jest świeża krew...

1
mnyozk napisał(a):

Zastanawiam się nad przepisaniem całej aplikacji na Scale i całkowitej rezygnacji z Javy i Springa, głównie z powodu [...] samym znudzeniem Java.

Ktoś (klient) za to zapłaci bo zostanie to poparte czymś więcej jak tylko znudzeniem javą jednego programisty?

0
0xmarcin napisał(a):

Jako programista Scali odradzam bo:

  • Oderski ma w d*** wsteczną kompatybilność
  • Idzie Scala 3 ale jeszcze nie doszła, jak już wskakiwać to w nową
  • Mierna jakość bibliotek, albo są niedorobione albo nawpier*** monad i innych zabawek - fajnie dopóki nie dojdziesz do pierwszego problemu
  • Kompilacja wolna jak diabli, IntelliJ z wtyczką do Scali potrafi się zaciąć lub nie wszystkie refactory działają tak dobrze jak w Javie

Kotlin to w mojej opinii najlepszy teraz wybór. Nawet Gradle dodał opcje opisu buildu w Kotlinie.
Jak nie jesteś przywiązany do Springa to teraz jest sporo konkurentów można więc Kotlin + Mikronaut/Quarkus/coś innego.
Dużo jest teraz tych frameworków, nie ma jeszcze nowego ale Spring wymięka - to co zrobili to przysypali ładnym api syf z wersji 4.0 i sprzedają jako SpringBoot. Ja tego nie kupuje, potrzebna jest świeża krew...

Tak tak, o braku kompatybilności wstecznej w Scali słyszałem, bo sam jej używam, ale nie aż tak często, chociaż powiem Ci, że nigdy nie miałem za bardzo problemów z wtyczką do Scali w Intellij, ale może mam farta po prostu :D
Ta aplikacja to mój projekt więc spokojnie mogę pozbyć się Springa i poeksperymentować ;)

BraVolt napisał(a):
mnyozk napisał(a):

Zastanawiam się nad przepisaniem całej aplikacji na Scale i całkowitej rezygnacji z Javy i Springa, głównie z powodu [...] samym znudzeniem Java.

Ktoś (klient) za to zapłaci bo zostanie to poparte czymś więcej jak tylko znudzeniem javą jednego programisty?

Nie, to mój projekt, po to aby poeksperymentować z nową wiedzą, także śmiało mogę działać z różnymi językami/frameworkami itp, zwłaszcza, że bardzo dobrze nauczyłbym się prawdziwego programowania funkcyjnego, chociaż Haskell jeszcze lepszy do tego ;)

@jarekr000000 @Wibowit Jesteście chyba na forum najbardziej doświadczonymi, którzy mieli okazję ze Scala pracować. Podpowiedzielibyście jakie jest Wasze zdanie? ;)

2

Scala + Play do budowy mikroserwisów

Od lat nie robi się już mikroserwisów na PlayFrameworku, Nie jest to nawet zalecane przez twórców Playa. Play był dedykowany do stron generowanych po stronie backendu (jak RoR) więc teraz to takie niechciane dziecko. Do pisania mikroserwisów polecana jest Akka HTTP (bardzo sprytna biblioteczka robiona przez tą samą firmę co Play). Ewentualnie jak chcesz framework wszystkomający to Lagom (też od nich)

Kotlin + Spring Boot

A czemu takie dziwne połączenie? A czemu taki dziwny półśrodek jeśli masz dość magii Springa? Kotlin ma swoje własne dedykowane biblioteki/frameworki do mikroserwisów. Z czego najpopularniejszy jest chyba Ktor

Po obejrzeniu kilku świetnych filmików z @jarekr000000 (Dzięki za kawał dobrej wiedzy! :D) zwłaszcza o patologii Spring, Jakarta EE oraz wadach adnotacji, a także w oparciu o własne doświadczenie jak magia Springa może przeszkadzać i dlaczego warto używać Hexagonal architecture/Ports&Adapters itp, pomyślałem o tym jakie moga być potencjalne zalety/wady użycia konkretnej kombinacji języka oraz bibliotek/frameworków do aplikacji webowych.

Jak chcesz małomagiczny framework dla Javy do wystawiania RESTa to polecam DropWizarda. Ilość magii ograniczona do minimum

3

Co do Scali - to fajny "zaczyn" dość nowoczesny web/rest w Scali od SoftwareMill
https://github.com/softwaremill/bootzooka

0

Od lat nie robi się już mikroserwisów na PlayFrameworku, Nie jest to nawet zalecane przez twórców Playa. Play był dedykowany do stron generowanych po stronie backendu (jak RoR) więc teraz to takie niechciane dziecko. Do pisania mikroserwisów polecana jest Akka HTTP (bardzo sprytna biblioteczka robiona przez tą samą firmę co Play). Ewentualnie jak chcesz framework wszystkomający to Lagom (też od nich)

Dzięki za uświadomienie, bo nie śledziłem losów Play ostatnio! ;) Co do Akki HTTP, nadawałaby się również do zwyczajnych mikroserwisów, które np. używają bazy danych i łączą się z zewnętrzymi serwisami, żeby pobrać cokolwiek, czy jednak bardziej pod kątem CRUD, Lagom nadaje się do tego, bo ma dużo więcej możliwości pod tym względem np. obsługę i18n (wielojęzykowości), walidacji itp?

Co do Scali - to fajny "zaczyn" dość nowoczesny web/rest w Scali od SoftwareMill
https://github.com/softwaremill/bootzooka

Na pewno sprawdzę, dzięki!

Co do Scali 3, jak widzicie przyszłość Scali w tej wersji? Z tego co widziałem, szykuje się sporo zmian i nowości.

@Shalom Z tego co kojarzę, to działałeś w bardzo poważnych miejscach jak ESA/CERN/ESO :D. Mógłbyś podzielić się wiedzą, jak wygląda właśnie sprawa języków/frameworków, które miałeś/masz okazję tam używać? Zakładam, że Java i Spring na pewno, a jak wyglądała sprawa ze Scalą i Kotlinem. Były używane w projektachw tych miejscach? ;)
Oczywiście zdaję sobie sprawę, że język i narzędzia dobiera się pod kątem rozwiązania problemu czy to biznesowego czy technicznego, ale jestem ciekawy jak to wygląda w takich instytucjach ;)

@jarekr000000 A u Ciebie można spotkać w projektach w wielu miejscach Scalę? W jakich obszarach w projektach ma zastosowanie? Z góry dzięki ;)

2

@mnyozk:

Co do Scali 3, jak widzicie przyszłość Scali w tej wersji? Z tego co widziałem, szykuje się sporo zmian i nowości.

Fajne. Ale tak 3 lata za późno.

Pech polega na tym, że dużo dobrych Scalowców już od dawana pisze w Haskellu.
A dużo słabych Scalowców (np. ja) w Kotlinie :-(
Perspektywa wyjścia nowej niekompatybilnej wersji powoduje, że jeszcze trudniej obecnie kogokolwiek do Scali zachęcić.
(trochę taki Osborne effect).

0

Fajne. Ale tak 3 lata za późno.
Pech polega na tym, że dużo dobrych Scalowców już od dawana pisze w Haskellu.
A dużo słabych Scalowców (np. ja) w Kotlinie :-(
Perspektywa wyjścia nowej niekompatybilnej wersji powoduje, że jeszcze trudniej obecnie kogokolwiek do Scali zachęcić.
(trochę taki Osborne effect).

Pytam tak właśnie o Scalę, dlatego, że podstawy znam, działa na JVM oraz przede wszystkim chciałbym nauczyć się naprawdę dobrze i solidnie paradygmatu funkcyjnego, i chcę również zacząć pisać w Haskellu, ale z tego co widzę, to chyba najlepiej będzie od razu ruszyć z Haskellem a dalszą naukę Scali podarować sobie, zwłaszcza przy nauce progr. funkcyjnego? ;)

To samo jeśli chodzi o stosowanie Scali w apkach webowych z integracją np. z bazami danych i wybranie Kotlina pod ten cel?

0

Ja się właśnie chciałem pouczyć Scali, tym się kierowałem przy ostatnich dwóch zmianach pracy. W poprzedniej firmie (dość znanej i lubianej na forum) padła decyzja, że przepisują na Javę (to był monolit), a w obecnej padła decyzja, że każdy nowy mikroserwis ma być w Rust, kilkadziesiąt scalowych mikroserwisów ma być utrzymywanych "póki jest sens" w Scali, ale właściwie każdy sobie zdaje sprawę, że za chwilę zacznie się przepisywanie w wolnym czasie.

Jestem ciekawy, jak się będą trzymały rzeczy ściśle ze Scalą powiązane - przede wszystkim Spark, ale też Hadoop czy Gatling.

2

Siłą scali jest właśnie ten JVM i to że możesz tony (również javowych) bibliotek użyć. To fakt.
Ale jeśli się chcesz uczyć fp to Haskell zdecydowanie bardziej polecam, głównie dlatego, że:
a) w Haskellu nie ma kompromisów - musi być czysto - w Scali niestety zawsze łatwo oszukać, można mieć zmienne, cichaczem puszczać efekty uboczne
b) są naprawdę fajne materiały do nauki, które na fp się koncentrują, - dużo jaśniej w Haskellu widać sens róznych koncepcji,
(choćby typeclass w Scali - koncept działa, ale jest mocno zaśmiecony składnią, która w sumie do czego innego służyła oryginalnie).

Scala to był długo fajny kompromis (jak wrzucić fp na prodkucje) swego czasu, ale obecnie w Haskellu też zrobisz np. webówke całkiem sensownie.
Co do kotlina: piszę w tym. ... jakby to powiedzieć - to jest taki język dla prostaków. Spoko, sprawdza się, na pewno lepszy od javy wielokrotnie, ale jak poznasz Haskella albo Scalę to będziesz czasem nad tym kotlinem płakać...

0

Zastanawiam się nad przepisaniem całej aplikacji na Scale i całkowitej rezygnacji z Javy i Springa, głównie z powodu tego, że Scala daje potężne możliwości, zwłaszcza jeśli chodzi o functional programming, oraz samym znudzeniem Java.

Haha :)

  1. Rozumiem, ze rozmawiamy o jakimś pet project? Kiedy opłaca się przepisywać CAŁĄ aplikację?
  2. Jakie to potężne możliwości daje Scala, z których chcesz skorzystać?
2

@Charles_Ray:

Jakie to potężne możliwości daje Scala, z których chcesz skorzystać?

Nie wiem co potrzebuje OP, pewnie nawet nie wie czego - z kontekstu rozumiem, że chce się pouczyć i dowiedzieć:
Scala daje kilka dużych powerów w pisaniu aplikacji:
a) Typeclasses - polimorfizm na zupełnie nowym poziomie (kto spróbował tego zwykle klasyczny subclass zaczyna boleć biedą),
b) HKT - można o wiele więcej powtarzalnego kodu wydzielić do bibliotek/utilsów (fakt, że brak tego w kotlinie to boli mnie raz na miesiąc, ale zawsze),
c) for comprehension - czyli można pisać przejrzysty kod reaktywny ( kontra do znanej prezentacji Tomka Nurkiewicza) (i dowolny na monadach), 100 razy lepsza alternatywa od porypanych koruptyn w kotlinie ,
d) całe fp goodies - case class, function types, do tego biblioteka standardowa ma niemutowalne kolekcje (nie wiem jak nawet można pisać kod biznesowy na java.util. - powinno być karalne), (To punkt w którym kotlin + vavr - w zasadzie daje radę)
e) no i najważniejsze - nie ma Springa :-) (choć jest Play, który gdzieniegdzie się plącze jako taki Scalowy, znienawidzony Spring właśnie).

3

O ile Haskell dobrze uczy programowania funkcyjnego (bo stosunkowo trudno się w nim pisze a'la imperatywnie) to Scala dobrze integruje się z ekosystemem Javy, a więc nie tylko wspomnianymi bibliotekami, ale też narzędziami (IDE od JetBrains, profilery, debuggery, wzbogacanie bajtkodu do różnych celów, np pokrycia testami, etc), a sama platforma Java ewoluuje i taki np Project Loom https://openjdk.java.net/projects/loom/ może sporo namieszać w dziedzinie pisania kodu wielowątkowego (a przynajmniej porównywalnie z tym co namieszał Golang).

Pracuję od kilku lat w projekcie Scalowym opartym o mikroserwisy i widzę, że sprawdzają się jeśli chodzi o ułatwienie migracji na nowy stos technologiczny. Trzeba tylko pamiętać by nie wkopać się w binarne protokoły (jak np Akka Remote, obecnie jawnie opisywana jako narzędzie niskopoziomowe i odradzana w używaniu bezpośrednio w kodzie biznesowym), co zrobili poprzednicy po których odziedziczyliśmy projekt. W nowych mikroserwisach ograniczamy się do RESTa i Kafki, a w obu przypadkach serializacja jest niezależna od wersji Javy, Scali, bibliotek itd RESTem i Kafką można spokojnie integrować nawet mikroserwisy napisane w różnych językach (i to też miejscami robimy, chociaż to jest tylko integracja z Javowymi wynalazkami, więc niespecjalnie odległe technologicznie).

Jeśli chodzi o kompatybilność wsteczną w Scali to z dekady na dekadę następuje pewne zwiększenie jej priorytetu. Przygodę ze Scalą zacząłem gdzieś od Scali 2.10, gdzie kompatybilność jest na poziomie średniej wersji, w sensie 2.10.x jest binarnie kompatybilna z 2.10.y. Wcześniej podobno było gorzej, tzn 2.9.1 była niekompatybilna binarnie z 2.9.2 i trzeba było wszystko przekompilować. W Scali 3 kompatybilność wsteczna ma być zwiększona, jeśli dobrze pamiętam. Wydaje mi się, że założenie jest takie, że kompilator Scali 3.(x+1) powinien być w stanie korzystać z bibliotek kompilowanych kompilatorem Scali 3.x. To byłby i tak spory postęp, bo teraz w przypadku wyjścia nowej wersji Scali (w sensie nowych ficzerów, a nie nowych łatek) jest sporo czekania, aż zależności zostaną przekompilowane pod nową Scalę, nawet jeśli te zależności są nadal utrzymywane.

1

Co do kompatybilności:
W Scali powstaje fajny tool:
https://github.com/propensive/fury

Build tool oparty o zależności do kodu źródłowego. Wiele innych języków już to robi (choćby haskell - hackage - cabal/stack). Bo przekompilowanie jest ogólnie dość prostym sposobem na kompatybilność.
Kłopot tak, że ten fury też pojawi się za późno. Gdbyby wszedł do użytku 3 lata temu to można by liczyć na bezproblemową migrację projektów... Teraz nikt raczej nie będzie migrował się do nowego (niewygrzanego) build toola przy okazji migracji na Scalę 3.

IMO kiedyś w javie też się możemy kiedyś na zależności od źródeł przestawić - bo Unsupported major. minor version zacznie za bardzo boleć. (zobaczymy).

0

Rozumiem, ze rozmawiamy o jakimś pet project? Kiedy opłaca się przepisywać CAŁĄ aplikację?
Jakie to potężne możliwości daje Scala, z których chcesz skorzystać?

Tak tak, jasne, że pet project ;) Ciężko byłoby przepisać np. taki cały system bankowy czy tradingowy bez uwzględnia czasu i kosztów haha :D
Chciałbym zwyczajnie bardzo dobrze nauczyć się FP i innego podejścia oprócz budowania apek webowych i mikroserwisów przy pomocy Javy i Springa zacząć korzystać z funkcji, które @jarekr000000 wymienił ;)

@Wibowit Dzięki za obszerne objaśnienie jak wygląda sprawa z kompatybilnością! ;)

Bardzo dużo dowiedziałem się co jak. Spróbuję nauczyć się i Scali i Haskella zwyczajnie poprzez zrobienie 2 osobnych projektów po godzinach.
W Scali napiszę aplikację webową do przechowywania linków i grupowania ich w foldery coś na zasadzie zakładek w Chrome/Firefox, bo sam będę z niej korzystał na własne potrzeby, a w Haskellu po poznaniu podstaw, coś bardziej skomplikowanego/ambitnego.

@null null
Zacząłem jakiś czas temu czytać tutorial/książkę do Rusta na głównej stronie i kodować w nim i jestem naprawdę pod wrażeniem. Mega mi się spodobał :D
Mógłbyś zdradzić szczegóły do czego są/będą wykorzystywane te mikroserwisy, które będziecie migrować na Rust? Nie są to raczej zwykłe CRUDy chyba? ;)

1

Zakładam że jesteś początkujący - nie radzę brać się za Haskella z nadzieją na przyszłość. Jest to niszowa technologia i jeśli liczysz że na niej zarobisz to raczej jesteś w błędzie, przynajmniej w Polsce. Poza tym warto też mieć czas na życie a nie kodzić 20 godzin dziennie :)
Za rok już będzie normalniej, może warto z tego będzie skorzystać ;)
Poza tym jeszcze są inne aspekty do nauki takie jak np. kolejki

2

@scibi92:

Zakładam że jesteś początkujący - nie radzę brać się za Haskella z nadzieją na przyszłość. Jest to niszowa technologia i jeśli liczysz że na niej zarobisz to raczej jesteś w błędzie, przynajmniej w Polsce.

Świat się zmienił, haskell jakis czas temu wylazł z niszy - PHP to to co prawda nie jest (pod względem popularności), ale praca w Haskellu w Polsce to już realność (są oferty, znam ludzi pracujących).

Poza tym warto też mieć czas na życie a nie kodzić 20 godzin dziennie :)

To jest akurat powód ZA kodzeniem w haskellu. Życie jest za krótkie, żeby rypać się z efektami ubocznymi.

Poza tym jeszcze są inne aspekty takie jak np. kolejki do nauki

kolejka.jpg

Kolejki do nauki

1

Jeszcze co do Scali, Haskella i innych im podobnych. Tam pracują nie tylko programiści ale i fanatycy. Kod Haskella częściej przypomina podręcznik do algebry abstrakcyjnej niż czytelny kod programu. Dziwne operatory: niech wszystko będzie $$, <>, <$>, $.$ powiedział Bóg tworząc Haskella, po co nadawać ładne, czytelne nazwy?

Ta sama mentalność występowała na początku w Scali (ScalaZ). Teraz jest nieco lepiej, ale nadal kod wielu bibliotek często jest bardzo "zwarty", tutaj przykład - losowy plik ze Slick'a (mikroORM): https://github.com/slick/slick/blob/master/slick/src/main/scala/slick/compiler/PruneProjections.scala
Widać dziwne :@, _1 i powódź nawiasów. Nie tak wyobrażam sobie kod XXI wieku...

Kiedyś znajmy pracował w mBanku na projekcie F#'owym. Do projektu (to była jakaś apka do oceny ryzyka) zatrudniono w większości matematyków. Po roku pracy prawie każda zmienna była nazwana x, y i z (na serio nie żartuje). Z kodem aplikacji praktycznie w ogóle nie dało się pracować, ponieważ zapomniano o czytelności i łatwości zrozumienia kodu. Teraz jako kontrreakcja na ten matematyczno-funkcyjny-fanatyzm sporo osób wybiera Go który jest aż nazbyt prosty. Być może za 10 lat znajdziemy złoty środek, być może jest nim otypowany Python...

2

@0xmarcin:

$$, <>, <$>, $.$ powiedział Bóg tworząc Haskella, po co nadawać ładne, czytelne nazwy?

Takie operatory są użyte także po to aby zwiększyć czytelność :-)
Wiem, że z punktu widzenia javowca ciężko zrozumieć. Jak nazwa nie ma 5ciu kawałków to nie wiemy co to robi - w odróżnieniu od od AbstractSingletonFactoryBeanImpl.
Ale oczywiście to trochę kwestia gustu i niektóre operatory są nieszczęśliwie dobrane - $ jest taki sobie (wizualnie nijak nie kojarzy mi się z aplikacją funkcji). (jakby używali PETSCII zamiast Ascii 7 bit to by znaleźli coś lepszego na pewno).

Tak czy siak - wolę czytać x y albo x $ y zamiast x.apply(y). Szczególnie jak tych apply trochę więcej jest w linijce.

Po roku pracy prawie każda zmienna była nazwana x, y i z (na serio nie żartuje)

Czasem takie zmienne to wręcz ideał ... jeśli kod jest silnie polimorficzny (abstrakcyjny). Oczywiście pytanie czy ten kod (F#) faktycznie jest polimorficzny.

Dawno temu pisałem tu jak przedzierałem się jako bardzo początkujący haskellowiec przez setki linii takiego kodu (kod GHC, a w zasadzie eta-lang) i byłem zszokowany, że wszystko mogę znaleźć. W tym samym czasie poległem na podobnym przedzieraniu się przez kod kompilatora kotlina (pisany w javie, w której od 20 lat grzebię w różnych kupach i myślałem, że jestem już niezły). To oczywiście tzw. dowód anegdotyczny, ale miałem te 2 nocki, gdzie zmieniłem radykalnie zdanie o kodzie haskella (na początku wydawał mi się, że jest zaszyfrowany, a na koniec już pisałem peany jaki to haskell jest czytelny). Drugie wyjaśnienie jest takie, że możliwe że jestem dziabnięty, bo ukończyłem matematykę :/

3

Dziwne operatory: niech wszystko będzie $$, <>, <$>, $.$ powiedział Bóg tworząc Haskella, po co nadawać ładne, czytelne nazwy?

Niedawno próbowałem te dziwne operatory pozbierać do kupy (jeszcze nie wszystko się udało):

Dla niektórych operatorów istnieją alternatywne, bardziej czytelne wersje, np:

(<|) = ($)      -- "apply forward"    or "pipe into"
(|>) = (&)      -- "apply backward"   or "pipe from"
(<.) = (.)      -- "compose backward" or "but first"
(.>) = flip (.) -- "compose forward"  or "and then"

Dzięki czemu można zapisać:

f x = f3 (f2 (f1 x))      -- normalny zapis
f x = f3 <| f2 <| f1 <| x -- apply forward.   -- jak w Elixirze
f x = x |> f1 |> f2 |> f3 -- apply backward
f = f3 <. f2 <. f1        -- compose backward -- bardziej po Haskelowemu
f = f1 .> f2 .> f3        -- compose forward

Nadużywanie operatorów w Haskellu wynika też z tego że mają bardziej czytelną składnie wywoływania niż funkcje z dwoma parametrami. Te cztery zapisy robią to samo:

fmap (function1 data1)
fmap $ function1 data1
function1 <$> data1
data1 <&> function1

który jest najbardziej czytelny?

1

Warto przytoczyć tutaj znany artykuł: https://www.innoq.com/en/blog/the-language-of-maths-is-not-the-language-of-your-business/
Jeżeli chodzi o pana @jarekr000000 to wydaje się być outlier'em, ale czy faktycznie przeciętny programista woli zmienne x i y, czy może te bardziej verbose (choć jak pokazuje Python nazwy mogą być czytelne i zwięzłe za razem) to niech każdy oceni sam...

1

Dla mnie taki zbyt funkcyjny kod nie wygląda jak narzędzie do rozwiązywania problemów biznesowych tylko jak zabawka dla matematyka. Częścią biznesu jest Order, PaymentId itp a nie jakieś abstrakcyjne aplicatory o dziwnych nazwach. Zresztą nawet @Wibowit który pisze w Scali pisał że puree FP jest bardzo trudny i niepraktyczny.
Kotlin z jakimś Vavrem albo Arrow wydaje się sensownym kompromisem

1

Ważny jest kontekst. (Mam wrażenie, że niedawno ktoś to też pisał).

Ludzie często widzą kod z bibliotek haskella, który jest mocno polimorficzny i dlatego zmienne są jednoliterkowe.
Uniwersalne zmienne trudno inaczej nazwać, bo pod a może być tam naprawdę cokolwiek.
Po prostu działa taka konwencja, która w javie też jest używana (i to tez przy polimorficznym kodzie) -zastanawialiście się czemu pisze się List<T>, a nie List<ELEMENT_TYPE> ?
(strzelam, że niektórzy javowcy nawet nie wiedzą, że argumenty generyków mogą być wieloliterowe...).
Co więcej jak popatrzysz w implementację Streamów to też widać takie linijki:

for (@SuppressWarnings("rawtypes") AbstractPipeline u = sourceStage, p = sourceStage.nextStage, e = this;
                 u != e;
                 u = p, p = p.nextStage) {

(Ale fakt, że to raczej mniejszość kodu - więcej zmiennych ma dłuższe nazwy).

Faktyczny kod systemów oparty o te biblioteki może już być inny i na pewno zależy od zespołu (mój amatorski haskell mocno śmierdzi javą, właśnie przez długie nazwy funkcji, typów i modułów).
Co więcej jeśli kod jest pisany dla jakiegoś działu ryzyka w banku to bardzo możliwe, że będzie operował na nazwach i symbolach matematycznych wprost używanych przez analityków - ot taka jaka dziedzina taki język domeny. W tym kontekście wprowadzanie długich nazw mogłoby wręcz być błędem, bo utrudniałoby komunikację.

3
0xmarcin napisał(a):

Jeszcze co do Scali, Haskella i innych im podobnych. Tam pracują nie tylko programiści ale i fanatycy. Kod Haskella częściej przypomina podręcznik do algebry abstrakcyjnej niż czytelny kod programu. Dziwne operatory: niech wszystko będzie $$, <>, <$>, $.$ powiedział Bóg tworząc Haskella, po co nadawać ładne, czytelne nazwy?

Ta sama mentalność występowała na początku w Scali (ScalaZ). Teraz jest nieco lepiej, ale nadal kod wielu bibliotek często jest bardzo "zwarty", tutaj przykład - losowy plik ze Slick'a (mikroORM): https://github.com/slick/slick/blob/master/slick/src/main/scala/slick/compiler/PruneProjections.scala
Widać dziwne :@, _1 i powódź nawiasów. Nie tak wyobrażam sobie kod XXI wieku...

:@ jest użyte 89 razy w Slicku, a przynajmniej tyle wystąpień znalazł mi IntelliJ w wersji Slicka którą mam w projekcie. To nie jest mało, przeglądając źródła Slicka można się do tego przyzwyczaić.

_1 służy do wybierania pola z krotki. Vavr ma analogiczną składnię. C++1 ma koszmarek typu std::get<1>(tuple). Jeśli ktoś używa krotek (czyli nieponazywanych struktur) do reprezentacji danych to potem musi albo użyć nienazwanych pól albo sobie je nazwać. To jest pewien wybór. Zrobienie klasy Pair z polami first i second jak w Kotlinie nie rozwiązuje sprawy, bo te nazwy nic nie mówią, a na pewno nie mówią więcej niż _1 i _2.

Jeśli chodzi o zwięźle nazwane metody (do tych zaliczam operatory, bo w Scali operator jest zwykłą metodą tylko nazwaną nieliterowo), które nie zawierają wyraźnych podpowiedzi co faktycznie robią to tutaj sprawa nie jest zero-jedynkowa. Dużo zależy od tego jak często operator jest używany. Dla przykładu dorzucanie elementu do mapy. Lepiej zrobić map1.put(key, value) czy map1 + (key, value) (względnie zamiast put jest updated)? map1 ++ map2 czy map1.concat(map2)? Jeśli jakichś operacji się często używa to warto mieć zwięzłe operatory. Jeśli się rzadko używa to warto mieć opisowo nazwane metody. To jakie operacje są często robione zależy od języka. W Haskellu częstymi operacjami jest składanie funkcji, więc tam naturalną rzeczą są zwięzłe operatory do składania funkcji na różne sposoby. W językach naszpikowanych nullami naturalną rzeczą są rozmaite operatory do wykonywania szeregu operacji na nullowalnych zmiennych.

4
scibi92 napisał(a):

Dla mnie taki zbyt funkcyjny kod nie wygląda jak narzędzie do rozwiązywania problemów biznesowych tylko jak zabawka dla matematyka. Częścią biznesu jest Order, PaymentId itp a nie jakieś abstrakcyjne aplicatory o dziwnych nazwach. Zresztą nawet @Wibowit który pisze w Scali pisał że puree FP jest bardzo trudny i niepraktyczny.

Kotlin z jakimś Vavrem albo Arrow wydaje się sensownym kompromisem

O ile dobrze pamiętam to ten "puree FP", który krytykowałem to były przekombinowane monady IO. O ile w świecie JSa modą jest wymyślanie nowych frameworków do generowania HTMLa, o tyle w świecie FP modą jest wymyślanie nowych wariantów monad IO (i całej otoczki wokół nich). Biblioteka standardowa Scali nie zawiera typowej monady IO. Jest Future, Try, Either, Option, etc ale monada IO (wraz z wspomnianą otoczką) jest z założenia jedną monadą do wszystkiego (obsługa błędów, asynchroniczności, przetwarzania równoległego, synchronizacji, transakcji, powtarzania zadań, itp itd). Ostatnio powstało ZIO https://zio.dev/ które jest monadą IO bez nadmiernej ceremonii i tutaj bardzo możliwe, że dałoby się odnieść zysk, ale i tak wymaga to dyscypliny. W Scali można bardzo łatwo przypadkowo zrobić efekt uboczny, kompilator tego nie pilnuje. Stąd niepraktyczność "skrajnie" czystego FP w Scali, o którym wielokrotnie pisałem.

Z drugiej strony wcale nie trzeba wchodzić w monady IO i stawać na głowie, żeby mieć sporą część kodu czystą funkcyjnie. Można oddzielić kod, który robi I/O (kod z efektami ubocznymi) od czysto funkcyjnego kodu, który przetwarza gotowe dane zgodnie z regułami biznesowymi. Scala się tutaj bardzo dobrze sprawdza, bo Scalowe kolekcje bardzo ułatwiają pisanie czysto funkcyjnego kodu do mielenia danych. Jest rozsądny podział w hierarchii kolekcji: wspólne typy bazowe (a'la widoki tylko do odczytu), podtypy dla kolekcji niemutowalnych i osobne podtypy dla kolekcji mutowalnych (bez upośledzonych zależności typu kolekcje mutowalne dziedziczą po niemutowalnych albo odwrotnie). Same kolekcje mają mnóstwo przydatnych metod wykonujących różnorakie transformacje.

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