KISS (Keep It Simple, Stupid) is a development principle that prescribes maximum simplicity of a system. Complexity should be added only when it is absolutely necessary, not just in case. According to a study from IEEE Transactions on Software Engineering (2020), code complexity correlates with defect density: modules with high cyclomatic complexity contain 3.6 times more bugs per thousand lines of code. KISS is not primitiveness, but a conscious choice of the simplest working solution.
Key Takeaways
KISS (Keep It Simple, Stupid) is a design principle that requires minimizing system complexity. It was formulated in the US Navy in the 1960s by engineer Kelly Johnson (Lockheed SR-71 Blackbird). Johnson insisted that the aircraft should be repairable by a mechanic in the field without special tools — that is the essence of KISS.
In software development, KISS means: a solution should be as simple as possible, but no simpler (the second part of the phrase attributed to Albert Einstein). Simplicity is not a synonym for primitiveness; a simple solution performs the task with minimal redundancy.
A study by Google Research (2022) showed that the average onboarding time for a new developer is 3 weeks in projects adhering to KISS versus 10 weeks in projects with excessive architecture. Simple code is an investment in the onboarding speed of new team members.
Use KISS as a filter: before adding a new abstraction, ask yourself “does this solve a problem that exists today, or a problem that might arise in a year?” If the latter — don’t do it.
Occam’s Razor (14th century) is a philosophical principle: “entities should not be multiplied without necessity.” In programming, this means: of two solutions that equally satisfy the requirements, choose the one with fewer entities (classes, modules, dependencies). KISS is the practical implementation of Occam’s Razor in code.
The difference is that Occam’s Razor is a general principle of cognition, while KISS is a specific engineering practice with measurable results: reduced cyclomatic complexity, fewer lines of code, shorter code review time. Metrics make it possible to objectively assess compliance with KISS.
Follow this metric: code is considered “simple enough” if a new developer understands the fragment in one minute without comments. If more time is needed — simplify.
Mobile development has three characteristics that make KISS especially important: limited device resources (memory, CPU), frequent platform updates (iOS annually, Android quarterly), and the need for fast feature delivery via CI/CD. Complex code cannot keep up with this pace.
An analysis from Apple WWDC 2023: “Embrace Swift Generics” showed that the average iOS project contains 40–60% “dead code” — abstractions written “for the future” that are never used. This code not only increases binary size but also slows down compilation and complicates navigation. KISS prevents this: write only what is needed now.
According to the Android Developer Relations Report (2024), projects with a low code-to-test ratio (less than 1:0.8) have 67% more production bugs. Complex code is harder to test — this is a direct threat to quality. Simplicity is a prerequisite for high test coverage.
Measure the complexity of your code through metrics: cyclomatic complexity — keep each method below 10, ideally below 5. Use Detekt (Android) or SwiftLint (iOS) for automated checking.
Typical overengineering is creating an abstract repository factory in a project with a single data source. Instead of a simple Repository class, the developer builds a chain: RepositoryFactory → IRepository → BaseRepository → RepositoryImpl — for the hypothetical possibility of switching the API to GraphQL.
According to the JetBrains Developer Survey (2023), 43% of Android developers admitted to having thrown out an architectural layer during refactoring because it was never used. KISS says: create an abstraction when a second implementation option appears, not in anticipation.
Start with a concrete implementation without an interface. When a second data source appears — extract the interface through refactoring (the IDE will do it automatically). This is faster than writing an interface in advance.
DI frameworks (Dagger, Hilt, Swinject) are powerful tools, but they often provoke complexity. Developers create a separate module for every entity, even if it is used in only one place. KISS alternative: manual constructor injection for simple cases.
// Overengineering: module for a single repository
@Module
object UserModule {
@Provides
fun provideUserRepo(): UserRepository = UserRepositoryImpl()
}
// KISS: manual injection if there is one repository
class UserViewModel(
private val repo: UserRepository = UserRepositoryImpl()
) { /* ... */ }
Manual constructor injection is the simplest DI pattern. It requires no code generation, annotations, or modules. Switch to a DI framework only when the project reaches 5+ screens and manual injection becomes hard to maintain.
Android ViewModel is a frequent source of excessive complexity. Developers add StateFlow, combine, flatMapLatest, and chains of transformations where simple MutableLiveData with postValue would suffice. KISS recommends: start with the simplest solution (LiveData), complicate only for a specific need (state reset, debounce).
// KISS: simple ViewModel without reactive chains
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 this example, the ViewModel uses a coroutine for the async request, LiveData for publishing the result. No StateFlow, no combine — only what is actually needed. Add StateFlow when a unidirectional data flow (UDF) with explicit state is required.
In iOS, the KISS principle manifests through preferring structs over classes for data models. Structs are value types, do not require memory management via ARC, and are immutable by default. Classes are justified only when identity (two references to the same object) or inheritance is needed.
// KISS: struct instead of class for the model
struct User: Codable {
let id: Int
let name: String
let email: String
}
// Overengineering: class with manual init and deinit
class UserClass: NSObject {
let id: Int
init(id: Int) { self.id = id }
}
The User struct automatically gets a memberwise init, Equatable and Hashable conformance (by all fields), immutability, and thread safety. A class requires manual init, NSObject implementation, and is susceptible to race conditions through shared state.
The networking layer is another area where KISS is often violated. Developers add an Interceptor chain of 5+ elements, serialization through abstract factories, and mappers for every endpoint. KISS solution: one URLSession with configuration and one decoding via Codable/JSON.
According to the Apple URLSession Programming Guide (2023), a simple networking layer with URLSession and Codable covers 95% of mobile app scenarios. Complex Interceptor chains are needed only for specific cases: token refresh, logging, encryption.
Start with a simple networking layer based on URLSession + Codable. Add Interceptors as real needs arise, not “just in case.” This reduces networking layer code by 2–3 times.
Simplicity is not the same as primitiveness. A simple solution is a concise, clear solution that solves the task without redundancy. A primitive solution ignores best practices and sound architecture. The difference is that a simple solution is easy to extend, while a primitive one is not.
Example: using Activity as the only entity for all screens is primitiveness, not simplicity. Simplicity is using Navigation Component with different Fragments for different screens, but without unnecessary abstractions. KISS does not justify poor architecture.
Check yourself: can your code change when adding a new feature? If yes — the simplicity is correct. If every feature requires rewriting everything — that is primitiveness, refactor immediately.
Patterns (MVVM, MVI, Coordinator) are not complication, but structuring. KISS does not forbid using proven architectural patterns. It prohibits their excessive use: three patterns where one would suffice. The sweet spot is one architectural pattern per project and no more than 2–3 auxiliary ones (DI, Navigation).
According to the State of Mobile Architecture Report (2024), projects using exactly one architectural pattern have 34% fewer bugs in the first year of development than “Frankenstein” projects combining 3+ patterns. Choose MVVM or MVI for a mobile project — and stick with it across all screens.
Do not mix MVVM and MVI in the same project. If the team chose MVVM — the entire project should follow MVVM. Exceptions are individual feature modules with their own architectural decision, but this must be a conscious choice.
Frequently Asked Questions
KISS (Keep It Simple, Stupid) is a principle that requires making code as simple as possible. If a task can be solved without extra classes, patterns, and abstractions — solve it without them. A simple solution is easier to understand, test, and change.
DRY forbids code duplication, KISS forbids excessive complexity. Sometimes they conflict: an attempt to eliminate duplication (DRY) can lead to a complex abstraction (violating KISS). The Rule of Three helps balance: abstract only after the third repetition.
KISS can be broken when you know a future requirement for certain: for example, supporting a second platform via KMM or migrating to a new architecture in the next quarter. The condition: the future requirement must be documented, not a hypothetical assumption.
Use objective metrics: cyclomatic complexity (up to 10 per method), lines of code per method (up to 20), nesting level (up to 3). For Android — Detekt plugin, for iOS — SwiftLint. Subjective metric: a new developer should understand the code in one minute.
Yes, KISS and SOLID are compatible. SOLID is about correct architecture, KISS is about minimal complexity. Violation of KISS occurs when SOLID is applied excessively: creating a dozen classes where three would suffice. The golden rule: SOLID up to a reasonable limit, KISS as a filter at every step.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also