Utils vs Helper vs Adapter vs Constant — Memahami Perannya dalam Struktur Proyek

Dalam proyek JavaScript atau TypeScript berskala menengah hingga besar, kita sering menemukan folder seperti utils/, helpers/, adapters/, dan constants/.
Sekilas tampak mirip — sama-sama berisi kode yang bisa dipakai ulang — tapi sebenarnya mereka punya tanggung jawab dan level abstraksi yang berbeda.

Mengetahui batasan fungsi tiap folder membuat arsitektur proyek jauh lebih teratur dan scalable.


🧩 1. Utils — Kumpulan Fungsi atau Kelas Primitif

Utils berisi fungsi teknis atau kelas primitif (primitive class) yang tidak tahu apa-apa tentang domain bisnis maupun framework.
Tujuannya: menyediakan pure logic — logika murni yang bisa dipakai di mana saja.

📦 Contoh

// utils/date.js
export function formatDate(date) {
  return new Date(date).toISOString().split('T')[0];
}

// utils/uuid.js
export class UUID {
  static generate() {
    return crypto.randomUUID();
  }
}

Fungsi dan kelas di utils tidak punya state bisnis, tidak tahu konsep seperti user atau order, dan bisa dengan mudah diuji tanpa dependency.

Ciri khas:

  • Hanya berisi pure function atau primitive class.

  • Tidak tergantung domain, database, atau framework.

  • Bisa digunakan di mana pun dalam sistem.


🧰 2. Helper — Pembantu Logika Domain

Helper digunakan untuk mendukung logika domain tertentu.
Berbeda dengan utils, helper tahu konteks bisnis yang sedang dikerjakan (misal user, order, atau blog).

📦 Contoh

// modules/user/userHelper.js
export function formatUserName(name) {
  return name.trim().toLowerCase();
}

Fungsi ini hanya masuk akal di konteks user domain — tidak relevan untuk modul lain.

Ciri khas:

  • Spesifik untuk satu domain atau modul.

  • Dipanggil dari service atau controller domain.

  • Membantu menjaga kode domain tetap bersih dan fokus.


🔌 3. Adapter — Jembatan Dunia Internal dan Eksternal

Adapter berfungsi sebagai lapisan penghubung antara kode internal dan sistem eksternal (API, library, database, atau layanan pihak ketiga).
Dengan adanya adapter, aplikasi tidak bergantung langsung pada implementasi eksternal.

📦 Contoh

// adapters/httpAdapter.js
import axios from "axios";

export const httpAdapter = {
  get: (url, config) => axios.get(url, config),
  post: (url, data, config) => axios.post(url, data, config),
};

Jika suatu hari kamu mengganti axios dengan fetch, cukup ubah httpAdapter tanpa perlu menyentuh service layer.

Ciri khas:

  • Abstraksi dari dependency eksternal.

  • Menjaga loose coupling antar layer.

  • Sering digunakan di service layer atau repository.


🧱 4. Constant — Nilai Tetap Global

Constant berisi nilai tetap atau konfigurasi global yang digunakan di seluruh aplikasi.
Biasanya berupa string, angka, environment key, atau enumerasi status.

📦 Contoh

// constants/appConstants.js
export const APP_NAME = "Nanangwiz";
export const DEFAULT_LANGUAGE = "id";
export const STATUS = {
  ACTIVE: "active",
  INACTIVE: "inactive",
};

Ciri khas:

  • Tidak mengandung logika.

  • Menyimpan nilai yang konsisten di seluruh aplikasi.

  • Digunakan lintas modul untuk menghindari magic string atau duplikasi nilai.


🗂️ Contoh Struktur Folder

src/
 ├── modules/
 │    ├── user/
 │    │     ├── userService.js
 │    │     ├── userHelper.js        ← domain helper
 │    │     └── userController.js
 │    └── order/
 │          └── orderHelper.js
 ├── utils/
 │    ├── date.js                    ← reusable primitive util
 │    └── uuid.js                    ← primitive class
 ├── adapters/
 │    ├── httpAdapter.js             ← external interface
 │    └── emailAdapter.js
 ├── constants/
 │    └── appConstants.js            ← global constants

🔍 Perbandingan Cepat

Aspek

Utils

Helper

Adapter

Constant

Fungsi utama

Logika teknis murni / primitive class

Mendukung logika domain

Menyambungkan sistem internal ↔ eksternal

Menyimpan nilai tetap

Tahu konteks bisnis?

❌ Tidak

✅ Ya

⚠️ Tahu dua sisi

❌ Tidak

Contoh isi

formatDate(), UUID.generate()

formatUserName()

httpAdapter.post()

APP_NAME, STATUS

Ketergantungan eksternal

Tidak

Kadang

Ya

Tidak

Tempat penggunaan

Global

Domain / Service

Infrastruktur

Global


🧠 Inti Konsep

Dengan membedakan folder seperti ini, kamu mempraktikkan prinsip Separation of Concerns (SoC) dan Single Responsibility Principle (SRP).
Hasilnya:

  • Struktur proyek jelas.

  • Kode lebih mudah diuji dan di-refactor.

  • Dependency eksternal bisa diganti tanpa mengubah logika bisnis.

Hey there 👋

Ready to help you explore?