Materi/Clean Code & Best Practices

Clean Code & Best Practices

Intermediate+280 XP

Chapter

Clean Code & Best Practices

Clean Code adalah kode yang mudah dibaca, dipahami, dan dimodifikasi oleh developer lain (termasuk kamu sendiri 6 bulan ke depan).

Penamaan yang Bermakna

// ❌ Tidak jelas
const d = new Date()
const arr = users.filter(u => u.a > 18)
function calc(x, y) { return x * y * 0.1 }

// ✅ Jelas dan deskriptif
const currentDate = new Date()
const adultUsers = users.filter(user => user.age > 18)
function calculateTax(price, quantity) { return price * quantity * 0.1 }

Fungsi Kecil & Satu Tujuan

// ❌ Fungsi terlalu besar, banyak tujuan
async function handleUser(req, res) {
  const { email, password, nama } = req.body
  if (!email || !password || !nama) return res.status(400).json({ error: '...' })
  const emailRegex = /^[^s@]+@[^s@]+.[^s@]+$/
  if (!emailRegex.test(email)) return res.status(400).json({ error: '...' })
  const existing = await User.findOne({ email })
  if (existing) return res.status(409).json({ error: '...' })
  const hashed = await bcrypt.hash(password, 12)
  const user = await User.create({ nama, email, password: hashed })
  const token = jwt.sign({ userId: user._id }, process.env.JWT_SECRET)
  res.json({ user, token })
}

// ✅ Dipecah jadi fungsi kecil
function validateRegisterInput(data) {
  const { email, password, nama } = data
  if (!email || !password || !nama) throw new Error('Semua field wajib diisi')
  if (!/^[^s@]+@[^s@]+.[^s@]+$/.test(email)) throw new Error('Email tidak valid')
  if (password.length < 6) throw new Error('Password minimal 6 karakter')
}

async function checkEmailUnique(email) {
  const existing = await User.findOne({ email })
  if (existing) throw new Error('Email sudah terdaftar')
}

async function createUserWithToken(userData) {
  const hashed = await bcrypt.hash(userData.password, 12)
  const user = await User.create({ ...userData, password: hashed })
  const token = jwt.sign({ userId: user._id }, process.env.JWT_SECRET)
  return { user, token }
}

async function handleRegister(req, res) {
  try {
    validateRegisterInput(req.body)
    await checkEmailUnique(req.body.email)
    const result = await createUserWithToken(req.body)
    res.status(201).json(result)
  } catch (error) {
    res.status(400).json({ error: error.message })
  }
}

SOLID Principles

S — Single Responsibility

Satu class/fungsi, satu tanggung jawab.

O — Open/Closed

Terbuka untuk extension, tertutup untuk modifikasi.

D — Don't Repeat Yourself (DRY)

// ❌ Duplikasi kode
function validateEmail(email) {
  return /^[^s@]+@[^s@]+.[^s@]+$/.test(email)
}
// ... di tempat lain
if (!/^[^s@]+@[^s@]+.[^s@]+$/.test(userEmail)) { ... }

// ✅ Tulis sekali, pakai berulang
const isValidEmail = (email) => /^[^s@]+@[^s@]+.[^s@]+$/.test(email)