Feature- en coremodules
Trek modulegrenzen.
Feature- en coremodules is een gratis Android Academy-les op CoddyKit. Dit is les 2 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Android Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Android Academy bevat in totaal 4 lessen.
Twee soorten modules
De meeste gemodulariseerde Android-apps organiseren code in twee hoofdsoorten modules: feature-modules en core-modules, met daarbovenop een dunne :app-module.
- Feature-modules bevatten een gebruikersgericht deel van de app (een scherm of proces).
- Core-modules bevatten gedeelde infrastructuur die door veel functies wordt gebruikt.
In deze les leer je hoe je deze grenzen goed trekt.
Anatomie van een feature-module
Een feature-module zoals :feature:profile bevat alles wat één functie nodig heeft: de Compose-schermen, het ViewModel en de UI-status. Deze is verticaal: de module beheert het volledige deel van de gebruikersinterface tot en met het view-model.
De module is voor gedeelde onderdelen afhankelijk van core-modules, maar mag niet afhankelijk zijn van andere feature-modules.
// feature/profile/ProfileScreen.kt
@Composable
fun ProfileScreen(viewModel: ProfileViewModel = hiltViewModel()) {
val state by viewModel.uiState.collectAsStateWithLifecycle()
when (state) {
is ProfileUiState.Loading -> CircularProgressIndicator()
is ProfileUiState.Success -> ProfileContent((state as ProfileUiState.Success).user)
is ProfileUiState.Error -> ErrorMessage()
}
}Het feature-ViewModel
Elke functie heeft zijn eigen ViewModel. Dit haalt via een repository uit een core-module gegevens op en stelt de UI-status beschikbaar. De feature-module weet niets over de manier waarop gegevens worden opgehaald, maar alleen over het contract van de repository.
// feature/profile/ProfileViewModel.kt
@HiltViewModel
class ProfileViewModel @Inject constructor(
private val userRepository: UserRepository // from :core:data
) : ViewModel() {
val uiState: StateFlow<ProfileUiState> =
userRepository.observeUser()
.map { ProfileUiState.Success(it) }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), ProfileUiState.Loading)
}Anatomie van een core-module
Een core-module is horizontaal: deze biedt één mogelijkheid die in verschillende functies wordt gebruikt. Veelvoorkomende core-modules zijn:
:core:model— gewone gegevensklassen die overal worden gedeeld:core:network— Retrofit/Ktor-clients:core:database— Room-configuratie:core:data— repositories die netwerk en database combineren:core:designsystem— thema en herbruikbare composables
// core/model/User.kt
data class User(
val id: String,
val name: String,
val avatarUrl: String
)De module voor het designsysteem
:core:designsystem is een van de meest hergebruikte modules. Deze bevat je MaterialTheme, kleurenschema's, typografie en herbruikbare composables zoals knoppen en kaarten. Elke functie gebruikt dezelfde stijl zonder code te kopiëren.
// core/designsystem/AppTheme.kt
@Composable
fun AppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val colors = if (darkTheme) DarkColors else LightColors
MaterialTheme(
colorScheme = colors,
typography = AppTypography,
content = content
)
}De datamodule beheert repositories
De module :core:data stelt repository-interfaces beschikbaar waarvan functies afhankelijk zijn, en verbergt de implementatie. Deze module is doorgaans afhankelijk van :core:network en :core:database en combineert deze tot één bron van waarheid.
// core/data/UserRepository.kt
interface UserRepository {
fun observeUser(): Flow<User>
suspend fun refresh()
}
// core/data/OfflineFirstUserRepository.kt
internal class OfflineFirstUserRepository @Inject constructor(
private val api: UserApi, // :core:network
private val dao: UserDao // :core:database
) : UserRepository {
override fun observeUser(): Flow<User> = dao.observe().map { it.toUser() }
override suspend fun refresh() { dao.upsert(api.fetch().toEntity()) }
}Model en ontwerpsysteem licht houden
De modules in de onderste kernlaag moeten van zo weinig mogelijk afhankelijk zijn. :core:model heeft idealiter helemaal geen Android-afhankelijkheden — alleen gewone Kotlin-dataklassen. Daardoor kun je deze module overal gebruiken en blijft het bouwen snel.
Als :core:model afhankelijk zou worden van Retrofit of Room, zou elke module die je dataklassen gebruikt deze zware bibliotheken meeslepen.
// core/model/build.gradle.kts
plugins {
id("myapp.jvm.library") // pure Kotlin, no Android
}
// No Retrofit, no Room, no Compose here — just data classesDe dunne module :app
De module :app is de samensteller. Deze moet maar weinig logica bevatten: de klasse Application, de enkele MainActivity, de NavHost op het hoogste niveau en de configuratie voor dependency-injectie. Alle echte schermen staan in featuremodules.
Met een dunne appmodule vinden de meeste wijzigingen plaats in features, waardoor de appmodule zelden opnieuw hoeft te worden gebouwd.
// app/MainActivity.kt
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
AppTheme { // from :core:designsystem
AppNavHost() // routes into :feature:* screens
}
}
}
}Goede grenzen bepalen
Hoe bepaal je wat een module wordt? Enkele praktische vuistregels:
- Een feature = een scherm of flow die een gebruiker kan benoemen (Home, Profile, Checkout).
- Een core-module = een mogelijkheid die door 2 of meer features wordt hergebruikt.
- Als twee features dezelfde code nodig hebben, verplaats je die omlaag naar een coremodule.
- Als een module te veel niet-gerelateerde dingen doet, splits je deze op.
Optioneel: splitsing tussen api en impl
In grote apps wordt een feature soms opgesplitst in een openbare :feature:profile:api (interfaces, navigatieroutes) en een private :feature:profile:impl (schermen, view-modellen). Andere features zijn alleen afhankelijk van de kleine api, nooit van de implementatie.
Dit is geavanceerd; voor de meeste apps is één module per feature ruim voldoende. Het is vooral belangrijk dat je weet dat dit patroon bestaat voor zeer grote codebases.
// Other features see only the contract, not the screens
// feature/home depends on :feature:profile:api
interface ProfileEntry {
val route: String
fun NavGraphBuilder.register(navController: NavController)
}De graaf samenvoegen
Zo worden de lagen voor ons voorbeeld aan elkaar gekoppeld. Let erop dat afhankelijkheden altijd alleen naar beneden wijzen: app -> feature -> data -> network/database -> model.
// :app -> :feature:home, :feature:profile
// :feature:home -> :core:data, :core:designsystem
// :feature:profile -> :core:data, :core:designsystem
// :core:data -> :core:network, :core:database, :core:model
// :core:network -> :core:model
// :core:database -> :core:model
// :core:model -> (nothing)Korte controle
Je modules :feature:home en :feature:profile moeten beide gebruikersgegevens ophalen en cachen. Waar hoort de code voor deze repository te staan?
Samenvatting: feature- en coremodules
Je hebt geleerd hoe je code in twee lagen opsplitst:
- Featuremodules zijn verticale doorsneden (scherm + ViewModel + UI-status).
- Coremodules zijn horizontale mogelijkheden (model, netwerk, database, data, ontwerpsysteem).
- De module
:appblijft dun en voegt alleen de features samen. - Gedeelde code verplaats je omlaag naar core;
:core:modelblijft vrij van Android en licht.
Vervolgens ga je de afhankelijkheden tussen deze modules beheren en de graaf overzichtelijk houden.
Leer Kotlin met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 36
- Lessen
- 152
Veelgestelde vragen
Is de les “Feature- en coremodules” gratis?
Ja — je kunt hier op het web alle 3 lessen van het leerpad Android Academy, waaronder “Feature- en coremodules”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus Android Academy bevat in totaal 4 lessen.
Wat leer ik in “Feature- en coremodules”?
Trek modulegrenzen. Je oefent met Android Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Android Academy te beginnen?
Ervaring vooraf is niet nodig. Android Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 2 van 4.
Hoe lang duurt de les “Feature- en coremodules”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Android Academy?
Ja. Elke les over Android Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Waarom modulariseren
- Feature- en coremodules
- Moduleafhankelijkheden beheren
- Navigatie tussen modules