KISS (Keep It Simple, Stupid): Solusi paling sederhana yang bekerja biasanya adalah solusi terbaik. Jangan membuat sesuatu jadi rumit kalau bisa sederhana.
Masalah: Developer sering tergoda untuk menulis kode yang "pintar" — teknik advanced yang sebenarnya tidak perlu. Kode pintar itu musuh maintenance.
Sebelum — kode "pintar" yang tidak perlu:
// BURUK: over-engineered untuk hal sederhana
const isEven = num => !(num & 1); // bitwise — "pintar" tapi bikin bingung
const double = arr => arr.reduce((a, c) => [...a, c * 2], []); // reduce overkill
const getName = user => user?.profile?.name ?? (() => { throw new Error("no name"); })();
// BERSIH: sederhana, jelas, bekerja
function isEven(num) {
return num % 2 === 0;
}
function doubleAll(numbers) {
return numbers.map(n => n * 2);
}
function getName(user) {
if (!user?.profile?.name) throw new Error("no name");
return user.profile.name;
}
Sebelum — abstraksi yang tidak perlu:
// BURUK: class untuk hal yang fungsi biasa bisa handle
class StringValidator {
constructor(value) {
this.value = value;
}
isNotEmpty() {
return this.value.trim() !== "";
}
isMinLength(min) {
return this.value.length >= min;
}
isMaxLength(max) {
return this.value.length <= max;
}
validate(rules) {
return rules.every(rule => rule(this));
}
}
const validator = new StringValidator(name);
if (validator.isNotEmpty() && validator.isMinLength(3)) { ... }
// BERSIH: fungsi sederhana
function isValidName(name) {
return name.trim() !== "" && name.length >= 3;
}
if (isValidName(name)) { ... }
Sebelum — state management overkill:
// BURUK: Redux + saga + selector untuk counter
// actions.js, reducers.js, sagas.js, selectors.js, store.js...
// 5 file, 100 baris untuk increment counter
// BERSIH: cukup useState
const [count, setCount] = useState(0);
Aturan praktis KISS:
- Pilih solusi yang paling sedikit moving parts
// BURUK: custom caching solution
class CacheManager {
constructor() { this.cache = new Map(); this.ttl = new Map(); }
set(key, value, ttl) { ... }
get(key) { ... }
invalidate(key) { ... }
cleanup() { ... }
}
// BERSIH: pakai yang sudah ada
const cache = new Map(); // untuk kasus sederhana
// atau pakai library yang sudah battle-tested
- Jangan optimasi sebelum waktunya
// BURUK: micro-optimasi yang tidak terukur
const len = arr.length;
for (let i = 0; i < len; i++) { ... } // "cache length" — tidak perlu di JS modern
// BERSIH: tulis yang paling readable
for (const item of arr) { ... }
// atau
arr.forEach(item => { ... });
- Jangan abstraksi terlalu dini
// Kalau cuma dipakai 1 tempat, tidak perlu jadi fungsi terpisah
// Kalau dipakai 2 tempat, pertimbangkan
// Kalau dipakai 3+ tempat, baru extract
// BURUK: fungsi yang hanya dipanggil sekali
function getActiveUserCount(users) {
return users.filter(u => u.isActive).length;
}
const count = getActiveUserCount(users);
// BERSIH: inline kalau hanya dipakai sekali
const activeCount = users.filter(u => u.isActive).length;
KISS bukan berarti "jangan belajar hal advanced". KISS artinya: gunakan tool yang sesuai dengan masalahnya. Regex bagus untuk pattern matching. Tapi jangan pakai regex untuk mengecek apakah string kosong.
Pertanyaan sebelum menulis kode:
- Apakah ada cara yang lebih sederhana?
- Apakah developer junior bisa memahami ini dalam 30 detik?
- Apakah saya menambah complexity karena "mungkin perlu nanti"?
🎭 Analogi sehari-hari
KISS itu kayak bedanya nelpon vs nge-set up automasi rumah pintar untuk nyalain lampu. Mau nyalain lampu kamar? Tekan saklar (1 step). Versus: pasang Alexa + IoT bulb + voice routine + scheduler app + IFTTT integration biar bisa bilang "Alexa, lampu kamar". Berhasil? Iya. Worth it? Buat masalah simple kayak nyalain lampu → NO. Buat masalah kompleks (control 50 device dari smartphone pas kerja remote) → mungkin worth it. Aturan KISS: pilih solusi paling simple yang KERJA buat masalah ini. Jangan pake mesin teknologi fancy buat masalah yang saklar mekanis cukup. Setiap layer abstraksi tambah cognitive load — bayar biaya itu cuma kalau dapet manfaat nyata.
⚠️ Jebakan yang sering ditemui
- "Smart code" syndrome — bitwise tricks, ternary nested, one-liner reduce kompleks. Lihat keren tapi gak bantu. Boring code that works > clever code that confuses.
- Premature abstraction — bikin class/factory/HOC dari awal "siapa tau perlu nanti". 90% kasus = nanti gak perlu, sekarang nambah complexity.
- Pakai library besar untuk masalah kecil — install lodash buat 1 fungsi
pick()yang bisa ditulis 3 baris. Audit dependency. - Premature optimization —
cache .length,for vs forEach micro-bench. Untouchable di JS modern. Profile dulu, optimize setelah ada bukti masalah. - Pikir "advanced = better" — Redux untuk app dengan 5 state?
useState+ Context jauh lebih KISS. - Boilerplate framework override — generate 50 file untuk feature yang butuh 1 file. Tools yang ngeluarin boilerplate banyak = tanda tools terlalu rumit untuk problem.
- Pikir KISS = jangan belajar advanced — SALAH. KISS = pilih tool yang TEPAT untuk masalah. Regex bagus untuk pattern matching, jelek untuk cek string kosong.
Tanda Kode "Over-Engineered"
- Banyak abstraksi cuma dipake 1x —
BaseUserManager → UserService → UserController → UserRepositoryuntuk CRUD simple - Configuration explosion — 50 option config untuk fitur yang dipake 2 cara
- Generic everything — semua dibikin generic "siapa tau" → susah dibaca
- Pattern matching kompetitif — paksa pake design pattern di mana-mana (Factory, Singleton, Observer)
- Junior developer butuh 1 jam buat paham — kode yang harusnya simple
Alternatif KISS
// Bukan: pakai class besar
class StringValidator { ... }
// KISS: fungsi sederhana
function isValidName(name) { return name.trim().length >= 3 }
// Bukan: Redux untuk state lokal
// KISS: useState
// Bukan: custom event bus implementation
// KISS: pakai library proven (mitt, EventEmitter) atau native CustomEvent
// Bukan: build microservice dari hari pertama
// KISS: monolith dulu, pecah ke service pas perlu (modular monolith)
🎯 Pertanyaan sebelum menulis kode
- "Apakah ada cara lebih sederhana?" → cari alternatif simple
- "Apakah developer junior bisa paham dalam 30 detik?" → kalau tidak, terlalu kompleks
- "Saya nambah complexity karena mungkin perlu nanti?" → YAGNI (You Aren't Gonna Need It)
- "Saya pakai pattern ini karena perlu, atau biar terlihat fancy?" → jujur ke diri sendiri
- "Bisa ditulis 5 baris yang clear daripada 1 baris yang clever?" → pilih clear
Aturan emas: boring code is good code. Kode boring = predictable, easy to debug, easy to onboard. Saving "kepintaran" untuk problem yang BENERAN butuh.
TL;DR: KISS = solusi paling sederhana yang KERJA. Hindari "smart code" (bitwise tricks, nested ternary), premature abstraction (class/factory yang gak perlu), premature optimization (micro-bench), pakai tool berlebihan (Redux untuk state simple). Tanda over-engineering: abstraksi cuma dipake 1x, configuration explosion, generic everything. Boring code > clever code. KISS bukan "jangan belajar advanced" tapi "pakai tool yang TEPAT". YAGNI: jangan tambah complexity untuk "mungkin perlu nanti".