1. Köhnə yanaşmanın problemləri
“Classpath-party”: hamı bir mətbəxdə
Modullar Java-da (9-cu versiyada) ortaya çıxmazdan əvvəl tətbiqin bütün kodu, kitabxanalar və asılılıqlar bir böyük yığın — classpath — içində toplanırdı. Kitabxanalar arasında faktiki sərhədlər yox idi: classpath-ə düşən istənilən sinif istənilən kəs tərəfindən tapılıb istifadə oluna bilərdi.
Ad toqquşmaları yaranırdı: iki kitabxana eyni tam ada malik sinif saxlayır, məsələn, com.example.Util — nəticədə “hansısa biri” seçilirdi, sizsə problemi artıq runtime-dakı qəribə davranışdan anlayırdınız.
Janrın klassikası — dependency hell: bir kitabxana logger-in 1.2 versiyasını tələb edir, digəri — 1.3-ü, nəticədə classpath-də hər ikisi olur. JVM hansını götürəcəyini bilmir və siz müəmmalı NoSuchMethodError alırsınız.
Və daha bir məsələ: sinif public elan edilsə də, kitabxananın daxili ehtiyacları üçün nəzərdə tutulubsa, başqa kod onu yenə də istifadə edə bilər — və prosesdə özünə nəsə zərər vura bilər. Böyük layihələr mina sahəsinə çevrilirdi, dəstək isə macəraya.
2. Java-da modul nədir?
Modul: deşikləri olan qutu kimi
Java 9-da modullu sistem (JPMS) yarandı. Modul — siniflər və paketlər olan bir qutudur, burada siz “deşikləri” özünüz açırsınız: kənara nəyi göstərdiyinizi açıq şəkildə bildirirsiniz (exports), nələri isə içəridə gizlədirsiniz. Və bəli: paketi export olunmayıbsa, hətta public sinif də digər modullara görünmür.
Rəsmi tərif
Modul — bağlı paketləri və sinifləri birləşdirən, kodu bölmənin məntiqi vahididir. Hər modul açıq şəkildə bildirir:
- nələri export edir — digər modullar üçün əlçatan edir (exports);
- və nələri import edir — hansı modullardan asılıdır (requires).
Modulun əsas xüsusiyyətləri:
- Aydın sərhədlər. Kənardan nə əlçatandır, nə deyil, dəqiq müəyyən edilir.
- Aydın asılılıqlar. Modul açıq requires olmadan başqa modulu “görmür”.
- İzolyasiya. Daxili detallar xarici aləmdən tam gizlənə bilər.
3. Modulluğun üstünlükləri
Yaxşılaşdırılmış enkapsulyasiya
Görünürlüğün yeni səviyyəsi — modul səviyyəsi — ortaya çıxdı. Sinif public olsa belə, onun paketi export edilmirsə, o, yalnız modul daxilində görünür. Kitabxananın daxili hissələri artıq “çölə sızmır”.
Asılılıqların açıq təsviri
Lazım olan asılılıqlar module-info.java-da sadalanır. Kompilyator və IDE siz asılı olduğunuz modulu göstərməyi unutmusunuzsa, əvvəlcədən xəbərdar edəcək.
Yaxşılaşdırılmış təhlükəsizlik və etibarlılıq
Daxili API-lərə çıxışın məhdudlaşdırılması təsadüfi və ya qəsdən müdaxiləni çətinləşdirir. Bu, iri kitabxanalar və platforma modulları üçün kritikdir.
“Kəsilmiş” JRE yaratmaq imkanı
jlink vasitəsilə yalnız lazım olan modullardan minimal runtime yığmaq olar. Bulud və embedded ssenarilərdə bu, disk sahəsinə və yaddaşa qənaət edir.
Bonus: startın sürətlənməsi və ölçünün kiçilməsi
Bütün modullar yox, yalnız həqiqətən istifadə olunanlar yüklənir — tətbiqlər daha tez başlayır və daha az resurs sərf edir.
4. Modullar harada istifadə olunur
Java-nın standart kitabxanasında
Java 9-dan başlayaraq, platformanın özü modulludur. Nümunələr:
- java.base — baza modulu (istənilən proqram üçün məcburidir).
- java.sql — verilənlər bazaları ilə iş.
- java.xml — XML ilə iş.
Əgər siz XML istifadə etmirsinizsə, java.xml modulu ümumiyyətlə sizin runtime-ınıza düşməyəcək.
Böyük tətbiqlərdə və kitabxanalarda
Monorepozitoriyanın hissələrini onlarla komandanın hazırladığı korporativ sistemlər üçün must-have. Modulluq münaqişələri azaldır və dəstəyi sadələşdirir.
Öz layihələrinizdə
Hətta pet-layihədə modullar arxitektura düşüncəsini məşq etdirməyə və kodu qaydasında saxlamağa kömək edir, “spagetti”dən qaçaraq.
5. Sintaksisin qısa icmalı: module-info.java
Ən vacibi — fayl module-info.java
Fayl module-info.java modulun mənbələrinin kökündə yerləşir və onun sərhədlərini və asılılıqlarını elan edir.
module my.awesome.module {
exports com.example.api; // Eksport olunan paket
requires java.sql; // Standart moduldan asılılıq
}
Əsas açar sözlər:
- module <ad> — modulu elan edir.
- exports <paket> — paketi digər modullar üçün əlçatan edir.
- requires <modul> — başqa moduldan asılılığı elan edir.
Minimal nümunə:
module com.myproject.core {
exports com.myproject.core.api;
}
Asılılıqla nümunə:
module com.myproject.app {
requires com.myproject.core;
requires java.sql;
}
Əlavə imkanlar (qısaca): refleksiya üçün opens, servislər üçün — uses və provides ... with ... (ətraflı — qabaqcıl mühazirələrdə).
6. Faydalı nüanslar
Modullar siniflər üçün “pasport” kimidir. Əvvəllər viza kimi public olan istənilən sinif tətbiq boyu “səyahət” edə bilirdi. İndi modul “pasportu” da lazımdır — paket export-u (exports). Onsuz sinif “evdə” qalır.
Dependency hell — real termindir. Əgər ClassNotFoundException: com.google.common.base.Strings görmüsünüzsə, artıq ora düşmüsünüz. Modullar sərt sərhədlər və asılılıqlar ilə bu “iblisləri” qovmaq üçün nəzərdə tutulub.
Artıq bütün Java modulludur. Hətta öz modullarınızı yazmırsınızsa belə, platforma artıq onlarla moduldan ibarətdir. Bu əmri yoxlayın:
java --list-modules
Bu, hazırlama prosesinə necə təsir edir
Siz kodun görünürlüğünü açıq şəkildə idarə edirsiniz və daxili paketlər artıq “təsadüfən” hamıya əlçatan olmur. IDE və kompilyator xətaları daha tez tutur: asılılığı elan etməyi unutmusunuzsa — layihə yığılmayacaq. Böyük sistemlərin dəstəyi sadələşir: kim kimdən asılıdır və dəyişikliklər nəyi poza bilər, anlamaq daha asan olur.
7. Modullara keçiddə tipik səhvlər
Səhv №1: paketi export etməyi unutmusunuz, amma sinif public-dir. Siz sinfi public kimi elan etmisiniz, lakin onun paketini export etməmisiniz — digər modullar onu istifadə edə bilməyəcək. Kompilyator belə bildirəcək: “Paket modul tərəfindən export edilmir”.
Səhv №2: requires vasitəsilə asılılığı elan etməmisiniz. Siz başqa moduldan tip istifadə edirsiniz, amma requires-i module-info.java-ya əlavə etməyi unutmusunuz. Nəticə — kompilyasiya xətası: “modul lazımi sinfi tapa bilmir”.
Səhv №3: modul adlarının təkrarlanması. Böyük layihədə iki modul təsadüfən eyni adı alıb. JVM bunu bağışlamır — adını dəyişin və vahid adlandırma qaydasına riayət edin.
Səhv №4: standart modulları unutmusunuz. Məsələn, JDBC istifadə edirsiniz, lakin requires java.sql; əlavə etməmisiniz. Java 8-də “belə də görünürdü”, 9+ versiyalarında isə — yox.
Səhv №5: başqa modulun daxili sinfini istifadə etməyə cəhd. Əgər paket export olunmursa, hətta public-sinif belə kənardan görünmür. Paketi export edin və ya API-ni “publik” qata çıxarın.
GO TO FULL VERSION