Use Cases (Diperbarui: 1/6/2026)

Automasi Refactoring yang Aman dengan Claude Code

Workflow aman untuk refactoring dengan Claude Code: contoh before/after, test, git diff, review, risiko, dan prompt siap pakai.

Automasi Refactoring yang Aman dengan Claude Code

Mulai dari batas aman, bukan dari “rapikan semuanya”

Cara paling aman memakai Claude Code untuk refactoring bukan meminta “bersihkan seluruh codebase”. Kalimat itu terdengar cepat, tetapi biasanya menghasilkan diff besar yang sulit direview. Refactoring berarti memperbaiki struktur internal tanpa mengubah perilaku yang dilihat user, API, test, dan sistem lain. Kalau batas ini kabur, automasi bisa berubah menjadi perubahan fitur tanpa sengaja.

Di artikel ini, Claude Code dipakai sebagai partner kerja praktis: membaca repo, membuat rencana kecil, mengubah satu bagian, menjalankan verifikasi, lalu menjelaskan git diff. Dokumentasi resmi common workflows berguna untuk memahami pola kerja ini. Untuk izin command dan konfigurasi proyek, lihat juga dokumentasi settings.

Kalau tim masih menyiapkan aturan penggunaan, baca juga panduan permission Claude Code dan context management Claude Code. Fokus artikel ini adalah rutinitas lapangan: apa yang ditanyakan dulu, perubahan apa yang aman untuk pemula, cara mengetes, dan cara membaca hasilnya.

Catatan Masa dari percobaan kecil: Claude Code sangat membantu untuk rename, extract pure function, memperjelas tipe TypeScript, dan menambahkan regression test. Ia menjadi sulit direview saat prompt terlalu luas, misalnya “modernisasi service ini”. Workflow yang membosankan justru yang menghasilkan nilai: scope sempit, test terlihat, diff kecil.

Workflow aman: inspect, plan, satu diff, verify

Gunakan urutan ini sampai tim cukup percaya dengan prosesnya.

LangkahYang dilakukan Claude CodeYang dicek manusia
1. InspectMembaca file, dependency, dan testScope tidak terlalu luas
2. PlanMembuat rencana maksimal tiga langkahTidak ada perubahan behavior tersembunyi
3. EditMengubah satu tema sajaDiff cukup kecil untuk direview
4. VerifyMenjalankan test, typecheck, lintKegagalan dijelaskan jelas
5. ReviewMerangkum git diff dan risikoBehavior before/after sama

Mulai dengan prompt tanpa edit.

Inspect repository ini untuk mencari kandidat refactoring yang aman.
Jangan edit file dulu.

Kondisi:
- Jangan mengubah external behavior
- Satu diff maksimal tiga file
- Prioritaskan area yang sudah punya test
- Kembalikan tabel berisi kandidat, alasan, command verifikasi, dan risiko

Kalimat “Jangan edit file dulu” penting. Claude Code bisa bergerak cepat dari membaca ke mengubah. Memisahkan investigasi dan implementasi menurunkan risiko.

Buat branch dan simpan baseline.

git status --short
git checkout -b refactor/safe-extract-order-total
npm test
npm run typecheck
npm run lint

Sesuaikan command dengan package.json. Jika test sudah gagal sebelum refactoring, catat. Kalau tidak, nanti sulit membedakan apakah kegagalan datang dari perubahan Claude Code atau dari kondisi lama.

Use case 1: Rename dan extract pure function kecil

Latihan paling aman adalah memperbaiki nama dan mengekstrak pure function. Pure function mengembalikan output yang sama untuk input yang sama, tanpa update database, mengirim email, memanggil API, atau mengubah global state. Claude Code cocok di area ini karena suksesnya mudah diuji.

// before: src/domain/order.ts
export function calc(o: { items: { p: number; q: number }[]; d?: number }) {
  let t = 0;
  for (const i of o.items) {
    t += i.p * i.q;
  }
  if (o.d) {
    t = t - o.d;
  }
  return Math.max(t, 0);
}

Kode ini pendek, tetapi p, q, dan d tidak menjelaskan domain. Minta Claude Code menulis test dulu, lalu memperbaiki nama.

Refactor fungsi calc di src/domain/order.ts dengan aman.

Syarat:
- Tambahkan unit test untuk mengunci behavior saat ini sebelum mengubah implementasi
- Nama export calc tetap dipertahankan dalam diff ini
- Perjelas nama variable dan type
- Pertahankan aturan total tidak pernah negatif
- Jalankan npm test -- order setelah perubahan

Hasil after yang baik tetap kecil.

// after: src/domain/order.ts
type OrderLine = {
  price: number;
  quantity: number;
};

type OrderInput = {
  items: OrderLine[];
  discount?: number;
};

export function calc(order: OrderInput): number {
  const subtotal = order.items.reduce(
    (sum, item) => sum + item.price * item.quantity,
    0
  );

  return Math.max(subtotal - (order.discount ?? 0), 0);
}

Test yang bisa langsung dicopy:

// src/domain/order.test.ts
import { describe, expect, it } from "vitest";
import { calc } from "./order";

describe("calc", () => {
  it("multiplies price and quantity", () => {
    expect(calc({ items: [{ price: 1200, quantity: 2 }] })).toBe(2400);
  });

  it("applies discount without returning a negative total", () => {
    expect(calc({ items: [{ price: 500, quantity: 1 }], discount: 800 })).toBe(0);
  });
});

Review hanya file yang berubah.

git diff -- src/domain/order.ts src/domain/order.test.ts
npm test -- order
npm run typecheck

Pertanyaan review bukan “apakah terlihat pintar?”, tetapi “apakah input yang sama masih punya makna bisnis yang sama?”. Cek perhitungan, nama export, dan deskripsi test.

Use case 2: Hapus any mulai dari boundary

Mengurangi any itu bagus, tetapi melakukannya di seluruh project sekaligus adalah mistake umum. Mulai dari boundary: API response, form payload, konfigurasi, webhook, atau file import. Di sinilah data yang tidak diketahui masuk ke sistem.

// before: src/lib/user-api.ts
export async function fetchUser(id: string): Promise<any> {
  const response = await fetch(`/api/users/${id}`);
  return response.json();
}

export function getDisplayName(user: any): string {
  return user.profile.displayName || user.name;
}

Beri target sempit dan jelaskan behavior saat data tidak lengkap.

Kurangi penggunaan any di src/lib/user-api.ts.

Syarat:
- Tambahkan type untuk API response
- Jangan ubah URL fetch dan makna return value
- Buat getDisplayName aman saat profile tidak ada
- Tambahkan test untuk behavior nama tampilan saat ini
- Jalankan npm test -- user-api dan npm run typecheck

Diff pertama yang masuk akal:

// after: src/lib/user-api.ts
export type UserResponse = {
  id: string;
  name: string;
  profile?: {
    displayName?: string;
  };
};

export async function fetchUser(id: string): Promise<UserResponse> {
  const response = await fetch(`/api/users/${id}`);
  return response.json() as Promise<UserResponse>;
}

export function getDisplayName(user: UserResponse): string {
  return user.profile?.displayName ?? user.name;
}

Cast ini belum memvalidasi data runtime. Jika proyek butuh keamanan input sungguhan, buat diff kedua dengan zod atau parser lokal yang sudah ada. Jangan campur “hapus any” dan “tambah library validasi” dalam diff pemula yang sama.

// src/lib/user-api.test.ts
import { describe, expect, it } from "vitest";
import { getDisplayName, type UserResponse } from "./user-api";

describe("getDisplayName", () => {
  it("uses profile displayName when present", () => {
    const user: UserResponse = {
      id: "u1",
      name: "Masa",
      profile: { displayName: "Masa I." },
    };

    expect(getDisplayName(user)).toBe("Masa I.");
  });

  it("falls back to name when profile is missing", () => {
    expect(getDisplayName({ id: "u2", name: "Guest" })).toBe("Guest");
  });
});

Saat review, cari shortcut berbahaya: as any, error yang ditelan, string kosong sebagai fallback, atau perubahan behavior field optional. Diff yang lebih type-safe tetap bisa merusak behavior.

Use case 3: Pecah fungsi besar setelah ada test harness

Fungsi service besar menggoda untuk dibersihkan, tetapi sering menyimpan logic penting. Order, billing, permission, notification, dan import job mencampur validasi, kalkulasi, persistence, dan side effect. Minta Claude Code mengekstrak satu bagian pure saja.

// before: src/services/order-service.ts
export async function createOrder(input: CreateOrderInput) {
  if (input.items.length === 0) {
    throw new Error("items required");
  }

  const subtotal = input.items.reduce((sum, item) => sum + item.price * item.quantity, 0);
  const shippingFee = subtotal >= 10000 ? 0 : 800;
  const total = subtotal + shippingFee;

  const order = await db.order.create({
    data: { userId: input.userId, subtotal, shippingFee, total },
  });

  await mailer.sendOrderCreated(order.id);
  return order;
}

Prompt harus menyebutkan yang tidak boleh dilakukan.

Buat createOrder di src/services/order-service.ts menjadi lebih kecil.

Dalam diff ini:
- Extract hanya kalkulasi shipping dan total ke pure function
- Beri nama calculateOrderTotals
- Tambahkan unit test untuk calculateOrderTotals
- Pertahankan urutan write database dan pengiriman email

Jangan lakukan dalam diff ini:
- Mengubah schema database
- Mengubah error message
- Mengubah bentuk API response
- Memindahkan fungsi yang tidak terkait
- Memformat seluruh file

After yang cukup:

// after: src/services/order-service.ts
export function calculateOrderTotals(items: OrderItem[]) {
  const subtotal = items.reduce(
    (sum, item) => sum + item.price * item.quantity,
    0
  );
  const shippingFee = subtotal >= 10000 ? 0 : 800;

  return {
    subtotal,
    shippingFee,
    total: subtotal + shippingFee,
  };
}

Command review:

git diff --stat
git diff -- src/services/order-service.ts
git diff -- src/services/order-service.test.ts
npm test -- order-service

Jika Claude Code juga memformat bagian tidak terkait:

Diff ini terlalu besar.
Kembalikan perubahan yang hanya formatting dan pertahankan hanya extraction calculateOrderTotals plus test.
Jangan ubah external behavior, error text, database write, atau urutan email.

Review dengan git diff, bukan perasaan

Penjelasan Claude Code membantu, tetapi diff adalah sumber kebenaran.

git diff --check
git diff --stat
git diff --name-only
git diff --word-diff -- src/domain/order.ts
AreaYang dicek
BehaviorInput, output, exception, HTTP status, urutan persistence
UkuranPerubahan muat dalam satu review manusia
TestBehavior lama dilindungi test
TypeTidak ada as any, cast berbahaya, atau error diabaikan
Side effectAPI, email, billing, delete, permission tetap berurutan
SummaryRingkasan Claude Code cocok dengan diff nyata

Prompt review:

Review git diff ini.

Cek:
- Apakah perubahan melewati scope refactoring?
- Behavior apa yang belum dilindungi test?
- Apakah ada cast tidak aman atau error yang ditelan?
- File mana yang harus diperiksa manusia dengan hati-hati?

Kembalikan:
- Terlihat aman
- Perlu konfirmasi manusia
- Harus diperbaiki
dengan nama file dan alasan.

Pitfall: failure dan risk yang sering terjadi

Failure pertama adalah prompt terlalu luas.

Buat service layer ini lebih bersih.

Ini bisa mencampur extraction, naming, error design, file move, dan formatting. Lebih aman:

Extract hanya kalkulasi shipping fee dari createOrder ke pure function.
Jangan ubah urutan proses, error message, atau return value.

Risk kedua adalah menerima diff yang terlihat rapi tanpa test. Readability bisa naik sementara edge case berubah: discount, free shipping, permission, retry, atau null. Kesalahan ketiga adalah mencampur formatter dan structural refactoring. Jika Prettier mengubah ratusan baris, perubahan penting tersembunyi. Risk keempat adalah membuka permission command terlalu luas di awal. Mulai dari read, test, typecheck, lint; tambah setelah workflow stabil.

Checklist dan CTA

## Refactoring checklist

- [ ] Perubahan hanya punya satu tujuan
- [ ] Baseline test dijalankan sebelum edit
- [ ] Behavior before/after ekuivalen
- [ ] Test baru atau lama melindungi behavior
- [ ] git diff --stat cukup kecil untuk direview
- [ ] git diff --check lolos
- [ ] Tidak ada any, cast tidak aman, atau error yang ditelan
- [ ] DB, email, billing, delete, permission tetap berurutan

Prompt final:

Jalankan satu diff refactoring yang aman.

Target:
- src/services/order-service.ts
- src/services/order-service.test.ts

Kriteria sukses:
- External behavior tidak berubah
- calculateOrderTotals diekstrak
- Test lama dan baru lolos
- Laporkan git diff --stat dan command yang dijalankan

Dilarang:
- Perubahan DB schema
- Perubahan API response
- Perubahan error message
- Edit file yang tidak terkait

Dalam verifikasi saya, dua kebiasaan paling membantu adalah meminta plan tanpa edit terlebih dahulu dan selalu menutup implementasi dengan ringkasan git diff. Gabungkan workflow ini dengan checklist review Claude Code dan best practice CLAUDE.md agar bisa dipakai tim.

Jika tim ingin model operasional yang aman, training Claude Code bisa membantu menyusun permission, prompt, review, dan desain workflow. Automasi refactoring bernilai ketika menurunkan risiko maintenance, bukan ketika menghasilkan diff besar yang sulit dipercaya.

#Claude Code #refactoring #code quality #automation #TypeScript
Gratis

PDF gratis: cheatsheet Claude Code

Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.

Kami menjaga datamu dan tidak mengirim spam.

Masa

Tentang penulis

Masa

Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.