SOLID-Prinzipien in Kotlin: Von der Theorie zur Praxis
SOLID ist ein Akronym für fünf grundlegende Prinzipien des objektorientierten Designs, formuliert von Robert Martin (Uncle Bob). Diese Prinzipien helfen dabei, flexiblen, skalierbaren und leicht wartbaren Code zu erstellen. In diesem Artikel analysieren wir jedes SOLID-Prinzip anhand von Beispielen aus der Welt von Kotlin, damit Sie sie sofort in Ihren Projekten anwenden können.
1. Single Responsibility Principle (SRP) — Prinzip der einzigen Verantwortung
Theorie: Jede Klasse sollte nur einen Grund für eine Änderung haben. Mit anderen Worten, die Klasse sollte für eine klar abgegrenzte Funktionalität verantwortlich sein.
Praxis in Kotlin: Betrachten wir eine typische Verletzung des SRP, bei der eine Klasse sich sowohl mit Datenverarbeitung, als auch mit Ausgabe und Validierung beschäftigt.
// ❌ Verletzung des SRPclass UserManager { fun registerUser(email: String, password: String) { if (isValidEmail(email) && isValidPassword(password)) { saveToDatabase(email, password) sendWelcomeEmail(email) } }
private fun isValidEmail(email: String): Boolean = email.contains("@") private fun isValidPassword(password: String): Boolean = password.length >= 6 private fun saveToDatabase(email: String, password: String) { /* ... */ } private fun sendWelcomeEmail(email: String) { /* ... */ }}Refactoring unter Einhaltung des SRP:
// ✅ Einhaltung des SRPclass UserValidator { fun isValidEmail(email: String): Boolean = email.contains("@") fun isValidPassword(password: String): Boolean = password.length >= 6}
class UserRepository { fun save(email: String, password: String) { /* Speichern in der DB */ }}
class EmailService { fun sendWelcomeEmail(email: String) { /* E-Mail senden */ }}
class UserRegistrationService( private val validator: UserValidator, private val repository: UserRepository, private val emailService: EmailService) { fun registerUser(email: String, password: String) { if (validator.isValidEmail(email) && validator.isValidPassword(password)) { repository.save(email, password) emailService.sendWelcomeEmail(email) } }}2. Open/Closed Principle (OCP) — Prinzip der Offenheit/Geschlossenheit
Theorie: Softwareentitäten (Klassen, Module, Funktionen) sollten für Erweiterungen offen, aber für Modifikationen geschlossen sein. Sie sollten in der Lage sein, neue Funktionalität hinzuzufügen, ohne vorhandenen Code zu ändern.
Praxis in Kotlin: Wir verwenden Interfaces und Polymorphismus. Anstatt if-else oder when für die Verarbeitung verschiedener Typen zu verwenden, erstellen wir eine Hierarchie.
// ❌ Verletzung des OCPclass DiscountCalculator { fun calculateDiscount(customerType: String, amount: Double): Double { return when (customerType) { "Regular" -> amount * 0.05 "Premium" -> amount * 0.10 "VIP" -> amount * 0.20 else -> 0.0 } } // Um "Gold" hinzuzufügen, muss diese Methode geändert werden!}// ✅ Einhaltung des OCPinterface DiscountStrategy { fun applyDiscount(amount: Double): Double}
class RegularDiscount : DiscountStrategy { override fun applyDiscount(amount: Double): Double = amount * 0.05}
class PremiumDiscount : DiscountStrategy { override fun applyDiscount(amount: Double): Double = amount * 0.10}
class VIPDiscount : DiscountStrategy { override fun applyDiscount(amount: Double): Double = amount * 0.20}
// Neuer Typ wird ohne Änderung des vorhandenen Codes hinzugefügtclass GoldDiscount : DiscountStrategy { override fun applyDiscount(amount: Double): Double = amount * 0.15}
class DiscountCalculator { fun calculateDiscount(strategy: DiscountStrategy, amount: Double): Double { return strategy.apply