---
name: scalability-clean-code
description: "Software architecture guidelines to maintain code readability (Clean Code, SOLID, DRY) and application scalability / Panduan arsitektur perangkat lunak untuk menjaga keterbacaan kode (Clean Code, SOLID, DRY) dan kemampuan skalabilitas aplikasi."
author: "Roedy Rustam"
---

# Scalability & Clean Code (2026 Edition)

[English](#english) | [Bahasa Indonesia](#bahasa-indonesia)

---

<a name="english"></a>
## English

### Orchestration & Integration
Connects and orchestrates with relevant domain skills like `brainstorming`, `zero-to-prod-orchestrator`, and `project-context-mapper` to ensure cohesive execution.

### Description
Software architecture guidelines for writing clean, scalable, and maintainable code. Covers SOLID principles, DRY/YAGNI/KISS, Clean Architecture layers, **Vertical Slice Architecture** (the modern alternative to layered architecture), Domain-Driven Design (DDD) patterns, and practical refactoring techniques.

### Trigger Conditions
- Refactoring a codebase that has become hard to understand or modify.
- Designing the architecture for a new feature or service.
- Identifying and eliminating code smells (God Classes, Feature Envy, Long Methods).
- Deciding between Layered Architecture vs Vertical Slice Architecture.
- Applying SOLID principles to a specific code problem.

### The SOLID Principles (With Modern Context)

#### Single Responsibility Principle (SRP)
A module/class/function should have one reason to change. In 2026 React/Node.js context:
- **Bad**: A React component that fetches data, transforms it, and renders UI.
- **Good**: Separate `useUserQuery()` hook (fetch), `transformUser()` util (transform), `UserCard` component (render).

#### Open/Closed Principle (OCP)
Open for extension, closed for modification. Use composition and strategy pattern:
```typescript
// Bad: modify existing code every time a new payment provider is added
function processPayment(type: 'stripe' | 'polar' | 'paypal', amount: number) {
  if (type === 'stripe') { /* ... */ }
  else if (type === 'polar') { /* ... */ }
}

// Good: extend by adding new providers, not modifying existing code
interface PaymentProvider {
  charge(amount: number): Promise<Receipt>;
}

class StripeProvider implements PaymentProvider { ... }
class PolarProvider implements PaymentProvider { ... }

function processPayment(provider: PaymentProvider, amount: number) {
  return provider.charge(amount);
}
```

#### Dependency Inversion Principle (DIP)
High-level modules should not depend on low-level modules — both should depend on abstractions:
```typescript
// Bad: handler directly imports concrete DB client
import { db } from './postgres-client';

// Good: inject the repository interface
interface UserRepository {
  findById(id: string): Promise<User | null>;
  save(user: User): Promise<void>;
}

async function getUser(repo: UserRepository, id: string) {
  return repo.findById(id);
}
```

### Vertical Slice Architecture (VSA)
The modern alternative to traditional layered architecture (Controller → Service → Repository). Organize code by **feature** (vertical slice) rather than by **technical layer** (horizontal slice):

```
Traditional (Layered):
src/
  controllers/    ← all controllers together
  services/       ← all services together
  repositories/   ← all repositories together

Vertical Slice:
src/
  features/
    users/
      create-user.handler.ts    ← all logic for "create user" in one place
      create-user.schema.ts
      create-user.test.ts
    products/
      list-products.handler.ts
      list-products.schema.ts
```

**Benefits of VSA**:
- Features are self-contained — easy to add, modify, delete, or move.
- No need to navigate 3-4 layers just to trace one user story.
- Natural boundary for microservice extraction.

```typescript
// features/users/create-user.handler.ts
// One file contains the complete "create user" vertical slice
import { z } from 'zod';
import { db } from '@/lib/db';
import { sendWelcomeEmail } from '@/lib/email';

export const CreateUserSchema = z.object({
  name: z.string().min(2),
  email: z.string().email(),
});

export type CreateUserInput = z.infer<typeof CreateUserSchema>;

export async function handleCreateUser(input: CreateUserInput) {
  const validated = CreateUserSchema.parse(input);
  
  const user = await db.user.create({ data: validated });
  await sendWelcomeEmail(user.email, user.name);
  
  return user;
}
```

### Clean Code Principles

#### Functions
- **Do one thing**: Functions should do one thing and do it well.
- **Small**: Aim for < 20 lines. If longer, extract sub-functions.
- **Descriptive names**: `getUsersByWorkspace()` not `getData()`.
- **No side effects**: Pure functions are predictable and testable.

#### Naming
- Variables: noun phrases (`userCount`, `activeWorkspaces`).
- Functions: verb phrases (`fetchUser`, `validateInput`, `sendEmail`).
- Boolean: question form (`isActive`, `hasPermission`, `canEdit`).
- Avoid abbreviations: `workspace` not `ws`, `configuration` not `cfg`.

#### Comments
- **Don't comment bad code — rewrite it.**
- Write self-documenting code: well-named variables and functions eliminate the need for most comments.
- **Do** comment: why (intent), not what (obvious from code).

#### DRY, YAGNI, KISS
- **DRY**: Don't Repeat Yourself — extract shared logic. But: avoid premature abstraction.
- **YAGNI**: You Aren't Gonna Need It — don't build features "just in case".
- **KISS**: Keep It Simple, Stupid — the simplest solution that works is usually best.

### Code Smells & Refactoring

| Smell | Symptom | Refactoring |
|---|---|---|
| **God Class** | Class does everything | Extract Class, Move Method |
| **Long Method** | Method > 30 lines | Extract Method |
| **Feature Envy** | Method uses another class's data excessively | Move Method |
| **Data Clumps** | Same 3+ params appear together repeatedly | Introduce Parameter Object |
| **Magic Numbers** | `if (status === 3)` | Extract Constant |
| **Shotgun Surgery** | One change requires edits in many places | Move Method, Inline Class |
| **Primitive Obsession** | Using string/int for domain concepts | Replace with Value Object |

### Architecture Decision Framework
When choosing an architecture, ask:
1. **What changes together?** Organize code that changes together.
2. **What is independently deployable?** Separate services by deployment boundary.
3. **What has different scaling needs?** Scale independently only what needs it.
4. **What is the team size?** Microservices add overhead — start monolith, extract when needed.

---

<a name="bahasa-indonesia"></a>
## Bahasa Indonesia

### Integrasi Orkestrasi
Terhubung dan mengorkestrasi skill domain yang relevan seperti `brainstorming`, `zero-to-prod-orchestrator`, dan `project-context-mapper` untuk memastikan eksekusi yang kohesif.

### Deskripsi
Panduan arsitektur perangkat lunak untuk menulis kode yang bersih, skalabel, dan mudah dirawat. Mencakup prinsip SOLID, DRY/YAGNI/KISS, lapisan Clean Architecture, **Vertical Slice Architecture** (alternatif modern dari layered architecture), pola Domain-Driven Design (DDD), dan teknik refactoring praktis.

### Kondisi Pemicu
- Merefaktor codebase yang sulit dipahami atau dimodifikasi.
- Merancang arsitektur untuk fitur atau layanan baru.
- Mengidentifikasi dan menghilangkan code smell (God Class, Feature Envy, Long Method).
- Memutuskan antara Layered Architecture vs Vertical Slice Architecture.
- Menerapkan prinsip SOLID pada masalah kode tertentu.

### Prinsip SOLID

#### SRP — Single Responsibility Principle
Setiap modul/kelas/fungsi harus memiliki satu alasan untuk berubah. Pisahkan pengambilan data, transformasi data, dan rendering UI.

#### OCP — Open/Closed Principle
Terbuka untuk ekstensi, tertutup untuk modifikasi. Gunakan komposisi dan pola strategi — tambah provider baru tanpa mengubah kode yang ada.

#### DIP — Dependency Inversion Principle
Modul tingkat tinggi tidak boleh bergantung pada modul tingkat rendah — keduanya harus bergantung pada abstraksi (interface).

### Vertical Slice Architecture (VSA)
Alternatif modern dari layered architecture tradisional. Organisasikan kode berdasarkan **fitur** (irisan vertikal), bukan lapisan teknis (irisan horizontal).

**Keuntungan VSA:**
- Fitur bersifat self-contained — mudah ditambah, dimodifikasi, dihapus, atau dipindah.
- Tidak perlu menavigasi 3-4 layer hanya untuk melacak satu user story.
- Batas natural untuk ekstraksi microservice.

### Prinsip Clean Code

#### Fungsi
- Lakukan satu hal dan lakukan dengan baik.
- Nama deskriptif: `getUsersByWorkspace()` bukan `getData()`.
- Tanpa efek samping: fungsi murni dapat diprediksi dan diuji.

#### Penamaan
- Variabel: frasa kata benda (`jumlahPengguna`, `workspaceAktif`).
- Fungsi: frasa kata kerja (`ambilPengguna`, `validasiInput`).
- Boolean: bentuk pertanyaan (`aktif`, `punyaIzin`, `bisaEdit`).

#### Komentar
- Jangan komen kode buruk — tulis ulang.
- Tulis kode yang mendokumentasikan dirinya sendiri.
- Komentar: **mengapa** (niat), bukan apa (jelas dari kode).

#### DRY, YAGNI, KISS
- **DRY**: Jangan ulangi diri sendiri — ekstrak logika bersama.
- **YAGNI**: Anda tidak akan membutuhkannya — jangan bangun fitur "untuk jaga-jaga".
- **KISS**: Tetap sederhana — solusi paling sederhana yang berfungsi biasanya terbaik.

### Code Smell & Refactoring
Identifikasi dan perbaiki: God Class, Long Method, Feature Envy, Data Clumps, Magic Numbers, Shotgun Surgery, Primitive Obsession.

### Framework Keputusan Arsitektur
1. **Apa yang berubah bersama?** Organisasikan kode yang berubah bersama.
2. **Apa yang dapat di-deploy secara independen?** Pisahkan layanan berdasarkan batas deployment.
3. **Apa yang memiliki kebutuhan scaling berbeda?** Scale secara independen hanya yang membutuhkannya.
4. **Berapa besar tim?** Microservices menambah overhead — mulai monolith, ekstrak saat diperlukan.
