Przejście z javy do scali

0

Cześć, ostatnio naszła mnie taka myśl, pewnie spowodowana tym, że z różnych stron słyszy się o Scali i językach funkcyjnych, żeby w imię walki z monotonią nauczyć się jej.

http://www.scala-lang.org/docu/files/ScalaTutorial-pl_PL.pdf
https://docs.scala-lang.org/pl/tutorials/tour/sequence-comprehensions.html

Z tych dwóch tutków i jakiś tam video na yt czytałem i oglądałem sobie i naszło mnie kilka rozkmin, które pewnie rozwiane przez Was pomogą mi w dalszej przygodzie z tym językiem. Otóż, w którym miejscu Scala ma przewagę nad Javą ? No ok, są operacja na strumieniach, ale to przecież w javie 8 weszło i działa tak samo. Są klasy przypadków dostarczające za free implementaje equals i hashCode. I co jeszcze ?
Druga sprawa dotyczy tego w jaki sposób ogarnąć kiedy dobrze użyć danej funkcjonalności Scali ? Bo tam jest sporo tego, np ekstraktory, dopasowanie wzorców i inne nowe dla mnie pojęcia. I jak tak myślałem, to na każdym kroku trzeba rozkminiać czy pisać w tej Scali po Javovemu czy użyć czegos "Scalowego" ? I czy to jest tak, że jak już piszemy w Scali to wszystko w Scali czy jedne rzeczy idą w Javie a reszta Scala ?

Odpowiedzi na te pytania postawią przede mną klarowniejszy sens nauki tego języka. I jeszcze jedno.. gdzieś wyczytałem, że jak się zdecyduję pisać w Scali to lepiej w Play niz Spring ?

2
  • Głównym powodem jest większa ekspresja języka, stąd i produktywność, czyli szybciej osiągniesz to samo co w Javie mniejszym nakładem pracy.
  • Scala zyskuje na popularności, więc i nie będzie takiego problemu z znalezieniem pracy.
  • Umożliwia łatwy dostęp do tego co oferuje Java (interop).
  • Ponadto programowanie funkcyjne naturalnie ułatwia pisanie kodu asynchronicznego i równoległego, chroni przede deadlockami. Stąd jest bardziej przystosowana do ówczesnych standardów. Gdy nasze procesory nie mają już większej mocy, tylko oferują coraz większą równolegle działających rdzeni - aż prosi się o nie marnowanie tej mocy pisaniem niewydajnego kodu synchronicznego.

Skorzystałbym więc z nauki Scali do podszkolenia i częstszego wykorzystywania pisania kodu równoległego.

5

Ja bym powiedział, że niedocenianym aspektem scali jest normalność bibliotek. To jest cecha kulturowa.
Przykład - chcemy po prostu uruchomić program (shell) i pobrac wyniki:
Scala

val result = "ls -al" !

vs
Java

Runtime rt = Runtime.getRuntime();
String[] commands = {"system.exe","-get t"};
Process proc = rt.exec(commands);

BufferedReader stdInput = new BufferedReader(new 
     InputStreamReader(proc.getInputStream()));

BufferedReader stdError = new BufferedReader(new 
     InputStreamReader(proc.getErrorStream()));

// read the output from the command
System.out.println("Here is the standard output of the command:\n");
String s = null;
while ((s = stdInput.readLine()) != null) {
    System.out.println(s);
}

// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
    System.out.println(s);
}

To i tak nieźle bo nigdzie nie widać czegoś w stylu RuntimeCommandExecutortBuilderFactoryImpl.getCurrentCommandExecutorBuilder() itd.
Ten Runtime.getRuntime() **prawdziwego **javowego architekta musi chyba gryźć w oczy.

Nic nie stoi na przeszkodzie aby w javie byla biblioteka typu:

final  String result =  Commands.execute("ls -l");

ale fakt, że niełatwo taką znaleźć, 20 lat po tym jak jezyk powstał, jest ciekawym.

Nie mówiąc już o porównaniu Spring-web vs Akka-HTTP czy JPA vs doobie lub slick (ale tutaj już elementy składniowe scali są wykorzystane i np. korzystanie z Akka-HTTP w Javie jest smutne, + zdarzają sie chlubne perełki jak JOOQ javowe - które mimo całej koszmarności generacji kodu jest OK ... tylko mało kto używa).

Roses are red, leaves are green, but only Java has AbstractSingletonProxyFactoryBean

0

Odnosząc się do Waszych odpowiedzi ..
Pisząc serwisy restowe często używa się programowania równoległego ? Może po prostu do tej pory pisałem za mało i zbyt proste rzeczy i nie dotarłem do tych trudniejszych. Jedynie co robiłem asynchronicznie to wysyłanie requestu do Firebase'a za pomocą adnotacji @Async, ale gdzieś czytałem, że nie powinno się jej używać. Do tej pory nie wiem dlaczego. Jakieś inne przykłady, gdzie warto użyć równoległych wątków?

Co do tego akka-http, to jest jakiś inny framework niż Spring czy to się stosuje jakoś razem ? Tak samo z JPA, niby takie fajne, ale dlaczego wszyscy mówią, żeby jednak używać czegoś innego ?

Reasumując, od czego najlepiej zacząć w Scali w kontekście apek webowych ? Zacząć stosować to akka http i doobie/slick czy coś innego ? Bo samo czytanie tutków o Scali nic nie daję, chciałbym zacząć już to stosować do czegoś sensownego ale nawet nie wiem od czego zacząć. I czy to jest z tą Scalą tak, że projekty są 100% Scala czy mieszane z javą ?

8

Z tych dwóch tutków i jakiś tam video na yt czytałem i oglądałem sobie i naszło mnie kilka rozkmin, które pewnie rozwiane przez Was pomogą mi w dalszej przygodzie z tym językiem. Otóż, w którym miejscu Scala ma przewagę nad Javą ? No ok, są operacja na strumieniach, ale to przecież w javie 8 weszło i działa tak samo. Są klasy przypadków dostarczające za free implementaje equals i hashCode. I co jeszcze ?

Najpierw trzeba sobie zadać pytanie czym jest programowanie funkcyjne. Wikipedia w zasadzie opisuje to w miarę OK:

In computer science, functional programming is a programming paradigm—a style of building the structure and elements of computer programs—that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. It is a declarative programming paradigm, which means programming is done with expressions[1] or declarations[2] instead of statements. In functional code, the output value of a function depends only on the arguments that are passed to the function, so calling a function f twice with the same value for an argument x will produce the same result f(x) each time; this is in contrast to procedures depending on a local or global state, which may produce different results at different times when called with the same arguments but a different program state. Eliminating side effects, i.e. changes in state that do not depend on the function inputs, can make it much easier to understand and predict the behavior of a program, which is one of the key motivations for the development of functional programming.

Jak widać sedno programowania funkcyjnego to wcale nie żonglowanie funkcjami, tylko operowanie na niemutowalnych danych. Funkcje wyższego rzędu w językach funkcyjnych są po to, by zredukować powtarzający się kod. Natomiast (do niedawna?) np w takim Node.js funkcje wyższego rzędu (tzn funkcje przyjmujące callbacki) są używane dlatego, że JavaScript oferuje tylko jeden wątek i używanie callbacków jest niejako wymuszone (nie ma żadnego awaita w JSie).

Scala ma pełno właściwości, które czynią programowanie funkcyjne w Scali znacznie bardziej rozsądnym niż w Javie:

  • Scala ma osobną hierarchię kolekcji, w tym kolekcji niemutowalnych z wydajnymi operacjami podziału i łączenia, np:
    • prepend dla Listy w Scali jest wykonywany w czasie stałym
    • podobnie wyciągnięcie tail z Listy jest w czasie stałym (oba powyższe są możliwe dlatego, że Lista w Scali to lista pojedynczo łączona)
    • wstawienie (bądź usunięcie) elementu do niemutowalnego Seta tworzy drugiego Seta w czasie logarytmicznym
    • podobnie z Mapą i Vectorem (w tych przypadkach można podmienić element w Mapie czy Vectorze z taką samą złożonością)
    • wszystko powyższe jest możliwe dzięki structural sharing - nowa niemutowalna kolekcja powstała z dołączenia czy usunięcia elementu współdzieli ze starą kolekcją dużą część danych
  • case class jest domyślnie (bo można wstawić słówko var i móc podmieniać pola) niemutowalna, zawiera metodę copy dla łatwego tworzenia podobnych instancji oraz gotowego companion objecta z ekstraktorem
  • niemutowalność case class oraz typowo używanych kolekcji sprawia, że można je dowolnie przesyłać między wątkami i nie martwić się o synchronizację
    • w Scali używanie wątków wprost jest rzadko spotykane i używa się aktorów - w mechaniźmie aktorów silnie zaleca się używanie niemutowalnych wiadomości, a niemutowalne kolekcje i struktury danych są świetnymi rodzajami wiadomości do przesyłania między wątkami/ aktorami/ etc
  • bardzo zwięzłe (nawet w porównaniu z Javą 8) sposoby zapisu funkcji
  • ekstraktory i dopasowanie wzorców umożliwia typowe dla języków funkcyjnych oddzielenie struktur danych od funkcjonalności - czasami jest to znacznie wygodniejsze niż OOP, a Scala umożliwia mieszanie wielu stylów, w zależności od tego który jest dla nas w danym momencie wygodniejszy
  • wbudowane w kompilator wsparcie dla optymalizacji rekurencji ogonowej - rekurencja ogonowa to często fundament czysto funkcyjnych algorytmów, bo daje te same możliwości co imperatywne konstrukcje, a zachowuje matematyczną czystość
  • itd

Książka https://www.manning.com/books/functional-programming-in-scala wprowadza w świat programowania funkcyjnego z użyciem Scali. Pamiętam, że było tam fajne tłumaczenie czym jest programowanie funkcyjne i skupiono się w pewnym momencie na 'local reasoning'. Mając niemutowalne obiekty nie musimy zastanawiać się czy dane wywołanie funkcji z interesującym nas obiektem jako parametrem zmieni ten obiekt. To sprawia, że jeśli chcemy się dowiedzieć skąd się wzięły dane w naszym obiekcie wystarczy cofnąć się do miejsca w którym został stworzony - i tyle. Zamiast sprawdzać które funkcje mogą zmienić stan naszego obiektu (a w magicznych imperatywnych frameworkach obiekt może być modyfikowany nawet z innego wątku i z zupełnie innego miejsca w kodzie) wystarczy, że prześledzimy historię tworzenia naszego obiektu i wcześniejszych obiektów.

Dodatkowo Scala ma pewną cechę odróżniającą ją od innych języków - parametry i konwersje implicit. Te rzeczy dają dużo możliwości na zredukowanie nadmiarowego kodu (jak się trochę pokodzi w Scali to się zrozumie), ale niektórzy kręcą nosem widząc implicity. IntelliJ ma w miarę OK wsparcie dla implicitów w Scali (Ctrl+Alt+P pokazuje implicit parametry, Ctrl+Alt+Q pokazuje implicit konwersje).

Druga sprawa dotyczy tego w jaki sposób ogarnąć kiedy dobrze użyć danej funkcjonalności Scali ? Bo tam jest sporo tego, np ekstraktory, dopasowanie wzorców i inne nowe dla mnie pojęcia. I jak tak myślałem, to na każdym kroku trzeba rozkminiać czy pisać w tej Scali po Javovemu czy użyć czegos "Scalowego" ? I czy to jest tak, że jak już piszemy w Scali to wszystko w Scali czy jedne rzeczy idą w Javie a reszta Scala ?

Kod typowo Scalowy raczej nie przypomina Javowego. Co innego gdybyś integrował się z Javowymi bibliotekami - wtedy Javizmy siłą rzeczy się pojawią. Scala wspiera równie mocno OOP co FP, więc kod Scalowy może wyglądać różnie. Ogólnie jednak typowy kod Scalowy jest pewnym kompromisem - z jednej strony kładzie się duży nacisk na niemutowalność przy operowaniu na kolekcjach czy własnych strukturach danych, a z drugiej strony opakowywanie wszelkich funkcji z efektami ubocznymi w rzeczy typu monada I/O jest uważana za przesadę (mimo, że np w Haskellu monada IO to norma). Do izolacji efektów ubocznych w Scali używa się zwykle systemu aktorów (czyli Akki).

Jak poklepiesz trochę w Scali, poczytasz kod Scalowy pisany przez (w miarę) doświadczonych Scalowców to z czasem załapiesz czym jest idiomatyczny Scalowy kod. Nie ma się co spinać. Podobnie jest przy każdym innym języków. Jeśli wyrwiesz Javowca i zmusisz go do pisania Pythona to możesz dostać kod Pythonowy z getterami i setterami wprost z Javowych fasolek. Z czasem jednak jego kod będzie stawał się coraz bardziej pythonic.

I jeszcze jedno.. gdzieś wyczytałem, że jak się zdecyduję pisać w Scali to lepiej w Play niz Spring ?

Scali nie łączy się z krowiastymi Javowymi frameworkami. Używa się natomiast Javowych bibliotek jeśli nie ma wygodnych Scalowych odpowiedników. Różnica między frameworkiem, a biblioteką jest taka, że bibliotekę można użyć lokalnie i w małym stopniu (np tylko interesujących nas kilka metod z biblioteki), natomiast framework wymusza na nas szerokie zastosowanie jego rozbudowanego API.

0

@Wibowit:
dziękuję bardzo za wyczerpującą odpowiedź. Reasumując polecasz zacząć uczyć się Scali tak ? Wiadomo, że najlepiej ucząc się pisząc jakąś apkę + dobra książka. I skoro twierdzisz, że mam scali nie łączyć z żadnym Springiem i innym to co najlepiej zacząć używać, żeby skrobnąć jakąś apkę webową/rest api ?

1

Nie tylko Scala jest na dostępna na JVM, ale i Kotlin, Clojure. Tego ostatniego warto się nauczyć, gdy chcesz osiągnąć koderskiego oświecenia ;)

1

Akka-HTTP ma wszystko co trzeba by postawić zwykłe REST API. Play Framework ma dodatkowo w zestawie system szablonów Twirl (moim zdaniem zbędny jeśli tworzysz SPA w Angularze czy React'u), multum filtrów/ wtyczek do uwierzytelniania czy autoryzacji (to chyba mocny punkt Playa) oraz szereg innych funkcjonalności, które niespecjalnie pamiętam, bo dawno nie programowałem w Playu.

Dobra książka to pojęcie względne - zależy czego się chcesz nauczyć. Jeśli chcesz załapać czym jest programowanie funkcyjne to warto przerobić tę książkę co podałem wcześniej (czyli https://www.manning.com/books/functional-programming-in-scala ), chociaż ja zaczynałem od krótkiego kursu Haskella, czyli LYAHFGG: http://learnyouahaskell.com/ Do stawiania RESTów w Scali przydatne będą zupełnie inne pozycje, ale ja osobiście starałbym się raczej skorzystać najpierw z oficjalnej dokumentacji, bo ta zwykle jest najbardziej na czasie.

1

Ze smutnych rzeczy:
Programowałem w **Scavie **tak przez półtora roku. Czyli pisząc nadal Javę składnią Scali. To było tak długo jak robiłem projekty domowe. Dopiero praca 5x8 przez kilka tygodni podciągnęła mnie trochę.
Słabo, że tych leveli do podciągnięcia jest bardzo dużo i im więcej opanowuję tym więcej poznaję nowych.

http://lambdaconf.us/downloads/documents/lambdaconf_slfp.pdf

Z drugiej strony - nawet na tym najniższym levelu => Scava jest już fajnie.

Olej Play - to właśnie taki Scalowy Spring. Jedyna zaleta to, że jest dobrz udokumentowany. Ale to jest przerost formy nad treścią i używa magię.
Jak robisz klasyczny backend Restowy dorby i wystarczający jest AKKA-HTTP.

Jest jeszcze jedna fajna rzecz ScalaJS - czyli możesz pisać front w Scali transpilowanej do JavaSkryptu i to pod angulara lub Reacta.. lub cokolwiek tam chcesz w JS.
Dość to podobne do TypeScriptu, ale jak to Scala ma większą moc. No i świetny sposób, żeby uniknąć biedy JS i nauczyć się Scali. Zła rzecz jest taka, że musisz JS umieć, bo nie ogarniesz uczenia dóch rzeczy na raz (ze ScaliJS jeszcze ten JS czasem "wycieka" - głównie przez słabe mappingi do bibliotek JS).

0

Zastanów się czy na pewno chcesz się dotykać tej Scali.

Jak chcesz liznąć FP to są przecież Elixir i Clojure.
Jak chcesz fajniejszy język od Javy to są Kotlin i Groovy.
https://www.slant.co/topics/708/~best-functional-programming-languages-for-programming-beginners
https://www.slant.co/versus/116/1538/~scala_vs_clojure
http://www.bestinclass.dk/da/posts/scala-vs-clojure-lets-get-down-to-business
https://superkotlin.com/kotlin-vs-scala/

Scala to z tego co wiem taka kobyła której się będziesz uczyć i uczyć... aż osiwiejesz.
Jak myślisz w tym pracować jako w głównym języku to spoko. Ale jak chcesz stosować jako język dodatkowy to chyba szkoda zachodu.

1

Scala to z tego co wiem taka kobyła której się będziesz uczyć i uczyć... aż osiwiejesz.

A co takiego wiesz, że w ten sposób piszesz? W świecie Scali się dużo mniej dzieje niż w takim np JavaScripcie.

U nas w zespole nie każdy jest wirtuozem Scali, ale i tak udaje się nam wszystkim systematycznie rozwijać system.

2

W kategorii - kobyła - to fakt, że czasem nie rozumiem przez całe godziny kodu pisanego przez LiHaoia czy paru innych kosmitówm, bo nie znam pewnych tricków z implicitami, ale jakoś mnie to nie blokuje bardzo.

Główna róznica do javy jest taka, że zamiast spędzać godziny na zastanawianiu się dlaczego po zamianie dwóch linijek wJavie mój magiczny bean już sie nie autowireduje i mam nulla - spędzam takie same godziny na odkrywaniu co znaczy magiczny komunikat kompilatora w Scali :-)
(a nadal uważam, że lepiej jak coś się wywala w buildzie a nie na produkcji).

Ale większość obaw o Scalę pochodzi od ludzi, którzy widzieli kod w Scali przez parę minut w życiu i doznała oczopląsu :-)
Znam projekty - katastrofy Scalowe... ale trudno powiedzieć na ile Scala na katastrofę wpłynęła. Znam też katastrofy w innych językach.

Clojure jest elegantszy (a Scala niestety to język śmietnik...), ale bez typów jakoś nie umiem.
Haskell jest czystszy, ale za to nie wybacza myślenia imperatywnego.
Scala jest dość po środku sensu, praktyczna, a daje duże możliwości rozwinięcia swoich umiejętności koderskich w sposób płynny.

Jak Cię bardziej interesuje coś co może być hitem ostro poszukiwanym na rynku pracy, (a nie tylko rozwój własny) to duże szanse ma Scala-- => czyli Kotlin. Mam nadzieję, że Kotlin bedzie się rozwijał w stronę Scali, i tylko będzie zrobiony lepiej (z nullami IMO im wyszło).

1

Kotlin to taki obcięty wariant Scali, który się szybciej kompiluje. Czytałem kiedyś artykuł (opinię jednego z twórców Kotlina) w którym o tym pisano, ale nie mogę go teraz znaleźć. Autorzy Scali jednak nie siedzą z założonymi rękami, a pracują nad przyspieszeniem kompilacji. Kompilacja przyrostowa dla Scali działa od wielu lat, ale dalej jest dużo do poprawienia jeśli chodzi o kompilację od zera.

Przez nacisk na szybkość kompilacji Kotlin pewnie nie dostanie najbardziej rozpoznawalnej cechy Scali czyli parametrów i konwersji implicit, gdyż te mogą czasem mocno spowalniać zarówno kompilację jak i działanie IDE. Przykład: scalaz - wystarczy na początku pliku zaimportować wszystko import scalaz._; import Scalaz._ i od razu IDE działa kilka razy wolniej przy edycji tego pliku. Scalaz to jednak przykład skrajny - w znakomitej większości przypadków implicitów jest rozsądna ilość i IDE działa płynnie.

Ponadto, jeśli chodzi o komunikaty błędów od kompilatora to im dłużej się kodzi tym mniej czasu się nad nimi spędza (oczywista oczywistość w sumie). Jeden powód to to, że unika się dziwacznych konstrukcji powodujących problemy, a inny to to że wiele błędów jest mocno szablonowych, np zapomnieliśmy zaimportować ExecutionContext dla stworzenia czy transformacji Future'a.

2

Ja planuję nauke Clojure jako języka funkcyjnego za kilka miesięcy :)

2

@scibi92 Clojure zainteresowałem się ze względu na współbieżności i sam fakt, że jest lispem więc pracując samemu bądź w bardzo małym zespole można skorzystać na jeszcze większej produktywności.

Generlnie Clojure (z punktu widzenia produktywności) to słaba opcja, ponieważ nie ma tam żadnego frameworka i ciężej jest się rozkręcić.

Z drugiej strony Clojure dzięki makrom sam w sobie jest jak framework, ale i tak (moim zdaniem) jest źle, bo dość dużo czasu traci się na składanie aplikacji z małych bibliotek (mi to trochę przypominało programowanie jak w nodejs/express). Najgorsze w tym, że większość bibliotek ma ostatnie commity tak z przed 2-3 lat :-/

Dla porównania praca z Elixirem jest o niebo lepsza. Tam wszystko działa, można zdać się na intuicję i do tego kody w tym języku dużo łatwiej się czyta.

Gdyby ktoś miał garść własnych przemyśleń na temat Clojure to chętnie bym się z nimi zapoznał :-)

0

Kotlina chciałem się uczyć ze względu, że w poprzedniej pracy kodziłem na Androida i trochę iOS i na pierwszy rzut oka jest bardzo podobny do Swifta.
A jeśli chciałbym pisać resty w tym, to jednak Spring czy Kotlin ma swoje ?

0

Proponuje Springa :)

0
Bambo napisał(a):

Kotlina chciałem się uczyć ze względu, że w poprzedniej pracy kodziłem na Androida i trochę iOS i na pierwszy rzut oka jest bardzo podobny do Swifta.
A jeśli chciałbym pisać resty w tym, to jednak Spring czy Kotlin ma swoje ?

Dla Kotlina np. https://github.com/Kotlin/ktor

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