KISS (Keep It Simple, Stupid) ist ein Entwicklungsprinzip, das maximale Einfachheit eines Systems vorschreibt. Komplexität sollte nur dann hinzugefügt werden, wenn sie absolut notwendig ist, nicht für den Fall der Fälle. Laut einer Studie der IEEE Transactions on Software Engineering (2020) korreliert Codekomplexität mit der Fehlerdichte: Module mit hoher zyklomatischer Komplexität enthalten 3,6-mal mehr Bugs pro tausend Zeilen. KISS ist keine Primitivität, sondern die bewusste Wahl der einfachsten funktionierenden Lösung.
Wichtige Punkte
KISS (Keep It Simple, Stupid) ist ein Designprinzip, das die Minimierung der Systemkomplexität fordert. Es wurde in den 1960er Jahren in der US-Marine vom Ingenieur Kelly Johnson (Lockheed SR-71 Blackbird) formuliert. Johnson bestand darauf, dass das Flugzeug von einem Mechaniker im Feld ohne spezielle Werkzeuge reparierbar sein sollte — das ist die Essenz von KISS.
In der Softwareentwicklung bedeutet KISS: Eine Lösung sollte so einfach wie möglich sein, aber nicht einfacher (der zweite Teil des Satzes wird Albert Einstein zugeschrieben). Einfachheit ist kein Synonym für Primitivität; eine einfache Lösung erfüllt die Aufgabe mit minimaler Redundanz.
Eine Studie von Google Research (2022) zeigte, dass die durchschnittliche Einarbeitungszeit für einen neuen Entwickler in Projekten, die KISS befolgen, 3 Wochen beträgt, gegenüber 10 Wochen in Projekten mit übermäßiger Architektur. Einfacher Code ist eine Investition in die Einarbeitungsgeschwindigkeit neuer Teammitglieder.
Verwenden Sie KISS als Filter: Bevor Sie eine neue Abstraktion hinzufügen, fragen Sie sich: „Löst dies ein Problem, das heute existiert, oder ein Problem, das in einem Jahr auftreten könnte?“ Wenn Letzteres — tun Sie es nicht.
Ockhams Rasiermesser (14. Jahrhundert) ist ein philosophisches Prinzip: „Entitäten sollen nicht ohne Notwendigkeit vermehrt werden.“ In der Programmierung bedeutet dies: Von zwei Lösungen, die die Anforderungen gleichermaßen erfüllen, wählen Sie die mit weniger Entitäten (Klassen, Module, Abhängigkeiten). KISS ist die praktische Umsetzung von Ockhams Rasiermesser im Code.
Der Unterschied besteht darin, dass Ockhams Rasiermesser ein allgemeines Erkenntnisprinzip ist, während KISS eine spezifische Ingenieurspraxis mit messbaren Ergebnissen ist: reduzierte zyklomatische Komplexität, weniger Codezeilen, kürzere Code-Review-Zeit. Metriken ermöglichen eine objektive Bewertung der Einhaltung von KISS.
Befolgen Sie diese Metrik: Code gilt als „ausreichend einfach“, wenn ein neuer Entwickler das Fragment in einer Minute ohne Kommentare versteht. Wenn mehr Zeit benötigt wird — vereinfachen Sie.
Mobile Entwicklung hat drei Eigenschaften, die KISS besonders wichtig machen: begrenzte Geräteressourcen (Speicher, CPU), häufige Plattform-Updates (iOS jährlich, Android vierteljährlich) und die Notwendigkeit schneller Feature-Auslieferung via CI/CD. Komplexer Code kann mit diesem Tempo nicht Schritt halten.
Eine Analyse von Apple WWDC 2023: „Embrace Swift Generics“ zeigte, dass das durchschnittliche iOS-Projekt 40–60% „toten Code“ enthält — Abstraktionen, die „für die Zukunft“ geschrieben wurden, aber nie verwendet werden. Dieser Code erhöht nicht nur die Binärgröße, sondern verlangsamt auch die Kompilierung und erschwert die Navigation. KISS verhindert dies: Schreiben Sie nur das, was jetzt benötigt wird.
Laut dem Android Developer Relations Report (2024) haben Projekte mit einem niedrigen Code-zu-Test-Verhältnis (weniger als 1:0.8) 67% mehr Produktionsfehler. Komplexer Code ist schwerer zu testen — dies ist eine direkte Bedrohung der Qualität. Einfachheit ist eine Voraussetzung für hohe Testabdeckung.
Messen Sie die Komplexität Ihres Codes anhand von Metriken: zyklomatische Komplexität — halten Sie jede Methode unter 10, idealerweise unter 5. Verwenden Sie Detekt (Android) oder SwiftLint (iOS) zur automatischen Überprüfung.
Typisches Overengineering ist die Erstellung einer abstrakten Repository-Factory in einem Projekt mit einer einzigen Datenquelle. Anstelle einer einfachen Repository-Klasse baut der Entwickler eine Kette: RepositoryFactory → IRepository → BaseRepository → RepositoryImpl — für die hypothetische Möglichkeit, die API auf GraphQL umzustellen.
Laut der JetBrains Developer Survey (2023) gaben 43% der Android-Entwickler zu, während des Refactorings eine Architekturschicht entfernt zu haben, weil sie nie genutzt wurde. KISS sagt: Erstellen Sie eine Abstraktion, wenn eine zweite Implementierungsoption auftaucht, nicht in Vorwegnahme.
Beginnen Sie mit einer konkreten Implementierung ohne Schnittstelle. Wenn eine zweite Datenquelle auftaucht — extrahieren Sie die Schnittstelle durch Refactoring (die IDE erledigt dies automatisch). Das ist schneller, als im Voraus eine Schnittstelle zu schreiben.
DI-Frameworks (Dagger, Hilt, Swinject) sind leistungsstarke Werkzeuge, aber sie provozieren oft Komplexität. Entwickler erstellen ein separates Modul für jede Entität, selbst wenn diese nur an einer Stelle verwendet wird. KISS-Alternative: manuelle Injektion über den Konstruktor für einfache Fälle.
// Overengineering: Modul für ein einzelnes Repository
@Module
object UserModule {
@Provides
fun provideUserRepo(): UserRepository = UserRepositoryImpl()
}
// KISS: Manuelle Injektion, wenn es nur ein Repository gibt
class UserViewModel(
private val repo: UserRepository = UserRepositoryImpl()
) { /* ... */ }
Die manuelle Injektion im Konstruktor ist das einfachste DI-Muster. Sie erfordert keine Codegenerierung, Annotationen oder Module. Wechseln Sie zu einem DI-Framework erst, wenn das Projekt 5+ Bildschirme erreicht und die manuelle Injektion schwer zu warten ist.
Android ViewModel ist eine häufige Quelle übermäßiger Komplexität. Entwickler fügen StateFlow, combine, flatMapLatest und Transformationsketten hinzu, wo ein einfaches MutableLiveData mit postValue ausreichen würde. KISS empfiehlt: Beginnen Sie mit der einfachsten Lösung (LiveData), verkomplizieren Sie nur für einen spezifischen Bedarf (State-Reset, Debounce).
// KISS: Einfaches ViewModel ohne reaktive Ketten
class ProfileViewModel : ViewModel() {
private val _name = MutableLiveData<String>()
val name: LiveData<String> = _name
fun loadUser(id: String) {
viewModelScope.launch {
_name.postValue(repo.getUser(id).name)
}
}
}
In diesem Beispiel verwendet das ViewModel eine Coroutine für die asynchrone Anfrage, LiveData zur Veröffentlichung des Ergebnisses. Kein StateFlow, kein Combine — nur das, was tatsächlich benötigt wird. Fügen Sie StateFlow hinzu, wenn ein unidirektionaler Datenfluss (UDF) mit explizitem Zustand erforderlich ist.
Im iOS-Bereich manifestiert sich das KISS-Prinzip durch die Bevorzugung von Strukturen (struct) gegenüber Klassen (class) für Datenmodelle. Strukturen sind Wertetypen, benötigen keine Speicherverwaltung via ARC und sind standardmäßig unveränderlich. Klassen sind nur gerechtfertigt, wenn Identität (zwei Referenzen auf dasselbe Objekt) oder Vererbung benötigt wird.
// KISS: struct statt class für das Modell
struct User: Codable {
let id: Int
let name: String
let email: String
}
// Overengineering: class mit manuellem init und deinit
class UserClass: NSObject {
let id: Int
init(id: Int) { self.id = id }
}
Die Struktur User erhält automatisch einen memberwise-Init, Equatable- und Hashable-Konformität (über alle Felder), Unveränderlichkeit und Sicherheit in Multithread-Umgebungen. Eine Klasse erfordert manuellen Init, NSObject-Implementierung und ist durch gemeinsamen Zustand anfällig für Wettlaufsituationen.
Die Netzwerkschicht ist ein weiterer Bereich, in dem KISS häufig verletzt wird. Entwickler fügen eine Interceptor-Kette mit 5+ Elementen, Serialisierung durch abstrakte Fabriken und Mapper für jeden Endpunkt hinzu. KISS-Lösung: eine URLSession mit Konfiguration und eine Decodierung via Codable/JSON.
Laut dem Apple URLSession Programming Guide (2023) deckt eine einfache Netzwerkschicht mit URLSession und Codable 95% der mobilen App-Szenarien ab. Komplexe Interceptor-Ketten werden nur für spezifische Fälle benötigt: Token-Erneuerung, Protokollierung, Verschlüsselung.
Beginnen Sie mit einer einfachen Netzwerkschicht auf Basis von URLSession + Codable. Fügen Sie Interceptors hinzu, wenn echte Anforderungen entstehen, nicht „für den Fall der Fälle“. Dies reduziert den Code der Netzwerkschicht um das 2–3-fache.
Einfachheit ist nicht dasselbe wie Primitivität. Eine einfache Lösung ist eine prägnante, klare Lösung, die die Aufgabe ohne Redundanz löst. Eine primitive Lösung ignoriert Best Practices und eine solide Architektur. Der Unterschied besteht darin, dass eine einfache Lösung leicht erweiterbar ist, eine primitive hingegen nicht.
Beispiel: Die Verwendung von Activity als einzige Entität für alle Bildschirme ist Primitivität, nicht Einfachheit. Einfachheit ist die Verwendung von Navigation Component mit verschiedenen Fragmenten für verschiedene Bildschirme, aber ohne unnötige Abstraktionen. KISS rechtfertigt keine schlechte Architektur.
Überprüfen Sie sich selbst: Kann sich Ihr Code ändern, wenn eine neue Funktion hinzugefügt wird? Wenn ja — ist die Einfachheit richtig. Wenn jede Funktion ein Umschreiben von allem erfordert — ist das Primitivität, refaktorieren Sie sofort.
Patterns (MVVM, MVI, Coordinator) sind keine Verkomplizierung, sondern Strukturierung. KISS verbietet nicht die Verwendung bewährter Architekturmuster. Es verbietet deren übermäßige Verwendung: drei Patterns, wo eines ausreichen würde. Der goldene Mittelweg ist ein Architekturmuster pro Projekt und nicht mehr als 2–3 Hilfsmuster (DI, Navigation).
Laut dem State of Mobile Architecture Report (2024) haben Projekte, die genau ein Architekturmuster verwenden, 34% weniger Fehler im ersten Entwicklungsjahr als „Frankenstein“-Projekte, die 3+ Patterns kombinieren. Wählen Sie MVVM oder MVI für ein mobiles Projekt — und bleiben Sie auf allen Bildschirmen dabei.
Mischen Sie nicht MVVM und MVI im selben Projekt. Wenn das Team MVVM gewählt hat — muss das gesamte Projekt MVVM folgen. Ausnahmen sind einzelne Feature-Module mit eigener Architekturentscheidung, aber dies muss eine bewusste Wahl sein.
Häufig gestellte Fragen
KISS (Keep It Simple, Stupid) ist ein Prinzip, das verlangt, Code so einfach wie möglich zu machen. Wenn eine Aufgabe ohne zusätzliche Klassen, Patterns und Abstraktionen gelöst werden kann — lösen Sie sie ohne diese. Eine einfache Lösung ist leichter zu verstehen, zu testen und zu ändern.
DRY verbietet Code-Duplizierung, KISS verbietet übermäßige Komplexität. Manchmal geraten sie in Konflikt: Der Versuch, Duplizierung zu beseitigen (DRY), kann zu einer komplexen Abstraktion führen (Verletzung von KISS). Die Rule of Three hilft beim Ausbalancieren: Abstrahieren Sie erst nach der dritten Wiederholung.
KISS kann gebrochen werden, wenn Sie eine zukünftige Anforderung sicher kennen: zum Beispiel die Unterstützung einer zweiten Plattform via KMM oder die Migration auf eine neue Architektur im nächsten Quartal. Die Bedingung: Die zukünftige Anforderung muss dokumentiert sein, keine hypothetische Annahme.
Verwenden Sie objektive Metriken: zyklomatische Komplexität (bis zu 10 pro Methode), Codezeilen pro Methode (bis zu 20), Verschachtelungstiefe (bis zu 3). Für Android — das Plugin Detekt, für iOS — SwiftLint. Subjektive Metrik: Ein neuer Entwickler sollte den Code in einer Minute verstehen.
Ja, KISS und SOLID sind kompatibel. SOLID betrifft die richtige Architektur, KISS die minimale Komplexität. Eine Verletzung von KISS tritt bei übermäßiger Anwendung von SOLID auf: Dutzende von Klassen zu erstellen, wo drei ausreichen würden. Die goldene Regel: SOLID bis zu einem vernünftigen Limit, KISS als Filter bei jedem Schritt.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch