Scala vs. Java: de ce ar trebui să învăț Scala?

Publicat: 2022-03-11

Desigur, există ceva adevăr în afirmația că „Scala este greu”, dar curba de învățare merită din plin investiția. Unele dintre caracteristicile mai complexe ale limbajului (Tuple, Funcții, Macro-uri, pentru a numi câteva) în cele din urmă fac mai ușor pentru dezvoltator să scrie un cod mai bun și să mărească performanța prin programarea în Scala. Sincer, suntem programatori și, dacă nu suntem suficient de deștepți pentru a învăța un limbaj care are o oarecare complexitate, atunci ne aflăm într-o afacere greșită.

Scala este un limbaj JVM sigur de tip care încorporează atât programarea orientată pe obiect, cât și programarea funcțională într-un limbaj extrem de concis, logic și extraordinar de puternic. Unii ar putea fi surprinși să afle că Scala nu este atât de nou pe cât credeau, fiind introdus pentru prima dată în 2003. Cu toate acestea, în special în ultimii câțiva ani, Scala a început să dezvolte un număr semnificativ de urmăritori. Ceea ce ridică întrebarea „De ce Scala?”.

Acest articol examinează avantajele Scala, în special față de Java (deoarece Scala este scris pentru a rula în JVM). Scala nu este singura încercare de a crea un „Java mai bun”. Alternative precum Kotlin și Ceylon au mers și ele pe această cale, dar au luat decizia fundamentală de a rămâne foarte aproape în sintaxă de limbajul Java în sine, pentru a minimiza curba de învățare. Aceasta poate părea o idee grozavă, dar în cele din urmă este oarecum auto-înfrângătoare, deoarece vă obligă să rămâneți într-un număr de aceleași paradigme Java care au fost motivul pentru care doriți să creați un „Java mai bun” în primul rând.

În schimb, Scala a fost creat special cu scopul de a fi un limbaj mai bun, renunțând la acele aspecte ale Java pe care le considera restrictive, excesiv de obositoare sau frustrante pentru dezvoltator. Ca rezultat, există într-adevăr distincții de cod și schimbări de paradigmă care pot face un pic mai dificilă învățarea timpurie a programării Scala, dar rezultatul este un limbaj mult mai curat și bine organizat, care este în cele din urmă mai ușor de utilizat și crește productivitatea.

Când comparăm Scala cu Java unul lângă altul, eficiența Scala este clară.

Scala vs. Java: care este cu adevărat mai complex?

În timp ce simplitatea limbajului Java a făcut parte din succesul său, în mod ironic, a contribuit și la complexitatea acestuia. Sigur, puteți scrie aproape orice în Java, dar liniile de cod necesare pentru a face acest lucru pot fi descurajante. Programarea în Scala, pe de altă parte, are o structură ceva mai complexă. Dar dacă poți scrie o singură linie de cod puțin mai complexă care înlocuiește 20 de linii „mai simple” de Java, care dintre ele este cu adevărat mai complexă?

Adevărul este că Java este adesea mult prea verbos. În Scala, compilatorul este incredibil de inteligent, astfel încât acest lucru evită ca dezvoltatorul să fie nevoie să specifice în mod explicit acele lucruri pe care compilatorul le poate deduce. Comparați, de exemplu, acest simplu „Hello World!” program în Java vs Scala:

Bună lume în Java:

 public class HelloJava { public static void main(String[] args) { System.out.println("Hello World!"); } }

Hello World in Scala:

 object HelloScala { def main(args: Array[String]): Unit = { println("Hello World!") } }

Deși aici nu există o distincție uriașă între cele două limbi, Scala este mai puțin pronunțată chiar și în acest exemplu simplu.

Pentru un exemplu mai practic, să aruncăm o privire la crearea unei liste simple de șiruri de caractere:

Java:

 List<String> list = new ArrayList<String>(); list.add("1"); list.add("2"); list.add("3");

Scala:

 val list = List("1", "2", "3")

Cu siguranță există câteva trucuri în Java pentru a scurta puțin codul, dar nu în utilizarea standard.

Acum luați în considerare un caz în care avem o listă de șiruri care sunt numere, dar dorim să convertim acea listă într-o listă de numere întregi:

Java:

 List<Integer> ints = new ArrayList<Integer>(); for (String s : list) { ints.add(Integer.parseInt(s)); }

Scala:

 val ints = list.map(s => s.toInt)

Datorită proprietăților funcționale ale Scala, această conversie devine extrem de simplă.

Un exemplu de clasă: Java vs. Scala

Să facem lucrurile cu un pas mai departe și să comparăm crearea de obiecte Java standard vechi / simplu vechi (POJO) în Java și Scala.

În primul rând, versiunea Java:

 public class User { private String name; private List<Order> orders; public User() { orders = new ArrayList<Order>(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Order> getOrders() { return orders; } public void setOrders(List<Order> orders) { this.orders = orders; } } public class Order { private int id; private List<Product> products; public Order() { products = new ArrayList<Product>(); } public int getId() { return id; } public void setId(int id) { this.id = id; } public List<Product> getProducts() { return products; } public void setProducts(List<Product> products) { this.products = products; } } public class Product { private int id; private String category; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } }

Uf. Cod Lotta.

Acum versiunea Scala:

 class User { var name: String = _ var orders: List[Order] = Nil } class Order { var id: Int = _ var products: List[Product] = Nil } class Product { var id: Int = _ var category: String = _ }

Care limbă am spus că este mai complicată?!

Suntem corecti?

Dacă ați ajuns până aici și sunteți programator Java, este posibil să vă gândiți în acest moment că fac o comparație nedreaptă a codului. La urma urmei, nimic nu mă împiedică să fac variabile publice în Java și apoi să scap de getters și setters.

Cu toate acestea, dacă vă gândiți înapoi la raționamentul din spatele getters și setters în Java, este special pentru viitor. Adică, dacă mai târziu trebuie să adăugați ceva logică fie la obținerea, fie la setarea variabilelor, va trebui să rescrieți acele variabile publice pentru a utiliza în schimb metode (de aceea este încurajată, pentru început, utilizarea getter-urilor și setter-urilor în Java). ). Cu toate acestea, în programarea Scala, acest lucru nu este cazul. Datorită designului limbajului, abstracția rămâne intactă fără a avea nevoie de getters și setters. Luați în considerare, de exemplu, această clasă de User modificată în Scala care aruncă o NullPointerException dacă încercați să setați numele la null:

 class User { private var _name: String = _ var orders: List[Order] = Nil def name = _name def name_=(name: String) = { if (name == null) { throw new NullPointerException("User.name cannot be null!") } _name = name }

Și încă puteți seta numele astfel:

 user.name = "John Doe"

Rețineți că acest lucru elimină complet necesitatea preconfigurarii accesoriilor de metodă.

Mai mult, deoarece Scala preferă imuabilitatea, pot scrie acest lucru în Scala și mai concis cu clasele de caz:

 case class User(name: String, orders: List[Order]) case class Order(id: Int, products: List[Product]) case class Product(id: Int, category: String)

Destul de nebunesc cât mai puțin cod trebuie să scriu.

Luând exemplul un pic mai departe

Acum luați în considerare un scenariu cu clasele de mai sus în care vreau să adaug o mică metodă ingenioasă în clasa de User care returnează o listă cu toate Products pe care User le-a comandat:

În lumea verbosă a Java:

 public List<Product> getProducts() { List<Product> products = new ArrayList<Product>(); for (Order order : orders) { products.addAll(order.getProducts()); } return products; }

Din fericire, java.util.List are o metodă addAll , sau getProducts() ar fi fost și mai lung în Java.

La Scala, pe de altă parte, tot ce ne trebuie este:

 def products = orders.flatMap(o => o.products)

Puteți vedea cât de mult mai mică este implementarea limbajului Scala. Da, poate părea mai complex pentru începătorul Scala, dar odată ce înțelegi pe deplin conceptele din spatele lui, codul Scala va părea mult mai simplist decât codul Java.

Să ne complicăm și mai mult aici. Ce se întâmplă dacă dorim să obținem numai Products dintr-o anumită Category ?

În acest caz, nu putem profita de metoda addAll din java.util.List , așa că lucrurile devin mai urâte în Java :

 public List<Product> getProductsByCategory(String category) { List<Product> products = new ArrayList<Product>(); for (Order order : orders) { for (Product product : order.getProducts()) { if (category.equals(product.getCategory())) { products.add(product); } } } return products; }

În Scala , totuși, codul rămâne destul de simplu. Pur și simplu folosim flatMap pentru a combina listele de produse din fiecare Order aplatizată într-o singură listă, apoi filtrăm pentru a le include numai pe cele care se potrivesc categoriei:

 def productsByCategory(category: String) = orders.flatMap(o => o.products).filter(p => p.category == category)

Dinamic vs static

Cu siguranță nu au lipsit limbi noi în ultimii ani, dar în timp ce aproape toate celelalte care au apărut recent sunt dinamice, Scala este tipizat static.

În calitate de dezvoltator profesionist – deși cunosc și folosesc multe limbaje dinamice – este de părere că verificările la timp de compilare sunt incredibil de importante pentru a scrie cod solid. Într-un limbaj dinamic, nu poți fi niciodată sigur că codul tău este suficient de lipsit de erori și de robust până când îl rulezi într-o gamă largă de scenarii. Acest lucru poate duce la defecte potențial grave ale codului care nu se realizează niciodată până când codul este în producție.

Învelire

Sperăm că acest articol combină Java vs Scala suficient pentru a vă oferi o idee preliminară a puterii și capacităților Scala și vă stârnește apetitul pentru a învăța limba. Nu numai că este un limbaj grozav care poate face programarea mai puțin plictisitoare și mai plăcută, dar este și folosit de unele dintre cele mai mari companii din lume (LinkedIn, Twitter, FourSquare, The Guardian, pentru a numi doar câteva).

Popularitatea și utilizarea Scala este în creștere rapidă, așa cum demonstrează numărul tot mai mare de poziții deschise pentru dezvoltatorii Scala. Dacă nu ai făcut-o deja, acum ar fi un moment bun să începi să călărești pe val și să nu mai întrebi „De ce să înveți Scala?”

Înrudit : Reduceți codul standard cu macrocomenzi Scala și cvasiquote