For the complete documentation index, see llms.txt. This page is also available as Markdown.

Clean architecture

Setelah kita memiliki API yang terhubung ke database, sekarang saatnya memikirkan struktur kode. Tanpa arsitektur yang jelas, kode akan sulit di-maintain, sulit di-test, dan sulit dikembangkan oleh tim.

Clean Architecture (diperkenalkan oleh Robert C. Martin) adalah pendekatan yang memisahkan kode ke dalam lapisan-lapisan (layer) berdasarkan tanggung jawabnya.

πŸ“‚ Kode Lengkap Bab Ini: Seluruh kode yang dibahas di bab ini tersedia di GitHub:

πŸ”— github.com/jacky-htg/workshop/tree/main/05-clean-architecture

5.1 Tiga Layer Utama

PRESENTATION LAYER (HTTP Handler, Routing, Request/Response DTO) :

  • Menerima input dari user

  • Memformat output ke user

  • TIDAK boleh mengandung logika bisnis

DOMAIN LAYER (Service / UseCase) :

  • Logika bisnis aplikasi

  • Aturan bisnis & validasi

  • Tidak peduli dari mana data berasal

DATA LAYER (Repository, Model) :

  • Akses database / API eksternal

  • Mapping data dari storage ke struct

  • Hanya operasi CRUD sederhana

Prinsip utama: Ketergantungan hanya mengarah ke dalam (inward). Layer dalam (Domain) tidak boleh tahu tentang layer luar (Presentation/Data).

5.2 Struktur Direktori

Berikut struktur direktori yang akan kita bangun:

Catatan tentang folder internal dan pkg:

  • internal/ – Kode yang hanya boleh digunakan oleh proyek ini. Go compiler akan melarang import dari luar.

  • pkg/ – Kode yang boleh diimport oleh proyek lain (library publik).

5.3 Memisahkan Entry Points (Server vs CLI)

Sebelumnya, kita mencampur logika server HTTP dan migration dalam satu main.go. Sekarang kita pisahkan:

cmd/server/main.go – Entry Point untuk API Server

Menjalankan HTTP server, graceful shutdown, dan injeksi dependency.

cmd/cli/main.go – Entry Point untuk Command Line

Menjalankan perintah administrasi seperti migration.

5.4 Dependency Injection dengan Interface

Dependency Injection (DI) memastikan setiap object hanya dibuat sekali (singleton) dan disuntikkan ke komponen yang membutuhkan. Kita sudah mempraktekkannya sebelumnya dengan NewUsers(db).

Sekarang kita tingkatkan dengan interface. Interface mendefinisikan kontrak behavior β€” apa yang bisa dilakukan, bukan bagaimana cara melakukannya.

Konvensi penamaan interface:

  • Jika berisi satu behavior β†’ akhiri dengan -er (contoh: Reader, Writer)

  • Jika berisi banyak behavior β†’ PascalCase (contoh: UserRepository)

Mengapa interface penting untuk DI?

  • Memungkinkan kita mengganti implementasi (misal: dari PostgreSQL ke MongoDB) tanpa mengubah kode lain

  • Memudahkan unit testing dengan mock object

5.5 Implementasi Layer per Layer

Layer Data – Model (internal/model/user.go)

Model adalah representasi struktur data dari database. Tidak mengandung tag JSON karena ini murni untuk layer data.

Layer Data – Repository (internal/repository/user_repository.go)

Repository bertanggung jawab untuk operasi database. Hanya berisi query sederhana β€” tanpa logika bisnis.

  • Berikut isi dari file pkg/database/postgre.go

Layer Domain – Service (internal/service/users.go)

Service berisi logika bisnis. Di contoh sederhana ini, service hanya meneruskan ke repository. Namun nanti di sinilah validasi, perhitungan, dan aturan bisnis lainnya berada.

Layer Presentation – DTO (internal/dto/user_response.go)

DTO (Data Transfer Object) adalah representasi data yang dikirim ke client. Tidak semua field dari model harus diekspos β€” misalnya, field Password tidak boleh dikirim ke response.

Perhatikan: Field Password tidak ada di UserResponse β€” ini sengaja agar password tidak bocor ke client.

Layer Presentation – Handler (internal/handler/user_handler.go)

Handler menerima HTTP request, memanggil service, lalu mengubah hasil menjadi JSON response.

Library Pendukung – Database (pkg/database/postgre.go)

Kode ini bisa dijadikan library karena tidak spesifik untuk proyek ini.

Entry Point Server (cmd/server/main.go)

Ini adalah tempat perakitan semua komponen (dependency injection). Urutan inisialisasi: database β†’ repository β†’ service β†’ handler.

5.6 Menjalankan Aplikasi

Ringkasan Bab 5

Di bab ini kita telah belajar:

Komponen
Folder
Tanggung Jawab

Model

internal/model

Struktur data dari database

Repository

internal/repository

Operasi database (CRUD)

Service

internal/service

Logika bisnis

DTO

internal/dto

Format response ke client

Handler

internal/handler

Menerima request, mengembalikan response

Library

pkg

Kode yang bisa digunakan ulang

Entry point

cmd

Server HTTP dan CLI tools

Manfaat Clean Architecture yang sudah kita rasakan:

  • βœ… Pemisahan tanggung jawab yang jelas

  • βœ… Model data tidak terikat dengan format JSON

  • βœ… Password tidak bocor ke response (karena dipisah di DTO)

  • βœ… Repository bisa diganti tanpa mengubah service/handler

  • βœ… CLI dan server berbagi kode yang sama

Yang akan datang:

  • ❌ Belum ada konfigurasi (database URL masih hardcoded)

  • ❌ Belum ada error handling yang terstruktur

  • ❌ Belum ada validasi input

Pada bab berikutnya, kita akan membahas Configuration β€” bagaimana mengelola konfigurasi aplikasi (database URL, port, timeout) tanpa hardcode.

Last updated