Kotlin-Codestil: Benennung und Formatierung
Ein konsistenter Kotlin-Stil macht Android-Code lesbar. Du lernst Regeln für Namen, Formatierung und Reviews.
Kotlin Coding Conventions sind gemeinsame Regeln für Stil, Benennung und Formatierung in Kotlin-Code. Für dich als Android-Entwickler sind sie kein Schmuck am Rand, sondern ein Werkzeug für bessere Lesbarkeit, schnellere Reviews und weniger Missverständnisse im Team.
Was ist das?
Kotlin Coding Conventions beschreiben, wie Kotlin-Code aussehen und benannt werden soll. Dazu gehören Einrückung, Zeilenumbrüche, Dateinamen, Paketnamen, Klassen, Funktionen, Variablen, Konstanten und die Reihenfolge von Code innerhalb einer Datei. Die Idee ist klar: Wenn alle im Projekt denselben Stil verwenden, musst du beim Lesen weniger Energie auf Form und mehr Energie auf Verhalten verwenden.
Im Android-Alltag ist das besonders wichtig, weil viele Dateien verschiedene Rollen haben. Eine App enthält zum Beispiel Compose-Screens, ViewModels, Repository-Klassen, Datenmodelle, Tests, Gradle-Dateien und manchmal noch XML-Ressourcen. Ohne gemeinsame Konventionen sieht jede Schicht anders aus. Dann erkennst du schwerer, ob ein Name eine UI-Funktion, einen Zustand, ein Datenobjekt oder eine einmalige Hilfsfunktion meint.
Das mentale Modell für Einsteiger lautet: Stil ist Teil der Kommunikation. Code wird häufiger gelesen als geschrieben. Ein guter Name erklärt, warum etwas existiert. Eine gute Formatierung zeigt, welche Teile zusammengehören. Eine passende Dateistruktur hilft dir, Verhalten schnell zu finden. Coding Conventions sind deshalb keine Frage von persönlichem Geschmack, sondern eine Vereinbarung für Zusammenarbeit.
In Kotlin gibt es offizielle Empfehlungen, an denen du dich orientieren solltest. Android-Projekte übernehmen viele dieser Regeln direkt, ergänzen sie aber oft durch lokale Teamregeln. Jetpack Compose bringt zusätzliche Namensmuster mit, etwa großgeschriebene Composable-Funktionen für UI-Bausteine. Architecture Components bringen typische Rollen wie MainViewModel, UserRepository oder LoginUiState mit. Solche Namen sind nicht zufällig: Sie machen den Zweck sichtbar.
Wie funktioniert es?
Coding Conventions wirken auf mehreren Ebenen. Die erste Ebene ist Formatierung. Kotlin nutzt meist vier Leerzeichen für Einrückung. Lange Parameterlisten, verkettete Aufrufe und Lambdas werden so umgebrochen, dass die Struktur klar bleibt. Du solltest Formatierung nicht von Hand verteidigen müssen. Nutze die IDE-Formatierung in Android Studio und, wenn im Projekt vorhanden, Tools wie ktlint oder Detekt. So wird Stil prüfbar und nicht zur Dauerdiskussion im Review.
Die zweite Ebene ist Benennung. Klassen und Objekte verwenden in Kotlin üblicherweise PascalCase, also zum Beispiel UserProfileScreen oder SettingsViewModel. Funktionen und Variablen verwenden camelCase, etwa loadUserProfile() oder isLoading. Konstanten auf Top-Level oder in object-Containern werden oft als UPPER_SNAKE_CASE geschrieben, wenn sie echte Konstanten sind. Paketnamen sind klein und enthalten keine Unterstriche.
Wichtiger als die reine Schreibweise ist die Absicht im Namen. data ist fast immer zu ungenau. userProfile ist besser. handleClick() ist schwach, wenn der Code eigentlich ein Login startet. submitLogin() oder onLoginClick() gibt mehr Kontext. In Android-Code solltest du außerdem zwischen Zustand, Ereignis und Aktion unterscheiden. LoginUiState beschreibt Daten für die Oberfläche. onPasswordChanged() beschreibt ein UI-Ereignis. login() beschreibt eine fachliche Aktion.
Die dritte Ebene ist Struktur innerhalb einer Datei. Eine Kotlin-Datei sollte nicht zu viele Verantwortlichkeiten mischen. Eine Datei für einen Compose-Screen kann den öffentlichen Screen oben enthalten, danach kleinere private Composables und Preview-Funktionen. Ein ViewModel sollte seine öffentlichen Zustände klar sichtbar machen und interne Details verstecken. private ist dabei auch eine Stilentscheidung: Es zeigt, was zur Schnittstelle gehört und was nur innerhalb der Datei oder Klasse wichtig ist.
Bei Compose ist Konsistenz besonders wertvoll. Composable-Funktionen, die UI-Elemente darstellen, werden wie Typen großgeschrieben: LoginScreen, UserHeader, PrimaryActionButton. Parameter sollten stabil und erwartbar sein. Häufig stehen Daten zuerst, dann Callbacks, dann Modifier. Der modifier: Modifier = Modifier ist in vielen UI-Funktionen ein Standardparameter, meist weit oben in der Liste. Dadurch können Aufrufer Layout-Verhalten von außen steuern, ohne dass die Komponente intern starr wird.
Auch Tests profitieren von klaren Konventionen. Testnamen dürfen in Kotlin mit Backticks geschrieben werden, wenn sie lesbare Sätze bilden. Das kann für Unit-Tests hilfreich sein. In größeren Teams ist aber wichtig, dass alle denselben Stil akzeptieren. Ob du login_withValidInput_emitsSuccess() oder `login emits success for valid input` nutzt, sollte nicht pro Datei neu entschieden werden.
In der Praxis
Stell dir vor, du baust einen Login-Screen mit Compose und ViewModel. Der folgende Ausschnitt zeigt keine komplette App, sondern konzentriert sich auf Stil, Benennung und Formatierung. Achte darauf, dass Namen Rollen beschreiben und die Parameter lesbar angeordnet sind.
data class LoginUiState(
val email: String = "",
val password: String = "",
val isLoading: Boolean = false,
val errorMessage: String? = null,
)
class LoginViewModel : ViewModel() {
private val _uiState = MutableStateFlow(LoginUiState())
val uiState: StateFlow<LoginUiState> = _uiState.asStateFlow()
fun onEmailChanged(email: String) {
_uiState.update { currentState ->
currentState.copy(email = email)
}
}
fun onPasswordChanged(password: String) {
_uiState.update { currentState ->
currentState.copy(password = password)
}
}
fun submitLogin() {
val currentState = _uiState.value
if (currentState.email.isBlank() || currentState.password.isBlank()) {
_uiState.update {
it.copy(errorMessage = "E-Mail und Passwort dürfen nicht leer sein.")
}
return
}
_uiState.update {
it.copy(isLoading = true, errorMessage = null)
}
}
}
@Composable
fun LoginScreen(
uiState: LoginUiState,
onEmailChanged: (String) -> Unit,
onPasswordChanged: (String) -> Unit,
onSubmitLogin: () -> Unit,
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(12.dp),
) {
OutlinedTextField(
value = uiState.email,
onValueChange = onEmailChanged,
label = { Text("E-Mail") },
enabled = !uiState.isLoading,
)
OutlinedTextField(
value = uiState.password,
onValueChange = onPasswordChanged,
label = { Text("Passwort") },
enabled = !uiState.isLoading,
)
Button(
onClick = onSubmitLogin,
enabled = !uiState.isLoading,
) {
Text("Anmelden")
}
}
}
Mehrere Konventionen arbeiten hier zusammen. LoginUiState sagt klar, dass die Klasse UI-Zustand trägt. _uiState ist veränderbar und privat, uiState ist die öffentliche, lesbare Sicht. Die Funktionen onEmailChanged() und onPasswordChanged() passen zu UI-Ereignissen. submitLogin() beschreibt die Aktion. Im Compose-Teil stehen Daten und Callbacks vor dem modifier, und der Screen versteckt keine Abhängigkeiten in globalen Variablen.
Eine praktische Entscheidungsregel: Benenne nach Absicht, nicht nach Implementierung. Wenn eine Funktion fetchData() heißt, frage dich, welche Daten gemeint sind und warum sie geladen werden. loadUserProfile() ist stärker. Wenn eine Variable flag heißt, frage dich, welchen Zustand sie ausdrückt. isPremiumUser oder hasAcceptedTerms sind klarer. Wenn ein Composable Content() heißt, frage dich, welchen sichtbaren Teil es darstellt. ProfileContent() oder EmptySearchResult() helfen beim Lesen.
Eine typische Stolperfalle ist übertriebene Abkürzung. Namen wie usr, pwd, vm, repoImpl2 sparen wenige Zeichen, kosten aber Verständnis. In Kotlin darf Code ruhig sprechend sein. Kurze Namen sind nur sinnvoll, wenn der Kontext sehr eng ist, etwa it in einer kleinen Lambda-Funktion oder id für eine eindeutig bekannte Kennung. Sobald der Leser scrollen oder raten muss, ist der Name zu schwach.
Eine zweite Stolperfalle ist uneinheitliche Formatierung in Pull Requests. Wenn du fachlichen Code änderst und gleichzeitig die halbe Datei neu formatierst, wird das Review unnötig schwer. Trenne reine Formatierungsänderungen von Verhaltensänderungen, wenn der Unterschied groß ist. In einem Team solltest du außerdem vorab klären, welches Tool den Stil erzwingt. Dann kann die CI prüfen, ob die Konventionen eingehalten werden.
Eine dritte Stolperfalle betrifft Compose-Parameter. Wenn jedes Composable Parameter in anderer Reihenfolge annimmt, wird die Nutzung unruhig. Lege im Projekt eine Reihenfolge fest, zum Beispiel: Pflichtdaten, UI-Zustand, Event-Callbacks, modifier, optionale Darstellungsparameter. Diese Regel ist nicht magisch, aber sie senkt Reibung. Du erkennst schneller, welche Werte ein UI-Baustein braucht und welche Aktionen er nach außen meldet.
Du kannst dein Verständnis gut durch Code-Reviews trainieren. Nimm eine Datei aus deinem Projekt und prüfe sie nur auf Namen und Struktur. Frage dich: Kann ich die öffentliche API der Klasse in einer Minute verstehen? Sind Zustände als Zustände benannt? Sind Ereignisse als Ereignisse benannt? Gibt es Funktionen, deren Name weniger verspricht als sie tun, oder mehr verspricht als sie leisten? Danach lässt du die automatische Formatierung laufen und vergleichst, was sich ändert.
Auch Tests helfen. Wenn ein Test schwer zu benennen ist, ist oft das getestete Verhalten unklar. Ein guter Testname zwingt dich, Eingabe, Aktion und erwartetes Ergebnis zu formulieren. Das wirkt zurück auf Produktionscode. Eine Funktion, die fünf Dinge gleichzeitig tut, bekommt selten einen guten Namen. Dann ist nicht der Name das Hauptproblem, sondern die Verantwortung der Funktion.
Fazit
Kotlin Coding Conventions geben deinem Android-Code eine verlässliche Form. Du schreibst nicht nur für den Compiler, sondern für dein zukünftiges Ich, dein Team und jedes Review vor einem Release. Prüfe bei deiner nächsten Aufgabe gezielt drei Dinge: Sind Namen absichtsvoll, ist die Formatierung automatisch reproduzierbar, und zeigt die Dateistruktur die Verantwortung des Codes? Öffne danach einen kleinen Pull Request oder bitte um ein Review nur zu Stil, Benennung und Formatierung. So lernst du, Konventionen nicht als Regelkatalog auswendig zu kennen, sondern als praktisches Werkzeug für bessere Android-Entwicklung zu nutzen.