KISS (Keep It Simple, Stupid) — zasada programowania nakazująca maksymalną prostotę systemu. Złożoność powinna być dodawana tylko wtedy, gdy jest absolutnie niezbędna, a nie na zapas. Według badań IEEE Transactions on Software Engineering (2020), złożoność kodu koreluje z gęstością defektów: moduły o wysokiej złożoności cyklomatycznej zawierają 3,6 razy więcej błędów na tysiąc wierszy. KISS — to nie prymitywność, ale świadomy wybór najprostszego działającego rozwiązania.
Najważniejsze
KISS (Keep It Simple, Stupid) — zasada projektowania wymagająca minimalizacji złożoności systemu. Sformułowana w US Navy w latach 60. XX wieku przez inżyniera Kelly'ego Johnsona (Lockheed SR-71 Blackbird). Johnson wymagał, aby samolot mógł być naprawiany przez mechanika w warunkach polowych bez specjalnych narzędzi — to jest właśnie istota KISS.
W programowaniu KISS oznacza: rozwiązanie powinno być tak proste, jak to możliwe, ale nie prostsze (druga część zdania przypisywana Albertowi Einsteinowi). Prostota — to nie synonim prymitywności; proste rozwiązanie wykonuje zadanie z minimalną nadmiarowością.
Badanie Google Research (2022) wykazało: średni czas wejścia w projekt dla nowego programisty wynosi 3 tygodnie w projektach zgodnych z KISS w porównaniu do 10 tygodni w projektach z nadmierną architekturą. Prosty kod to inwestycja w szybkość adaptacji nowych członków zespołu.
Stosuj KISS jako filtr: przed dodaniem nowej abstrakcji zapytaj siebie „rozwiązuje to problem, który pojawił się dzisiaj, czy problem, który może pojawić się za rok?” Jeśli to drugie — nie rób tego.
Brzytwa Ockhama (XIV wiek) — zasada filozoficzna: „nie należy mnożyć bytów bez potrzeby”. W programowaniu oznacza to: z dwóch rozwiązań równie spełniających wymagania wybierz to, które ma mniej bytów (klas, modułów, zależności). KISS — praktyczna realizacja brzytwy Ockhama w kodzie.
Różnica polega na tym, że brzytwa Ockhama to ogólna zasada poznania, a KISS to konkretna praktyka inżynierska z mierzalnym rezultatem: zmniejszenie złożoności cyklomatycznej, redukcja liczby wierszy kodu, skrócenie czasu code review. Metryki pozwalają obiektywnie ocenić przestrzeganie KISS.
Kieruj się metryką: kod jest uznawany za „wystarczająco prosty”, jeśli nowy programista rozumie fragment w ciągu jednej minuty bez komentarzy. Jeśli potrzeba więcej — upraszczaj.
Programowanie mobilne ma trzy cechy, które czynią KISS szczególnie ważnym: ograniczone zasoby urządzenia (pamięć, procesor), częste aktualizacje platform (iOS corocznie, Android — kwartalnie) i konieczność szybkiego dostarczania funkcji przez CI/CD. Złożony kod nie wytrzymuje tego tempa.
Analiza Apple WWDC 2023: „Embrace Swift Generics” wykazała: średni projekt iOS zawiera 40–60% „martwego kodu” — abstrakcji napisanych na przyszłość, które nigdy nie są używane. Ten kod nie tylko zwiększa rozmiar pliku binarnego, ale także spowalnia kompilację i utrudnia nawigację. KISS zapobiega temu: pisz tylko to, co jest potrzebne teraz.
Według danych Android Developer Relations Report (2024), projekty z niskim stosunkiem kodu do testów (poniżej 1:0.8) mają o 67% więcej błędów w produkcji. Złożony kod jest trudniejszy do testowania — to bezpośrednie zagrożenie dla jakości. Prostota — warunek konieczny wysokiego pokrycia testami.
Mierz złożoność swojego kodu za pomocą metryk: złożoność cyklomatyczna (Cyclomatic Complexity) — utrzymuj każdą metodę poniżej 10, idealnie do 5. Używaj Detekt (Android) lub SwiftLint (iOS) do automatycznego sprawdzania.
Typowy overengineering — tworzenie abstrakcyjnej fabryki repozytoriów w projekcie z jednym źródłem danych. Zamiast prostej klasy Repository programista buduje łańcuch: RepositoryFactory → IRepository → BaseRepository → RepositoryImpl — dla hipotetycznej zmiany API na GraphQL.
Według ankiety JetBrains Developer Survey (2023), 43% programistów Android przyznało, że przynajmniej raz wyrzucili warstwę architektoniczną podczas refaktoringu, ponieważ nie była używana. KISS mówi: twórz abstrakcję, gdy pojawia się druga wersja implementacji, a nie w oczekiwaniu.
Zacznij od konkretnej implementacji bez interfejsu. Gdy pojawi się drugie źródło danych — wyodrębnij interfejs przez refaktoring (IDE zrobi to automatycznie). To szybsze niż pisanie interfejsu z góry.
Frameworki DI (Dagger, Hilt, Swinject) — potężne narzędzia, ale często prowokują komplikowanie. Programiści tworzą osobny moduł dla każdej encji, nawet jeśli jest używana w jednym miejscu. Alternatywa KISS: ręczne wstrzykiwanie przez konstruktor w prostych przypadkach.
// Overengineering: moduł dla jednego repozytorium
@Module
object UserModule {
@Provides
fun provideUserRepo(): UserRepository = UserRepositoryImpl()
}
// KISS: ręczne wstrzykiwanie, jeśli repozytorium jest jedno
class UserViewModel(
private val repo: UserRepository = UserRepositoryImpl()
) { /* ... */ }
Ręczne wstrzykiwanie w konstruktorze — najprostszy wzorzec DI. Nie wymaga generowania kodu, adnotacji ani modułów. Przełączaj się na framework DI dopiero gdy projekt osiągnie 5+ ekranów i ręczne wstrzykiwanie staje się trudne do utrzymania.
Android ViewModel — częste źródło nadmiernej złożoności. Programiści dodają StateFlow, combine, flatMapLatest i łańcuchy transformacji tam, gdzie wystarczy prosty MutableLiveData z postValue. KISS zaleca: zaczynaj od najprostszego rozwiązania (LiveData), komplikuj tylko pod konkretne zadanie (resetowanie stanu, debounce).
// KISS: prosty ViewModel bez reaktywnych łańcuchów
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)
}
}
}
W tym przykładzie ViewModel używa coroutine do asynchronicznego zapytania, LiveData do publikacji wyniku. Żadnego StateFlow, żadnego combine — tylko to, co jest naprawdę potrzebne. Dodawaj StateFlow, gdy wymagany jest jednostronny przepływ danych (UDF) z jawnym stanem.
W iOS zasada KISS przejawia się przez preferowanie struktur (struct) nad klasami (class) dla modeli danych. Struktury to value type, nie wymagają zarządzania pamięcią przez ARC, są domyślnie niemutowalne. Klasy są uzasadnione tylko w przypadku konieczności tożsamości (dwa wskaźniki do jednego obiektu) lub dziedziczenia.
// KISS: struct zamiast class dla modelu
struct User: Codable {
let id: Int
let name: String
let email: String
}
// Overengineering: class z manualnym init i deinit
class UserClass: NSObject {
let id: Int
init(id: Int) { self.id = id }
}
Struktura User automatycznie otrzymuje memberwise init, obsługę Equatable i Hashable (po wszystkich polach), niemutowalność i bezpieczeństwo w środowisku wielowątkowym. Klasa wymaga ręcznego init, implementacji NSObject i jest podatna na race conditions przez wspólny stan.
Warstwa sieciowa — kolejny obszar, gdzie KISS jest często naruszany. Programiści dodają łańcuch Interceptor z 5+ elementami, serializację przez abstrakcyjne fabryki i mappery dla każdego endpointu. Rozwiązanie KISS: jeden URLSession z konfiguracją i jeden dekoding przez Codable/JSON.
Zgodnie z zaleceniami Apple: URLSession Programming Guide (2023), prosta warstwa sieciowa na URLSession z Codable pokrywa 95% scenariuszy aplikacji mobilnej. Złożone łańcuchy Interceptor są potrzebne tylko do specyficznych przypadków: odświeżanie tokenów, logowanie, szyfrowanie.
Zacznij od prostej warstwy sieciowej na URLSession + Codable. Dodawaj Interceptor w miarę rzeczywistej potrzeby, a nie na zapas. To skraca kod warstwy sieciowej 2–3 razy.
Prostota — to nie to samo co prymitywność. Proste rozwiązanie jest zwięzłe, zrozumiałe i rozwiązuje zadanie bez nadmiarowości. Prymitywne — ignoruje best practices i zdrową architekturę. Różnica polega na tym, że proste rozwiązanie łatwo rozszerzyć, a prymitywne — nie.
Przykład: używanie Activity jako jedynej encji dla wszystkich ekranów — to prymitywność, a nie prostota. Prostota — użycie Navigation Component z różnymi Fragment dla różnych ekranów, ale bez zbędnych abstrakcji. KISS nie usprawiedliwia złej architektury.
Sprawdzaj siebie: czy twój kod może się zmienić przy dodaniu nowej funkcji? Jeśli tak — prostota jest właściwa. Jeśli dla każdej funkcji trzeba przepisywać wszystko — to prymitywność, pilnie refaktoryzuj.
Wzorce (MVVM, MVI, Coordinator) — to nie komplikacja, ale strukturyzacja. KISS nie zabrania używania sprawdzonych wzorców architektonicznych. Zabrania się ich nadmiernego stosowania: trzy wzorce tam, gdzie wystarczyłby jeden. Złoty środek — jeden wzorzec architektoniczny na projekt i nie więcej niż 2–3 pomocnicze (DI, Navigation).
Zgodnie z State of Mobile Architecture Report (2024), projekty używające dokładnie jednego wzorca architektonicznego mają o 34% mniej błędów w pierwszym roku rozwoju niż projekty-„frankensteiny” z kombinacją 3+ wzorców. Wybierz MVVM lub MVI dla projektu mobilnego — i trzymaj się go na wszystkich ekranach.
Nie mieszaj MVVM i MVI w jednym projekcie. Jeśli zespół wybrał MVVM — cały projekt powinien stosować MVVM. Wyjątek — osobne moduły funkcji z własnym rozwiązaniem architektonicznym, ale to powinien być świadomy wybór.
Często zadawane pytania
KISS (Keep It Simple, Stupid) — zasada wymagająca, aby kod był maksymalnie prosty. Jeśli zadanie można rozwiązać bez zbędnych klas, wzorców i abstrakcji — rozwiązuj bez nich. Proste rozwiązanie łatwiej zrozumieć, przetestować i zmienić.
DRY zabrania powielania kodu, KISS — nadmiernej złożoności. Czasami są w konflikcie: próba wyeliminowania powielania (DRY) może prowadzić do złożonej abstrakcji (naruszenie KISS). Reguła trzech (Rule of Three) pomaga zachować równowagę: abstrahuj dopiero po trzecim powtórzeniu.
KISS można naruszyć, gdy dokładnie znasz przyszłe wymaganie: na przykład wsparcie drugiej platformy przez KMM lub migrację na nową architekturę w następnym kwartale. Warunek: przyszłe wymaganie musi być udokumentowane, a nie hipotetycznym założeniem.
Używaj obiektywnych metryk: złożoność cyklomatyczna (do 10 na metodę), liczba wierszy na metodę (do 20), poziom zagnieżdżenia (do 3). Dla Android — wtyczka Detekt, dla iOS — SwiftLint. Subiektywna metryka: nowy programista powinien rozumieć kod w ciągu jednej minuty.
Tak, KISS i SOLID są zgodne. SOLID dotyczy właściwej architektury, KISS — minimalnej złożoności. Naruszenie KISS powstaje przy nadmiernym stosowaniu SOLID: tworzeniu dziesięciu klas tam, gdzie wystarczyłyby trzy. Złota zasada: SOLID do rozsądnego limitu, KISS jako filtr na każdym kroku.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również