CodeGym /Kurslar /JAVA 25 SELF /Layihənin modullara bölünməsi: ən yaxşı təcrübələr

Layihənin modullara bölünməsi: ən yaxşı təcrübələr

JAVA 25 SELF
Səviyyə, Dərs
Mövcuddur

1. Layihəni nə zaman və niyə modullara bölmək lazımdır

Niyə hər şeyi bir modulda etmək düzgün deyil

Əgər siz kiçik laboratoriya işi və ya "Hello, World!" yazırsınızsa, modul sistemi artıq görünə bilər. Lakin layihə böyüdükcə — onlarla və yüzlərlə sinif, çoxlu paketlər, üçüncü tərəf kitabxanaları — xaos qaçılmaz olur. Bu, rəfləri olmayan kitabxanaya bənzəyir: kitab az olanda — dözüləndir, amma sonra nəsə tapmaq çətinləşir. Modullar — sizin rəflərinizdir: onlar nizam yaratmağa kömək edir və «mətbəxi» (reallaşdırmanı) gizlədir, çöldə yalnız «vitrini» (API) saxlayır.

Niyə modullara bölmək lazımdır

  • Məsuliyyətin bölüşdürülməsi: hər modul öz sahəsinə cavabdehdir (məsələn, MB, biznes məntiqi, UI).
  • Kodu təkrar istifadə: modulu başqa layihəyə qoşmaq olar.
  • Testlənmənin yaxşılaşdırılması: modullar müstəqil test edilir.
  • Təhlükəsizlik və enkapsulyasiya: çöldən yalnız API görünür, reallaşdırma gizlidir.
  • Dəstəyin asanlaşması: daha az «sehrli» əlaqə, asılılıqların aydın xəritəsi.
  • Sürətli yığma və deployment: yalnız dəyişən modullar yenidən yığılır.

Modullara nə zaman bölmək lazımdır

  • Layihə bir proqramçı üçün həddən artıq böyük olur (və ya IDE «yavaşımağa» başlayır).
  • Hissələr aydın seçilir: core, ui, utils, api, impl.
  • Kodun digər layihələrdə təkrar istifadəsi planlaşdırılır.
  • Yalnız layihənin bir hissəsinə lazım olan xarici asılılıqlar var.
  • Reallaşdırma detallarını (alqoritmlər, daxili siniflər) gizlətmək lazımdır.

2. Modulluluğun tipik sxemləri

Aşağıda — tədris və istehsal layihələri üçün uyğun olan məşhur bölmə sxemləri.

«Soğanvari» arxitektura (Onion Architecture)

Xarici qat daxili qatdan asılıdır, əksinə yox.

[ app (UI) ]
     ↓
[ core (məntiq) ]
     ↓
[ utils (utilitlər) ]
  • app — xarici modul: qrafik interfeys, veb-tətbiq, giriş nöqtəsi (main).
  • core — biznes məntiqi, modellər, servislər.
  • utils — köməkçi siniflər.

Qayda: daxili qat xarici qatdan asılı olmamalıdır. Beləliklə, core müxtəlif interfeyslərdə (konsol, veb, desktop) təkrar istifadə oluna bilər.

API və reallaşdırma üçün modullar

Kitabxanalar üçün interfeysləri və onların reallaşdırmasını ayrıca ayırmaq rahatdır:

[ mylib.api ]  ← yalnız interfeysləri ixrac edir
[ mylib.impl ] ← reallaşdırmaları saxlayır, ixrac edilmir

Testlər üçün modullar

Testlər çox vaxt ayrıca modulda saxlanılır ki, istehsal artefaktına düşməsin.

[ app ]
[ core ]
[ core.tests ]

Tədris layihəsi üçün sxem

myeditor/
  ├─ app/         ← giriş nöqtəsi, tətbiqin işə salınması
  ├─ core/        ← biznes məntiqi (fayllar və mətnlə işləmək)
  └─ utils/       ← utilitlər (loglama, parsing)

3. Modullar arasında asılılıqlar

Java modullarında asılılıqlar module-info.java faylında requires açar sözü ilə açıq şəkildə göstərilir. Bu həm oxunaqlılığı artırır, həm də kompilyator/JVM-ə exports vasitəsilə API əlçatanlığını idarə etməyə imkan verir.

Asılılıq nümunəsi

core/module-info.java

module myeditor.core {
    exports myeditor.core.api; // çöldən yalnız api paketi görünür
    requires myeditor.utils;   // utilitlərdən istifadə edirik
}

app/module-info.java

module myeditor.app {
    requires myeditor.core;    // core-dan istifadə edirik
    requires myeditor.utils;   // utilitləri birbaşa istifadə edə bilərik
}

Qaydalar və best practices

  • Dairəvi asılılıqlardan qaçın. Əgər A requires B və B requires A — bu dizayn qüsurudur. Adətən ümumi common/api modulu ayırmaqla həll olunur.
  • Asılılıqları minimuma endirin. Həqiqətən lazım deyilsə, modulu qoşmayın.
  • İstifadə olunan paketləri ixrac edin. Siniflər exports vasitəsilə elan olunan paketlərdə olmalıdır, əks halda kompilyasiya xətası olacaq.
  • Utilitlər — maksimum müstəqil. utils biznes məntiqindən asılı olmamalıdır.

4. Təcrübə: tədris layihəsini 3 modul üzrə bölməyə nümunə

Qovluq strukturu

myeditor/
  ├─ app/
  │    ├─ src/
  │    │    └─ myeditor/app/Main.java
  │    └─ module-info.java
  ├─ core/
  │    ├─ src/
  │    │    ├─ myeditor/core/api/TextService.java
  │    │    └─ myeditor/core/impl/TextServiceImpl.java
  │    └─ module-info.java
  └─ utils/
       ├─ src/
       │    └─ myeditor/utils/Logger.java
       └─ module-info.java

module-info.java nümunələri

core/module-info.java

module myeditor.core {
    exports myeditor.core.api;
    requires myeditor.utils;
}

app/module-info.java

module myeditor.app {
    requires myeditor.core;
    requires myeditor.utils;
}

utils/module-info.java

module myeditor.utils {
    exports myeditor.utils;
}

Kod nümunəsi (TextService)

myeditor/core/api/TextService.java

package myeditor.core.api;

public interface TextService {
    String toUpperCase(String text);
}

myeditor/core/impl/TextServiceImpl.java

package myeditor.core.impl;

import myeditor.core.api.TextService;

public class TextServiceImpl implements TextService {
    @Override
    public String toUpperCase(String text) {
        return text.toUpperCase();
    }
}

myeditor/app/Main.java

package myeditor.app;

import myeditor.core.api.TextService;
import myeditor.core.impl.TextServiceImpl;

public class Main {
    public static void main(String[] args) {
        TextService service = new TextServiceImpl();
        System.out.println(service.toUpperCase("hello, modules!"));
    }
}

Bu IntelliJ IDEA-da necə görünür

  • Hər kataloq layihə strukturunda ayrıca Module-dir.
  • Hər modulun src kökündə öz module-info.java faylı var.
  • app daxilində main işə salınarkən IDE module-path-i özü təyin edəcək.
  • İxrac olunmayan paketdən sinif istifadə etməyə cəhd kompilyasiya xətası ilə nəticələnəcək.

5. Yığmaya təsir: Maven/Gradle və modullar

Maven

Çoxmodullu layihə — bu «valideyn» layihə (parent) və bir neçə «övlad» moduldur.

myeditor/
  ├─ pom.xml        ← parent
  ├─ app/
  │    └─ pom.xml
  ├─ core/
  │    └─ pom.xml
  └─ utils/
       └─ pom.xml

parent pom.xml nümunəsi

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>myeditor</groupId>
  <artifactId>myeditor-parent</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>

  <modules>
    <module>app</module>
    <module>core</module>
    <module>utils</module>
  </modules>
</project>

Xüsusiyyətlər:

  • Maven kompilyasiya zamanı module-info.java-nı nəzərə alır.
  • İşə salmaq üçün --classpath əvəzinə --module-path istifadə olunur.
  • Əgər exports və ya requires unudulubsa — kompilyasiya xətası alacaqsınız.

Gradle

Çoxmodulluluq settings.gradle vasitəsilə və modullar üçün ayrıca build.gradle faylları ilə qurulur.

settings.gradle

rootProject.name = 'myeditor'
include 'app', 'core', 'utils'

Modul üçün build.gradle

plugins {
    id 'java'
}

java {
    modularity.inferModulePath = true
}

IntelliJ IDEA

  • IDEA Java modulu yaradılarkən module-info.java faylını yarada bilir.
  • Maven/Gradle ilə modul strukturu avtomatik götürülür.
  • app-dən main işə salınanda IDE module-path-i quracaq.
  • İdxal/ixrac dialoqları paketlərin və modulların görünürlüyünü göstərir.

Modullara bölərkən tipik səhvlər

Səhv №1: Modullar arasında dairəvi asılılıqlar. Əgər iki modul bir-birinə qarşılıqlı olaraq requires elan edirsə, kompilyator səhv verəcək. Bu, adətən arxitekturanın «pozulması» əlamətidir. Həll — ümumi api modulunu ayırmaq və ya sərhədləri yenidən nəzərdən keçirmək.

Səhv №2: İxrac olunmayan paketlərdən siniflərin istifadəsi. Sinif public ola bilər, lakin əgər paket module-info.java-da exports ilə göstərilməyibsə, başqa modul onu görməyəcək. Nəticə — kompilyasiya xətası.

Səhv №3: İstifadə olunan modul üçün requires əlavə edilməməsi. Müvafiq qeyd olmadan başqa moduldan import kompilyasiya olunmayacaq. Asılılıqları həmişə açıq şəkildə elan edin.

Səhv №4: Modul adlarının təkrarlanması. Modul adları yığım daxilində unikal olmalıdır (xüsusən Maven/Gradle ilə). Dublikatlar yığmanı pozur.

Səhv №5: Kataloq strukturunun səhv olması. module-info.java faylı müvafiq modulun src kökündə yerləşməlidir. Əks halda kompilyator modulu tapmayacaq.

Səhv №6: İşə salınarkən səhv module-path. Əl ilə işə salarkən --classpath əvəzinə --module-path göstərin, əks halda «module not found» alacaqsınız.

1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Hadisə jurnalına əlaqə kanalının açılması 📢
Hadisə jurnalına əlaqə kanalının açılması 📢
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Rəqəmsal Ünvan Kitabının Memarı 🗺️
Rəqəmsal Ünvan Kitabının Memarı 🗺️
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION