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ł
apizwiera zbiór interfejsów i klas pomocniczych - moduł
generatorpełni funkcję biblioteki, potencjalnie jednej z wielu, która implementuje interfejsy zdefiniowane wapi - moduł
clientużywa moduługeneratorna 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
apidefiniuje interfejsRectangleGenerator, którego jedyną funckją jest dostarczenie strumienia prostokątów (klasaRect)generatorposiada prywatne implementacje tego interfejsu i udostępnia je jedynie przez metody static factory klasyGenerators.clientbędzie używał wygenerowanych przez dostępne implementacjeRectangleGeneratora 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:
apieksportuje pakietcom.kamilachyla.bggen.api:
|
|
generatorużywa modułuapii eksportujecom.kamilachyla.bggen.generator:
|
|
clientposiada jedną klasę (Main); używa moduługeneratori 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
generatororazclientuż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...
- 2024-01-11 - Java 23 w praktyce
- 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