De ce ar trebui dezvoltatorii Java să ofere Grails o șansă?
Publicat: 2022-03-11Java are un ecosistem care s-a maturizat de-a lungul anilor de dezvoltare, stabilindu-l ca una dintre cele mai fiabile platforme de acolo. Cu toate acestea, îi lipsesc mijloacele necesare pentru a face treaba rapid, mai ales pentru lucruri precum aplicațiile web. În încercarea de a evita frustrările cu aceste tipuri de probleme, dezvoltatorii optează adesea pentru limbaje de implementare și cadrele lor web moderne, cum ar fi Ruby cu Ruby on Rails, Python cu Django și așa mai departe. Spre deosebire de Java, acestea oferă o cale mult mai simplificată pentru construirea unei aplicații web.
Din fericire, pentru dezvoltatorii Java care doresc să construiască aplicații web, există o modalitate mai bună și implică Grails. În acest articol, vom vedea cum Grails cu Groovy este o alternativă viabilă în domeniul JVM. Ne vom uita la câteva exemple în care Grails ne atrage ca dezvoltatori Java și ar putea tenta pe altcineva să-i dea o șansă.
Povestea
Într-un startup pentru care am lucrat, am avut exact această problemă. Aveam o aplicație de primăvară cu care devenise greu de lucrat. Odată cu creșterea din ce în ce mai mare, am constatat curând că refactorizarea și adăugarea de funcționalități ne luau mult mai mult decât ar trebui. Combinarea acestora cu alte motivații ne-a determinat să ne rescriem aplicația de bază. Am fost, de asemenea, deschiși să schimbăm sau să înlocuim tehnologia existentă. Grails a părut o alegere viabilă, deoarece rulează în JVM și este construit pe baza tehnologiilor pe care le cunoșteam deja. Folosește limbajul de programare Groovy dar, în același timp, vă permite să îl amestecați cu Java. Așa că am făcut pasul.
Cu toată viteza înainte
Un lucru la care Grails excelează cu adevărat este facilitarea începerii unui nou proiect. Este la fel de simplu ca rularea unei comenzi care creează structura proiectului cu toate folderele necesare pentru clasele pe care le vei adăuga mai târziu. Adăugarea de clase de model, controlere, servicii și pagini web necesită un efort la fel de minim. Singurul lucru de care trebuie să aveți grijă este să numiți și să plasați corect lucrurile. Spre deosebire de Java, practic nu există niciun cod standard care trebuie să existe doar pentru că trebuie să fie. Acest lucru este parțial posibil prin utilizarea Spring și Hibernate, care sunt doi dintre pilonii Grails, precum și a conceptului de codificare prin convenție. Pentru a rula proiectul, Grails vine la pachet cu Apache Tomcat ca server de dezvoltare. Tot ce trebuie să facem este să rulăm proiectul în IDE-ul nostru și serverul va fi pornit cu codul nostru implementat. De asemenea, Grails' Object Relational Mapping (GORM) cu Hibernate se va ocupa de crearea bazei de date pentru noi. Pentru a folosi o bază de date existentă, trebuie să configuram proprietățile conexiunii JDBC sau pur și simplu să o lăsăm implicit pentru a folosi o instanță în memorie. Odată ce serverul cu Grails rulează (necesită puțin mai mult decât o aplicație Spring MVC), putem modifica codul, iar funcționalitatea de implementare la cald va menține sesiunea noastră de depanare echipată cu cea mai recentă versiune. Singurele clase care nu pot fi reîncărcate în acest fel sunt clasele de entități.
Popularea bazei de date se poate face folosind scripturi SQL, dar acest lucru poate deveni plictisitor. Toate proiectele Grails conțin o clasă Bootstrap care va fi rulată atunci când aplicația noastră este rulată. În această clasă, putem stoca sau modifica datele și astfel inițializam starea aplicației noastre. Acest lucru s-a dovedit foarte util pentru noi, așa că avem imediat câteva cazuri de testare în versiunea de dezvoltare.
Manipularea datelor
Unul dintre lucrurile care ne-a atras imediat atenția cu Grails a fost ușurința de a lucra cu date. Citirea din baza de date este o sarcină care trebuie făcută din nou și din nou. Și de multe ori este simplu. Cum ar fi preluarea uneia sau mai multor entități care îndeplinesc anumite criterii și apoi agregarea lor. De ce să nu folosiți un Finder dinamic pentru asta? Este o modalitate de a interoga datele în care metodele sunt create dinamic în timpul execuției. Tot ce trebuie să faci este să urmezi o convenție de denumire.
def users = User.findAllByLastNameLikeOrAgeGreaterThan('Doe%', 30)
Linia de deasupra liniei va prelua toate obiectele User cu numele de familie care încep cu „Doe” sau cu vârsta mai mare de 30 de ani. Da, nu este un caz foarte sofisticat, dar înțelegeți esențialul.
Ce se întâmplă dacă am dori să filtram această listă suplimentar pentru cele care au proprietatea „failedLogins” mai mare de 10? Și dacă am vrea să le sortăm după data la care au fost create? Și dacă am vrea să le concatenăm prenumele sau să găsim vârsta maximă a utilizatorilor returnați?
users = users.findAll() { it.failedLogins > 10 } users = users.sort { it.dateCreated } def firstNamesString = users.firstName.join(', ') def maximumAge = users.age.max()
Exemplele de mai sus pot părea simple, dar arată cât de puternic poate fi Grails pentru interogarea, filtrarea și manipularea datelor. În Java 8, puteți obține rezultate similare pentru unele dintre aceste cazuri, dar va necesita totuși mai mult cod decât Grails.
Uneori vreau să creez diferit
Un constructor dinamic sau un constructor de argument numit este o caracteristică pe care mulți dintre noi am vrut să o avem în Java. Este frumos să definiți ce constructori permite o anumită clasă, dar în multe cazuri doriți doar să setați unele proprietăți și să obțineți instanța blestemată. Groovy adaugă un constructor special pentru fiecare entitate care ia practic eleganța unei hărți ca intrare și setează proprietățile cu intrările hărții.
def Person = new Person(name: 'Batman', age: 57)
Această abordare duce la un cod mult mai expresiv și evită necesitatea întregului cod standard al constructorului.
Și BTW, iată câteva exemple de minunatie și eleganță a hărților lui Groovy:
def emptyMap = [:] def map = [bread:3, milk:5, butter:2] map['bread'] = 4 map.milk = 6
Acesta este un alt exemplu al modului în care codul poate fi scurt și simplu, dar puternic. Acesta arată cum poate fi utilizată inițializarea în linie și cum pot fi manipulate valorile hărții într-un mod similar cu proprietățile obiectului. Nu este nevoie să apelați metode tradiționale Java pentru manipularea de bază, cu excepția cazului în care doriți cu adevărat.
Avem nevoie de mai multă putere!
Desigur, nu există un cadru care să poată face totul, dar atunci când completăm golurile, ar trebui să vedem ce altceva ar putea fi deja disponibil înainte de a încerca să implementăm propria noastră soluție. Pentru a ne extinde arsenalul de funcționalități bazate pe Grails, putem folosi pluginuri Grails. Instalarea unui plugin se face pur și simplu prin adăugarea unei alte linii în clasa BuildConfig
care este prezentă în fiecare proiect Grails (convenția codului lovește din nou!).

compile ':spring-security-core:2.0-RC4'
Linia de mai sus adaugă nucleul de securitate Spring la aplicația noastră și practic nu mai este nevoie de configurație pentru a încorpora această funcționalitate.
Acestea fiind spuse, permiteți-mi să vă povestesc despre un caz cu care a trebuit să ne ocupăm. Aveam nevoie să implementăm o căutare care acoperă mai multe entități de date. Grails are un plugin Elasticsearch care este ușor de utilizat. După cum am menționat anterior, trebuie doar să facem referință la plugin în fișierul de configurare și suntem gata de plecare. Dacă vrem să căutăm entități dintr-o anumită clasă, trebuie doar să adăugăm o proprietate statică „căutabilă” la acea clasă. Și dacă vrem, putem chiar să limităm proprietățile care vor fi permise să fie căutate.
class User { static searchable = { only = name } String name Double salary }
Este un cod atât de mic, dar sub capotă, Grails și pluginul Elasticsearch vor indexa automat toți utilizatorii după nume și ne vor permite să căutăm după nume. Apelul de căutare real este, de asemenea, foarte concis:
User.search("${params.query}")
Dacă nu vrem, nu va trebui niciodată să atingem indicele Lucene. Totul se va face automat pentru noi. Pluginul are chiar și un API pentru afișarea rezultatelor căutării – poate evidenția potrivirea găsită în textul căutat. Acesta este doar un exemplu în care un plugin poate oferi un pachet uriaș de funcționalități care ne pot face mult mai eficienți, evitând nevoia de a-l implementa noi înșine.
Încă avem nevoie de mai multă putere
Pluginurile sunt grozave, dar uneori nu avem nevoie de un întreg plugin, vrem doar ceva în plus. Îți amintești ultima dată când ai vrut să ai o metodă suplimentară pe o clasă Java existentă, dar nu ai vrut (sau nu ai putut) să le extinzi/înlocui? În Groovy, puteți adăuga metode și proprietăți la clasele existente sau chiar doar anumite instanțe ale acestora. De exemplu, puteți adăuga o metodă de formatting
la clasa java.util.Date
, care este minunată atunci când doriți să formatați datele în mod constant și pur și simplu nu doriți să scrieți clase util statice sau să definiți diferite filtre.
Date.metaClass.formatDate = { delegate.format("dd.MM.yyyy") }
Ce se întâmplă dacă doriți să sortați o listă de utilizatori după o valoare calculată și aveți nevoie de aceasta doar într-un caz (adică adăugarea unei noi metode în clasa User ar fi poluantă)? Puteți adăuga o proprietate în fiecare dintre aceste instanțe și apoi pur și simplu sortați sau filtrați colecția după acea proprietate:
user.metaClass.computedProp = 312 * 32 * 3
Autorii groovy au adăugat deja o mulțime de îmbunătățiri la unele dintre clasele de bază Java, așa că nu trebuie să facem acest lucru. Mai jos sunt câteva exemple.
Folosind „minus” pentru a elimina toate elementele dintr-o colecție care sunt prezente într-o altă colecție.
assert [1, 2, 3, 4, 4, 5] - [2, 4] == [1, 3, 5]
Metode suplimentare pentru manipularea obiectelor java.util.Date
care sunt utile de atâtea ori, cum ar fi adăugarea/scăderea zilelor din date sau obținerea/setarea unui anumit câmp al datei fără a-l converti în Calendar
sau a utiliza biblioteci suplimentare.
def yesterdayAllMyTroublesSeemedSoFarAway = new Date() - 1 def myAwesomeAnniversaryYear = myAwesomeDate[Calendar.YEAR] + 1 myAwesomeDate.set(year: myAwesomeAnniversaryYear, second: 0)
Când doriți să obțineți cu adevărat descriptiv cu manipularea datei, puteți utiliza pur și simplu clasa TimeCategory
adăugată Groovy:
use (TimeCategory) { println 1.minute.from.now println 10.hours.ago def someDate = new Date() println someDate - 3.months }
Un ciocan și un cui
Apoi sunt IDE-urile. GGTS și IntelliJ IDEA bazate pe Eclipse sunt configurate pentru a lucra cu Grails. Ei înțeleg structura proiectului (și vă vor ajuta să navigați prin foldere și resurse) și au comenzi rapide pentru comenzile pe care le veți folosi cel mai des (de exemplu, adăugați controler, adăugați o pagină, rulați un proiect etc.). Cu Grails veți executa comenzi (pentru a rula un proiect sau pentru a configura o nouă funcționalitate plugin) și veți avea nevoie de diferite configurații, care sunt acoperite și de IDE-uri. Completarea codului funcționează bine în paginile de șabloane web Grails, unde veți face adesea referire la controlere și acțiuni. Există, de asemenea, alte IDE-uri care pot fi utilizate cu Grails, cum ar fi Netbeans, TextMate, Emacs și altele.
Dar partea întunecată?
La fel ca în orice în viață, există și avertismente cu Grails. Se face multă magie sub capotă, ceea ce poate fi adesea un lucru bun, dar uneori rezultatul nu va fi cel așteptat. Erori se vor întâmpla doar din cauza faptului că nu folosiți tastarea (da, tipurile sunt opționale în Groovy) și nu sunt suficient de atenți. Și poate nu vei observa o eroare până nu va fi prea târziu. De asemenea, este foarte tentant să scrii versuri pentru a-ți impresiona colegii. Si tu. Dar aceste linii puternice de cod ar putea să nu fie la fel de explicite pentru colegii tăi. Sau chiar pentru tine în câteva luni. De aceea cred că Grails necesită mai multă disciplină de programare decât unele dintre cadrele mai tradiționale.
Timpul inseamna bani
Codarea nu ar trebui să ia mai mult timp doar pentru că cadrul dvs. actual o cere. Mai ales cu numărul din ce în ce mai mare de startup-uri în zilele noastre, este important să ne concentrăm asupra sarcinilor care contează cu adevărat și să fim cât mai eficiente. Timpul este într-adevăr bani și timpul de piață este esențial. Trebuie să fii capabil să acționezi rapid și să implementezi soluția înainte ca timpul să expire și concurența să te învingă.
Prietenii mei care lucrează cu Ruby on Rails sau Python/Django îmi spuneau de mult cât de cool sunt acele tehnologii. Și mi s-a părut o prostie să mă gândesc cât de mult timp mi-a luat în Java să scriu cod care stochează ceva în baza de date și îl afișează într-o pagină web. Graals poate fi într-adevăr un răspuns util. Nu este că nu ați putea face acest lucru cu Java pur, Spring MVC și Hibernate. Ai putea. Aplicația dvs. ar putea chiar să ruleze puțin mai repede. Dar vei termina treaba mai repede cu Grails.