Tworzymy model aplikacji przy pomocy JDL. JHipster tutorial part 5

Witaj!

Po przyjemnym i ciepłym weekendzie chciałbym zaprosić Cię na ciąg dalszy przygód z JHispterem. Będziemy dziś tworzyć model danych. 🙂

W ostatniej części poradnika udało nam się dodać do aplikacji MoocYourLife jedną encję. Jak pewni zauważyłeś, użycie do tego celu generatora dostarczonego przez JHipstera usprawniło mocno pracę. Tworznie wszystkich plików ręcznie byłoby o wiele bardziej czasochłonne. Ciągle jednak, jeżeli chcemy mieć wiele encji, czeka nas trochę zabawy z odpalaniem tego generatora wiele razy i uważania za każdym razem, żeby gdzieś się nie pomylić. Aby rozwiązać ten problem, skorzystamy z języka JDL – JHipster Domain Language. Pozwoli on nam zaprojektować model danych naszej aplikacji, a następnie wygenerować wszystkie encje na raz.

Takie podejście ma jeszcze jedną zaletę. Mianowicie, kiedy tworzymy jakiś projekt od zera, to jedną z pierwszych rzeczy jaką powinniśmy przemyśleć jest model danych. Uświadomimy sobie wtedy dokładnie co nasza aplikacja ma robić, jakie dane przechowywać i jakie relacje powinny być między tymi danymi. Właśnie dlatego zabieramy się za tę czynność teraz. 🙂

Zapraszam zatem na małą zabawę w architeka systemów. 🙂

Czym jest JDL?

Jest to język, który pozwala nam opisać domenę naszej aplikacji. Innymi słowy, przy pomocy tego języka zdefiniujemy encje i relacje, a następnie całą definicję modelu wrzucimy do JHipstera.

Do pisania naszego modelu polecem JDL Studio (link tutaj), które jest bardzo prostym narzędziem on-line do edycji i wizualizacji kodu JDL.

Uruchommy zatem JDL Studio. Po lewej stronie będziemy pisać kod, a po prawej zobaczymy wizualiacją modelu danych. Po otwarciu aplikacji widzimy przykładowy model, ale skasujmy go całego – chcemy zacząć od zera.

Tworzymy encję

Zacznijmy od stworzenia encji. Robi się to bardzo prosto:

entity Course {}

Jeżeli chcemy, aby tabela w bazie danych miała inną nazwę niż klasa w Javie, podajemy tę nazwę w nawiasach okrągłych:

entity Course (course_table) {}

Następnie definiujemy pola danej encji:

entity Course {
name String required,
description String required,
begin_date LocalDate,
active Boolean required
}

jak widzisz deklarowanie pól jest bardzo proste. Podajemy nazwę, typ i ewentualnie informację o walidacji. Jeżeli pracujemy z relacyjną bazą danych, (a przypomnę, że JHipster obsługuje też inne bazy) mamy dostępne takie typy pól:

  • String
  • Integer
  • Long
  • BigDecimal
  • Float
  • Double
  • Enum
  • Boolean
  • LocalDate
  • ZonedDateTime
  • Blob
  • AnyBlob
  • ImageBlob
  • TextBlob

Ważne jest to, że JHipster z automatu do każdej encji dodaje pole „id”! Nie musimy o to się martwić.

Dodajemy relacje

Żeby móc stworzyć jakąkolwiek relacje, dodajmy jeszcze jedną encję:

entity Lesson {
name String required,
}

Chcemy, żeby Kurs składał się z wielu Lekcji. Dodajmy zatem relację OneToMany:

relationship OneToMany {
Course{lesson} to Lesson{course required}
}

Jak zapewne zauważyłeś, możemy dodać ograniczenie „required” – nie będą wtedy mogły istniej Lekcje bez przypisanego im Kursu.

Domyślnie JDL łączy encję poprzez pole „Id”. Możemy to jednak zmienić. Gdybyśmy chcieli użyć przykładowo pola „name”, wyglądałoby to w ten sposób:

relationship OneToMany {
Course{lesson} to Lesson{course(name) required}
}

Odpowiednie pole podajemy po prostu w nawiasie okrągłym.

JDL obsługuje następujące typy relacji:

  • OneToOne
  • OneToMany
  • ManyToOne
  • ManyToMany

JDL ma fajną opcję dzięki której nie będziemy generować zbyt dużo kodu. Takie same relacje możemy grupować w ten sposób:

relationship OneToMany {
A{b} to B{a},
B{c} to C{b}
}

Enumeracje

JDL pozwala zdefiniować własnego „enuma”. Np.:

enum Language {
POLISH, ENGLISH, FRENCH
}

Następnie możemy używać takiego typu przy deklaracji encji:

entity Course {
name String required,
description String required,
begin_date LocalDate,
active Boolean required,
language Language
}

Dodatkowe możliwości

JDL udostępnia jeszcze szereg dodatkowych opcji, z których skorzysta potem JHipster.

Service

Jeżeli nie zdefiniujemy żadnych serwisów, klasy REST kontrolera będą bezpośrednio korzystać z klas DAO. Taki rozwiązanie jest dobre, jeżeli nasza aplikacja nie jest złożona i służy przede wszystkim do prostych operacji CRUD. Jeżeli jednak nasz przypadek jest trochę bardziej skomplikowany, powinniśmy stworzyć klasę serwisową, która będzie pomiędzy tymi dwoma warstwami i w niej zawrzeć dodatkową logikę.

Dlatego jeżeli chcemy dodać serwis, definiujemy go:

service Course with serviceClass

albo:

service Course with serviceImpl

Jaka jest różnica między tymi dwoma możliwościmi? W pierwszym przypadku zostanie po prostu utworzona klasa seriwsowa. Natomiast w drugim, poza klasą zostanie utworzony jeszcze jej interfejs, który to będzie używany w REST kontrolerze.

DTO

Możemy też chcieć używać klas Data Transfer Object (DTO). Wpisujemy wtedy:

dto Course with mapstruct

Dzięki tekiemy podejściu możemy dokładnie określić jak obiekt przychodzący do REST kontrolera ma być zamieniany na naszą encję. Czasami taka możliwość jest potrzebna. Dodam tylko, że transformacja klas odbywa się przy pomocy narzędzie MapStruct.

Paginacja

Wpisując:

paginate Course with infinite-scroll

nasze encje typu Kurs będą przewijane poprzez infinite scrolla. Możemy też użyć paginacji z przyciskami „następny” oraz „poprzedni”:

paginate Course with pager

Tak po krótce wygląda JDL oraz najważniejsze jego funkcje, których będę używał. Jak sam widzisz, korzystając z tego języka opis modelu danych jest bardzo prosty. Jest to niewątliwie jego ogromna zaleta.

Można oczywiście narzekać, że JDL ma trochę mało możliwości i jest dość ubogi. To prawda, ale pamiętajmy, że jego głównym celem jest szybsze wygenerowanie encji. Jeżeli chcemy zmienić coś bardziej szczegółowo (np. typ w bazie danych, na taki którego JDL nie obsługuje), to zawsze możemy to zrobić ręcznie.

Model MoocYourLife w JDL

Skoro już umiemy używać JDLa, trzeba stworzyć model aplikacji! 🙂 Trochę nad nim posiedziałem i udało mi się zrobić coś, co zaimportuję do JHipstera. Należy jednak pamiętać, że to co teraz zrobiłem to jest jakaś pierwsza wersja, która będzie pewną bazą. Naturalne jednak jest to, że podczas powstawania aplikacji model danych ewoluuje i zmienia się.

Link do niego w JDL-Studio jest tutaj, a poniżej diagram:

Podstawą naszego systemu jest Course, czyli prawdziwy kurs internetowy, na który użytkownicy będą mogli się zapisać. Kurs składa się z Lekcji – jest to po prostu pewna forma podziału materiału na mniejsze części. Każda lekcja to zestaw Elementów. Jest ich kilka rodzai:

  • TEXT – kawałek zwykłego tekstu
  • VIDEO – film
  • AUDIO – plik dźwiękowy
  • QUIZ – jest to po prostu zestaw pytań zadanych do uczestnika

Także jak widzisz, kurs internetowy to po prostu zestaw tekstów, filmów, plików dźwiękowych i quizów. Prosta, ale wystarczająca struktura.

Póki co założyłem, że mogą być dwa rodzaje (QuestionType) pytań w Quizach: pytanie jednokrotnego wyboru (SINGLE_SELECT) oraz pytania otwarte (OPEN).

Ponadto, dla każdego Kursu będzie forum, które składa się z Topiców, a każdy z nich z Postów. Każdy Post ma autora. Dodatkowo przewiduję dodawanie niezależnych Postów pod każdym Elementem Kusu.

Ładujemy plik do JHipstera

Na końcu najprzyjemniejsza rzecz, czyli tworzymy wszystkie nasze encje. 🙂 Pobieramy plik z modelem z JDL-Studio. Powinien mieć rozszerzenie .jh. Następnie uruchamiamy terminal i będąc w głównym katalogu projektu wpisujemy:

$ yo jhipster:import-jdl jhipster-jdl.jh

gdzie „jhipster-jdl.jh” to nazwa pliku pobranego z JDL-Studio.

I to tyle! 🙂

Zachęcam do uruchomienia aplikacji i sprawdzenia, czy naszę encję sie odpowiednio dodały.

Jak sam widzisz, tworzenie modelu danych w ten sposób nie jest skomplikowane i przyspiesza znacznie proces tworzenia encji w JHipsterze. Fajnie, że takie narzędzie zostało zrobione, choć istnieje dopiero od najnowszej, czwartej wersji JHisptera.

W razie pytań lub wątpliwości zachęcam do komentowania!

Trzymaj się i…

NIECH KOD BĘDZIE Z TOBĄ!

2 komentarze

    • Piotr Kalinowski

      Powinny, masz rację 🙂 Dlatego właśnie napisałem, że model będzie ewaluował. Na tym etapie najważniejsze jest dla mnie, żeby dobrze określić encje i relacje między nimi. Ewentualne atrybuty będę pewnie sukcesywnie dodawał.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *