Dlaczego warto stosować moduły
Szybkość kompilacji, odpowiedzialność i ponowne użycie
Dlaczego warto stosować moduły to bezpłatna lekcja Android Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Android Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Android Academy zawiera 4 lekcji w sumie.
Problem monolitu
Gdy aplikacja na Androida się rozrasta, cały jej kod często znajduje się w jednym module app. Taki układ to monolit. Na początku jest wygodny, ale z czasem staje się uciążliwy: każda zmiana dotyczy tego samego modułu, kompilacje trwają coraz dłużej, a członkowie zespołu nieustannie wchodzą sobie w drogę.
Modularyzacja oznacza podzielenie jednego dużego modułu na wiele mniejszych, wyspecjalizowanych modułów Gradle. W tej lekcji dowie się Pan lub dowie się Pani, dlaczego zespoły to robią i jakie konkretne korzyści można dzięki temu uzyskać.
Czym właściwie jest moduł
W Gradle moduł to niezależnie budowalna jednostka kodu z własnym plikiem build.gradle.kts. Pańska aplikacja lub Pani aplikacja ma już co najmniej jeden taki moduł: moduł :app. Każdy moduł należy zadeklarować w pliku settings.gradle.kts.
Dodanie modułu jest równie proste jak jego dołączenie. Każdy moduł generuje własny wynik kompilacji i może zależeć od innych modułów.
// settings.gradle.kts
include(":app")
include(":core:designsystem")
include(":core:data")
include(":feature:home")
include(":feature:profile")Korzyść 1: szybsze kompilacje
Największą praktyczną korzyścią jest szybkość kompilacji. Gradle może kompilować moduły równolegle i, co najważniejsze, buforować oraz pomijać moduły, których dane wejściowe się nie zmieniły.
Jeśli edytuje Pan lub edytuje Pani tylko :feature:profile, Gradle ponownie wykorzysta gotowe wyniki kompilacji wszystkich pozostałych modułów. W monolicie każda zmiana może wymusić ponowną kompilację całej aplikacji.
- Równoległe wykonywanie zadań w modułach
- Przyrostowe kompilacje: ponowna kompilacja tylko zmienionych elementów
- Większa skuteczność wykorzystania zdalnej pamięci podręcznej i pamięci podręcznej kompilacji
// gradle.properties
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configuration-cache=trueKorzyść 2: wyraźne granice
Moduły wymuszają istnienie granic. Kod w jednym module może korzystać tylko z tego, co inny moduł celowo udostępnia. Zapobiega to splątanej strukturze, w której każda klasa odwołuje się bezpośrednio do każdej innej klasy.
Widocznością steruje Pan lub steruje Pani za pomocą konfiguracji Gradle api i implementation. implementation utrzymuje zależność jako prywatną dla modułu, więc odbiorcy nie mogą przypadkowo z niej korzystać.
// feature/profile/build.gradle.kts
dependencies {
// Exposed to whoever depends on :feature:profile
api(project(":core:model"))
// Private: hidden from consumers of this module
implementation(project(":core:network"))
}Korzyść 3: ponowne użycie
Gdy logika znajduje się w wyspecjalizowanym module, można ją ponownie wykorzystać w dowolnym miejscu. Moduł :core:designsystem zawierający motyw, kolory i kompozysy wielokrotnego użytku może być współdzielony przez wszystkie funkcje.
Ta sama zasada sprawdza się w przypadku wielu aplikacji: firma może współdzielić moduł :core:network między kilkoma produktami zamiast kopiować kod.
// Any feature can pull in shared building blocks
// feature/home/build.gradle.kts
dependencies {
implementation(project(":core:designsystem"))
implementation(project(":core:data"))
}Korzyść 4: odpowiedzialność zespołów
Moduły dobrze odzwierciedlają odpowiedzialność zespołów. Zespół płatności odpowiada za :feature:payments, a zespół profilu za :feature:profile. Zespoły mogą pracować równolegle i napotykać mniej konfliktów podczas scalania, ponieważ ich kod znajduje się w osobnych folderach i plikach kompilacji.
Narzędzia takie jak plik CODEOWNERS mogą automatycznie prosić właściwy zespół o przegląd zmian na podstawie ścieżki modułu.
# .github/CODEOWNERS
/feature/payments/ @org/payments-team
/feature/profile/ @org/profile-team
/core/designsystem/ @org/platform-teamKorzyść 5: enkapsulacja za pomocą widoczności
Wewnątrz modułu modyfikator internal języka Kotlin staje się bardzo użyteczny. Klasa lub funkcja oznaczona jako internal jest widoczna wyłącznie w swoim module. Inne moduły nie mogą się do niej odwoływać.
Pozwala to udostępnić niewielki publiczny interfejs i ukryć szczegóły implementacji, czego nie da się wymusić w jednym ogromnym module.
// In :core:data
// Public API other modules may use
fun interface UserRepository {
suspend fun loadUser(id: String): User
}
// Hidden from other modules
internal class DefaultUserRepository(
private val api: UserApi
) : UserRepository {
override suspend fun loadUser(id: String) = api.fetch(id).toUser()
}Koszt: dodatkowe nakłady
Modularyzacja nie jest darmowa. Każdy moduł wymaga utrzymywania pliku build.gradle.kts, a ponadto trzeba przemyśleć, do którego modułu należy każda część kodu. Nadmierna modularyzacja małej aplikacji tworzy dodatkową pracę bez wymiernych korzyści.
Zasada praktyczna brzmi: warto modularyzować, gdy czas kompilacji zaczyna przeszkadzać, gdy zespoły wchodzą sobie w drogę albo gdy istnieją wyraźne warstwy wielokrotnego użytku. Hobbystyczna aplikacja tworzona w weekend zazwyczaj nie potrzebuje 30 modułów.
Typowy układ modułów
Popularna, skalowalna struktura dzieli moduły na warstwy app, feature i core. Moduł :app łączy wszystko w całość, moduły funkcji zawierają ekrany widoczne dla użytkownika, a moduły core — współdzieloną infrastrukturę.
// Conceptual project tree
// app/ <- single entry point, wires features
// feature/
// home/
// profile/
// settings/
// core/
// designsystem/ <- theme + reusable composables
// data/ <- repositories
// network/ <- Retrofit/Ktor
// model/ <- shared data classesWtyczki konwencji utrzymują porządek
Przy wielu modułach kopiowanie tej samej konfiguracji Gradle w każdym miejscu prowadzi do problemów. Zespoły wydzielają wspólną konfigurację do wtyczek konwencji (w module build-logic). Każdy właściwy moduł stosuje wtedy jedną wtyczkę zamiast powtarzać dziesiątki wierszy.
Ten wzorzec można zobaczyć w dużych aplikacjach open source, takich jak Now in Android. Na razie wystarczy wiedzieć, że jego celem jest utrzymanie małych i spójnych plików kompilacji.
// feature/home/build.gradle.kts
plugins {
// One convention plugin sets up Android + Compose + Kotlin
id("myapp.android.feature")
}
android { namespace = "com.myapp.feature.home" }Sposób myślenia: myślenie warstwami
Najbardziej użyteczny model mentalny jest następujący: zależności powinny przepływać w dół. Moduły funkcji zależą od modułów core, ale moduły core nie zależą od modułów funkcji. Moduł :app znajduje się na samej górze i zależy od wszystkiego, czego potrzebuje do złożenia aplikacji.
Jeśli zachowa Pan lub zachowa Pani ten kierunek, graf modułów pozostanie przejrzysty i uda się uniknąć cykli, które zostaną omówione w jednej z późniejszych lekcji.
// Allowed: app -> feature -> core
// Forbidden: core -> feature (upward) or feature -> feature (sideways)
// app/build.gradle.kts
dependencies {
implementation(project(":feature:home"))
implementation(project(":feature:profile"))
}Szybkie sprawdzenie
Co jest najbardziej konkretną, codzienną korzyścią, jaką zespoły uzyskują dzięki modularyzacji rozwijającej się aplikacji na Androida?
Podsumowanie: po co modularyzować
Dowiedział się Pan lub dowiedziała się Pani, dlaczego zespoły dzielą monolit na moduły:
- Szybsze kompilacje dzięki wykonywaniu równoległemu i przyrostowemu buforowaniu
- Wyraźne granice dzięki użyciu
api/implementationorazinternal - Ponowne użycie warstw core, takich jak system projektowy i warstwa sieciowa
- Odpowiedzialność zespołów i mniej konfliktów podczas scalania
Poznał Pan lub poznała Pani również koszt tego rozwiązania (dodatkowe pliki kompilacji) oraz złotą zasadę: zależności przepływają w dół, app -> feature -> core. W następnej części narysuje Pan lub narysuje Pani rzeczywiste granice między modułami funkcji i core.
Często zadawane pytania
Czy lekcja „Dlaczego warto stosować moduły” jest bezpłatna?
Tak — pełny tekst „Dlaczego warto stosować moduły” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Android Academy, przejdź na CoddyKit PRO. Kurs Android Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Dlaczego warto stosować moduły”?
Szybkość kompilacji, odpowiedzialność i ponowne użycie Ćwiczysz Android Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Android Academy?
Nie wymagamy żadnego doświadczenia. Android Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.
Ile czasu zajmuje lekcja „Dlaczego warto stosować moduły”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Android Academy?
Tak. Każda lekcja Android Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Dlaczego warto stosować moduły
- Moduły funkcji i moduły podstawowe
- Zarządzanie zależnościami modułów
- Nawigacja między modułami