Dlaczego programiści Java powinni dać Grailsowi szansę?
Opublikowany: 2022-03-11Java ma ekosystem, który dojrzał przez lata rozwoju, czyniąc ją jedną z najbardziej niezawodnych platform. Jednak brakuje mu środków niezbędnych do szybkiego wykonania pracy, zwłaszcza w przypadku takich rzeczy, jak aplikacje internetowe. Próbując uniknąć frustracji związanych z tego typu problemami, programiści często wybierają zamiast tego języki implementacyjne i swoje nowoczesne frameworki internetowe, takie jak Ruby z Ruby on Rails, Python z Django i tak dalej. W przeciwieństwie do Javy, zapewniają one znacznie bardziej uproszczoną ścieżkę do budowania aplikacji internetowej.
Na szczęście dla programistów Java, którzy chcą tworzyć aplikacje internetowe, istnieje lepszy sposób i obejmuje Grails. W tym artykule zobaczymy, jak Grails z Groovy jest realną alternatywą w świecie JVM. Przyjrzymy się kilku przykładom, w których Grails przemawia do nas jako programistów Javy i może kusić kogoś innego, aby również spróbować.
Historia
W startupie, w którym pracowałem, mieliśmy dokładnie taki problem. Mieliśmy aplikację Spring, z którą ciężko się pracowało. Wraz z jej rozwojem szybko odkryliśmy, że refaktoryzacja i dodawanie funkcjonalności zabierało nam znacznie więcej czasu niż powinno. Połączenie tego z innymi motywacjami skłoniło nas do podjęcia decyzji o przepisaniu naszej podstawowej aplikacji. Byliśmy również otwarci na zmianę lub wymianę istniejącego stosu technologicznego. Grails wyglądał na realny wybór, ponieważ działa w JVM i jest zbudowany na bazie technologii, które już znaliśmy. Wykorzystuje język programowania Groovy, ale jednocześnie pozwala mieszać go z Javą. Więc podjęliśmy decyzję.
Cała naprzód
Jedną z rzeczy, w których Grails naprawdę się wyróżnia, jest ułatwienie rozpoczęcia nowego projektu. Jest to tak proste, jak uruchomienie polecenia, które tworzy strukturę projektu ze wszystkimi folderami potrzebnymi dla klas, które dodasz później. Dodanie klas modeli, kontrolerów, usług i stron internetowych wymaga podobnie minimalnego nakładu pracy. Jedyne, o co musisz zadbać, to prawidłowe nazywanie i umieszczanie elementów. W przeciwieństwie do Javy, praktycznie nie ma standardowego kodu, który musi tam być tylko dlatego, że musi. Jest to częściowo możliwe dzięki wykorzystaniu Spring i Hibernate, które są dwoma filarami Grails, a także koncepcji kodowania przez konwencję. Aby uruchomić projekt, Grails jest dostarczany w pakiecie z Apache Tomcat jako serwerem programistycznym. Wystarczy, że uruchomimy projekt w naszym IDE, a serwer zostanie odpalony z wdrożonym naszym kodem. Również Grails' Object Relational Mapping (GORM) z Hibernate zajmie się stworzeniem bazy danych za nas. Aby użyć istniejącej bazy danych, musimy skonfigurować właściwości połączenia JDBC lub po prostu pozostawić domyślną instancję w pamięci. Gdy serwer z Grails jest już uruchomiony (zajmuje trochę więcej niż aplikacja Spring MVC), możemy zmodyfikować kod, a funkcja gorącego wdrożenia utrzyma naszą sesję debugowania w najnowszej wersji. Jedynymi klasami, których nie można przeładować w ten sposób, są klasy encji.
Wypełnianie bazy danych można wykonać za pomocą skryptów SQL, ale może to być nużące. Wszystkie projekty Grails zawierają klasę Bootstrap, która zostanie uruchomiona po uruchomieniu naszej aplikacji. W tej klasie możemy przechowywać lub modyfikować dane i tym samym inicjować stan naszej aplikacji. Okazało się to dla nas bardzo przydatne, więc od razu mamy kilka przypadków testowych w wersji rozwojowej.
Manipulowanie danymi
Jedną z rzeczy, które od razu przykuły naszą uwagę w Grails, była łatwość pracy z danymi. Czytanie z bazy danych to zadanie, które trzeba powtarzać w kółko. I wiele razy jest to proste. Jak pobieranie jednego lub więcej podmiotów spełniających określone kryteria, a następnie ich agregowanie. Dlaczego nie użyć do tego dynamicznego szukacza? Jest to sposób odpytywania danych, w którym metody są tworzone dynamicznie w czasie wykonywania. Wszystko, co musisz zrobić, to przestrzegać konwencji nazewnictwa.
def users = User.findAllByLastNameLikeOrAgeGreaterThan('Doe%', 30)
Powyższy wiersz spowoduje pobranie wszystkich obiektów użytkownika z nazwiskami zaczynającymi się od „Doe” lub w wieku powyżej 30 lat. Tak, niezbyt wyrafinowany przypadek, ale rozumiesz.
Co by było, gdybyśmy chcieli dodatkowo przefiltrować tę listę pod kątem tych, które mają właściwość „failedLogins” większą niż 10? A co, gdybyśmy chcieli je posortować według daty utworzenia? A co by było, gdybyśmy chcieli połączyć ich imiona lub znaleźć maksymalny wiek zwracanych użytkowników?
users = users.findAll() { it.failedLogins > 10 } users = users.sort { it.dateCreated } def firstNamesString = users.firstName.join(', ') def maximumAge = users.age.max()
Powyższe przykłady mogą wydawać się proste, ale pokazują, jak potężne mogą być Grails w zakresie zapytań, filtrowania i manipulowania danymi. W Javie 8 możesz osiągnąć podobne wyniki w niektórych z tych przypadków, ale nadal będzie to wymagało więcej kodu niż Grails.
Czasami chcę tworzyć inaczej
Konstruktor dynamiczny lub nazwany konstruktor argumentów to funkcja, którą wielu z nas chciało mieć w Javie. Fajnie jest zdefiniować, na które konstruktory zezwala dana klasa, ale w wielu przypadkach po prostu chcesz ustawić pewne właściwości i uzyskać daną instancję. Groovy dodaje specjalny konstruktor dla każdej encji, który zasadniczo przyjmuje elegancję mapy jako dane wejściowe i ustawia właściwości za pomocą wpisów mapy.
def Person = new Person(name: 'Batman', age: 57)
Takie podejście prowadzi do kodu, który jest znacznie bardziej ekspresyjny i pozwala uniknąć konieczności stosowania całego kodu konstruktora.
A tak przy okazji, oto kilka przykładów wspaniałości i elegancji map Groovy'ego:
def emptyMap = [:] def map = [bread:3, milk:5, butter:2] map['bread'] = 4 map.milk = 6
To kolejny przykład tego, jak kod może być krótki i prosty, a jednocześnie potężny. Pokazuje, w jaki sposób można użyć inicjalizacji wbudowanej i jak można manipulować wartościami mapy w sposób podobny do właściwości obiektu. Nie ma potrzeby wywoływania tradycyjnych metod Java w celu podstawowej manipulacji, chyba że naprawdę tego chcesz.
Potrzebujemy więcej mocy!
Oczywiście nie ma frameworka, który może zrobić wszystko, ale kiedy uzupełniamy luki, powinniśmy zobaczyć, co jeszcze może być dostępne, zanim spróbujemy zaimplementować własne rozwiązanie. Aby rozszerzyć nasz arsenał funkcji opartych na Grails, możemy użyć wtyczek Grails. Instalowanie wtyczki odbywa się po prostu przez dodanie kolejnej linii w klasie BuildConfig
, która jest obecna w każdym projekcie Grails (znów pojawia się konwencja kodu!).

compile ':spring-security-core:2.0-RC4'
Powyższa linia dodaje rdzeń bezpieczeństwa Spring do naszej aplikacji i praktycznie nie ma potrzeby dodatkowej konfiguracji, aby włączyć tę funkcjonalność.
Biorąc to pod uwagę, pozwól, że opowiem ci o sprawie, którą mieliśmy do czynienia. Musieliśmy wdrożyć wyszukiwanie obejmujące kilka jednostek danych. Grails ma wtyczkę Elasticsearch, która jest bardzo prosta w użyciu. Jak wspomniano wcześniej, wystarczy odwołać się do wtyczki w pliku konfiguracyjnym i gotowe. Jeśli chcemy szukać jednostek z określonej klasy, wystarczy dodać do tej klasy właściwość statyczną „przeszukiwalną”. A jeśli chcemy, możemy nawet ograniczyć nieruchomości, które będą mogły być przeszukiwane.
class User { static searchable = { only = name } String name Double salary }
To tak mało kodu, ale pod maską Grails i wtyczka Elasticsearch automatycznie zaindeksują wszystkich użytkowników według nazwy i umożliwią nam wyszukiwanie według nazwy. Samo wyszukiwanie jest również bardzo zwięzłe:
User.search("${params.query}")
Jeśli nie chcemy, nigdy nie będziemy musieli dotykać indeksu Lucene. Wszystko zostanie dla nas zrobione auto-magicznie. Wtyczka ma nawet interfejs API do wyświetlania wyników wyszukiwania – może podświetlić dopasowanie znalezione w wyszukiwanym tekście. To tylko przykład, jak wtyczka może zapewnić ogromny pakiet funkcji, które mogą sprawić, że będziemy o wiele bardziej wydajni, unikając konieczności samodzielnego jej wdrażania.
Nadal potrzebujemy więcej mocy
Wtyczki są świetne, ale czasami nie potrzebujemy całej wtyczki, po prostu chcemy czegoś dodatkowego. Czy pamiętasz, kiedy ostatnio chciałeś mieć dodatkową metodę w istniejącej klasie Javy, ale nie chciałeś (lub nie mogłeś) jej rozszerzyć/nadpisać? W Groovy możesz dodawać metody i właściwości do istniejących klas, a nawet tylko niektórych ich wystąpień. Na przykład, możesz dodać metodę formatting
do klasy java.util.Date
, która jest niesamowita, gdy chcesz konsekwentnie formatować daty i po prostu nie chcesz pisać statycznych klas użytkowych lub definiować różnych filtrów.
Date.metaClass.formatDate = { delegate.format("dd.MM.yyyy") }
Co zrobić, jeśli chcesz posortować listę użytkowników według obliczonej wartości i potrzebujesz tego tylko w jednym przypadku (np. dodanie nowej metody w klasie User będzie zanieczyszczać)? Możesz dodać właściwość do każdej z tych instancji, a następnie po prostu posortować lub przefiltrować kolekcję według tej właściwości:
user.metaClass.computedProp = 312 * 32 * 3
Autorzy groovy dodali już wiele ulepszeń do niektórych podstawowych klas Javy, więc nie musimy tego robić. Poniżej kilka przykładów.
Użycie „minus” do usunięcia wszystkich elementów z kolekcji, które są obecne w innej kolekcji.
assert [1, 2, 3, 4, 4, 5] - [2, 4] == [1, 3, 5]
Dodatkowe metody manipulowania obiektami java.util.Date
, które przydają się tak wiele razy, takie jak dodawanie/odejmowanie dni od dat lub pobieranie/ustawianie określonego pola daty bez konwertowania go do Calendar
lub korzystania z dodatkowych bibliotek.
def yesterdayAllMyTroublesSeemedSoFarAway = new Date() - 1 def myAwesomeAnniversaryYear = myAwesomeDate[Calendar.YEAR] + 1 myAwesomeDate.set(year: myAwesomeAnniversaryYear, second: 0)
Jeśli chcesz naprawdę uzyskać opis przy manipulacji datami, możesz po prostu użyć dodanej przez Groovy klasy TimeCategory
:
use (TimeCategory) { println 1.minute.from.now println 10.hours.ago def someDate = new Date() println someDate - 3.months }
Młotek i gwóźdź
Następnie są IDE. Oparte na Eclipse GGTS i IntelliJ IDEA są skonfigurowane do pracy z Grails. Rozumieją strukturę projektu (i pomagają poruszać się po folderach i zasobach) oraz mają skróty do najczęściej używanych poleceń (np. dodaj kontroler, dodaj stronę, uruchom projekt itp.). Dzięki Grails będziesz wykonywać polecenia (aby uruchomić projekt lub skonfigurować nową funkcjonalność wtyczki) i będziesz potrzebować różnych konfiguracji, co jest również objęte IDE. Uzupełnianie kodu działa dobrze na stronach szablonów internetowych Grails, gdzie często odwołujesz się do kontrolerów i akcji. Istnieją również inne IDE, których można używać z Grails, takie jak Netbeans, TextMate, Emacs i inne.
A co z ciemną stroną?
Tak jak ze wszystkim w życiu, z Graalami są też pewne zastrzeżenia. Pod maską dzieje się wiele magii, co często może być dobrą rzeczą, ale czasami rezultat nie będzie taki, jakiego się spodziewałeś. Błędy będą się pojawiać tylko dlatego, że nie używasz pisania (tak, typy są opcjonalne w Groovy) i nie jesteś wystarczająco ostrożny. A może nie zauważysz błędu, dopóki nie będzie za późno. Ponadto bardzo kuszące jest pisanie linijek, które zaimponują współpracownikom. I siebie. Ale te potężne wiersze kodu mogą nie być tak oczywiste dla twoich współpracowników. Albo nawet do siebie za kilka miesięcy. Dlatego uważam, że Grails wymaga większej dyscypliny programistycznej niż niektóre z bardziej tradycyjnych frameworków.
Czas to pieniądz
Kodowanie nie powinno zająć więcej czasu tylko dlatego, że wymaga tego Twój obecny framework. Zwłaszcza w obliczu coraz większej liczby startupów w dzisiejszych czasach ważne jest, aby skupić się na zadaniach, które naprawdę mają znaczenie i być tak wydajnym, jak to tylko możliwe. Czas to rzeczywiście pieniądz, a czas wprowadzenia na rynek ma kluczowe znaczenie. Musisz być w stanie działać szybko i wdrożyć rozwiązanie, zanim skończy się czas, a konkurencja Cię wyprzedzi.
Moi przyjaciele pracujący z Ruby on Rails lub Python/Django od dawna mówią mi, jak fajne są te technologie. I naprawdę głupio było pomyśleć, ile więcej czasu zajęło mi w Javie napisanie kodu, który przechowuje coś w bazie danych i wyświetla to na stronie internetowej. Grails rzeczywiście może być przydatną odpowiedzią. Nie chodzi o to, że nie można tego zrobić w czystej Javie, Spring MVC i Hibernate. Mógłbyś. Twoja aplikacja może nawet działać trochę szybciej. Ale dzięki Grails szybciej wykonasz pracę.