Java 9: praktyczny przykład - trzy moduły
Programowanie modularne
Dziś szybki “przykład na kolanie” pokazujący jak napisać aplikację modularną. Przykładowa aplikacja będzie generatorem obrazów (bggen). Architektura modułów będzie bardzo prosta. Oto ona:
- moduł
api
zwiera zbiór interfejsów i klas pomocniczych - moduł
generator
pełni funkcję biblioteki, potencjalnie jednej z wielu, która implementuje interfejsy zdefiniowane wapi
- moduł
client
używa moduługenerator
na swoje potrzeby biznesowe.
Krok po kroku
Opiszę krok po kroku jak stworzyć taką aplikację.
Utworzenie projektu z trzema modułami
Używam edytora IntellijIdea Community. Tworzę standardowy projekt (javowy, nie używam mavena), a wewnątrz niego dodaję trzy moduły (i usuwam moduł “główny” utworzony automatycznie po utworzeniu aplikacji; chę mieć płaską strukturę projektu). Są to moduły w rozumieniu IntellijIdea - mają odrębne struktury katalogów, ustawienia SDK, bibliotek, katalogu wynikowego kompilacji itd.
Implementacja
api
definiuje interfejsRectangleGenerator
, którego jedyną funckją jest dostarczenie strumienia prostokątów (klasaRect
)generator
posiada prywatne implementacje tego interfejsu i udostępnia je jedynie przez metody static factory klasyGenerators
.client
będzie używał wygenerowanych przez dostępne implementacjeRectangleGenerator
a prostokątów i tworzył obrazy o zadanej rozdzielczości (w przykładzie prostokąty są wypisywane na standardowe wyjście).
Definiowanie modułów w rozumieniu java 9
Moduły w rozumieniu IntelliJIdea staną się modułami javy 9 tylko wówczas, gdy będą posiadały deskryptory modułu. Deskryptor modułu jest skompilowanym opisem modułu. Opis modułu to plik o nazwie module-info.java
.
Wewnątrz katalogów src
każdego z modułów tworzę opisy, z których wynika, że:
api
eksportuje pakietcom.kamilachyla.bggen.api
:
|
|
generator
używa modułuapi
i eksportujecom.kamilachyla.bggen.generator
:
|
|
client
posiada jedną klasę (Main
); używa moduługenerator
i klas/interfejsów z api:
|
|
Struktura plików na dysku wygląda teraz tak:
|
|
Kompilacja
Kompiluję trzy moduły w taki oto sposób:
- tworzę katalog mlib, gdzie będą się znajdowały klasy wynikowe (mlib będzie katalogiem zawierającym skompilowane moduły)
- kompiluję - niezależny od innych modułów - moduł
api
:
|
|
- kompilacja modułów zależnych od innych modułów wymaga podania ścieżki do katalogu z wymaganymi modułami, więc do skompilowania modułów
generator
orazclient
używam opcji wiersza poleceń--module-path mlib
:
|
|
Gotowe! Oto struktura katalogu mlib ze skompilowanymi modułami:
|
|
Uruchomienie
Uruchomienie aplikacji również wymaga podania ścieżki do katalogu z modułami (program java
również rozpoznaje opcję --module-path
), a samą klasę główną podaję poprzedzoną nazwą modułu w postaci <nazwa_modułu>/<pełna-nazwa-klasy>
:
|
|
I w rezultacie otrzymuję:
|
|
Generowanie wykresu zależności między modułami i pakietami
Narzędzie jdeps pozwala wygeerować graf zależności między pakietami/modułami w formacie .dot, z którego graphviz generuje wykres.
|
|
Ponwyższy wykres wygenerowałam bez zależności do pakietów z biblioteki standardowej; dla ciekawych - pełny wykres:
Źródła projektu dostępne są w projekcie bggen na githubie.
Ten wpis jest częścią serii java.
- 2021-09-12 - Java 18: co nowego? - przegląd JEP-ów
- 2021-21-09 - Java 17 - RandomGenerator i spółka
- 2021-15-09 - Java 17 - co nowego?
- 2021-04-03 - Java 15 - czym są sealed classes?
- 2021-26-02 - Java 13 i 14: Bloki tekstowe i rekordy
- 2021-24-02 - Java 12 - wyrażenie switch (preview feature)
- 2021-23-02 - Java 11 - HTTP Client i uruchamianie jednoplikowych programów
- 2021-18-02 - Java 9 - co to jest JShell i dlaczego warto używać REPL-a w Javie
- 2021-12-02 - Java 10 - var, nowe metody w Optional, kolekcje "unmodifiable"
- 2021-11-02 - Java 9 - nowości w bibliotece
- 2021-10-02 - Java 9: czy mogę stworzyć z mojej aplikacji binarkę?
- 2021-10-02 - Java 9: praktyczny przykład - trzy moduły
- 2021-08-02 - Java 8: praktyczny przykład - przewidywanie kolejnej daty w serii