Belajar Quarkus - Architecture & Design Patterns
Episode 18 of 24

Belajar Quarkus - Architecture & Design Patterns

Episode ini membahas arsitektur aplikasi Quarkus: modular architecture dengan feature-based organization, domain-driven design dan hexagonal architecture, event-driven architecture dengan reactive messaging, serta CQRS, event sourcing, dan publish/subscribe patterns.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Semakin besar aplikasi, semakin besar pula biaya salah struktur. Kode yang tidak terorganisir menjadi sulit diubah, sulit dites, dan sulit dipahami tim baru. Arsitektur yang baik bukan kemewahan — ia investasi untuk kelangsungan proyek.

Episode 18 membahas arsitektur dan design patterns untuk aplikasi Quarkus: modular architecture dengan feature-based organization, domain-driven design dan hexagonal architecture, event-driven architecture dengan reactive messaging, serta CQRS, event sourcing, dan publish/subscribe patterns.

Modular Architecture dengan Feature-Based Organization

Struktur Berbasis Fitur

Daripada mengelompokkan file berdasarkan tipe (semua controller di satu folder, semua service di folder lain), kelompokkan berdasarkan fitur. Ini membuat setiap fitur mandiri dan mudah diubah.

Struktur berbasis fitur
src/main/java/com/example/
├── order/
│   ├── Order.java
│   ├── OrderRepository.java
│   ├── OrderService.java
│   └── OrderResource.java
├── customer/
│   ├── Customer.java
│   ├── CustomerRepository.java
│   └── CustomerResource.java
└── common/
    ├── ErrorResponse.java
    └── ValidationExceptionMapper.java

Setiap fitur berisi entity, repository, service, dan resource-nya dalam satu package. Folder common menampung hal yang benar-benar lintas fitur. Jalankan ./mvnw quarkus:dev untuk melihat Dev UI yang mencantumkan seluruh bean per package.

Keuntungan Modular

Perubahan pada satu fitur tidak mengganggu fitur lain. Tim bisa bekerja paralel di fitur berbeda dengan konflik minimal. Quarkus memproses setiap package secara seragam, jadi pemisahan ini tidak menambah overhead.

Domain-Driven Design dan Hexagonal Architecture

DDD di Quarkus

Domain-Driven Design (DDD) menempatkan model domain sebagai pusat. Konsep penting: bounded context, aggregate, entity, dan value object. Repository dan service dipisahkan dari transport layer.

JavaEntity domain dan repository
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
 
@Entity
@Table(name = "customers")
public class Customer extends PanacheEntity {
    public String nama;
    public String email;
 
    public void ubahEmail(String emailBaru) {
        this.email = emailBaru;
    }
}

Hexagonal Architecture

Hexagonal (ports and adapters) memisahkan inti aplikasi dari dunia luar. Port adalah interface yang didefinisikan domain; adapter adalah implementasi teknis (REST, database, messaging). Quarkus mempermudah pola ini dengan interface CDI:

JavaPort dan adapter
public interface CustomerPort {
    Customer simpan(Customer customer);
}
 
@ApplicationScoped
public class CustomerRepositoryAdapter implements CustomerPort {
    @Override
    public Customer simpan(Customer customer) {
        return customer.persistAndReturnSelf();
    }
}

Domain memanggil CustomerPort, tidak peduli apakah implementasinya Hibernate, database lain, atau mock. Mengganti implementasi tinggal mengganti adapter — kode domain tidak berubah.

Event-Driven Architecture dengan Quarkus Reactive Messaging

Decoupling Lewat Event

Event-driven architecture memisahkan producer dari consumer. Producer hanya mempublikasikan event; consumer memutuskan apa yang dilakukan. Di Quarkus, ini diwujudkan dengan Reactive Messaging (episode 15).

JavaPublikasikan event order
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.eclipse.microprofile.reactive.messaging.Channel;
import org.eclipse.microprofile.reactive.messaging.Emitter;
 
@ApplicationScoped
public class OrderEventPublisher {
 
    @Inject
    @Channel("order-created")
    Emitter<OrderCreated> emitter;
 
    public void terbitkan(OrderCreated event) {
        emitter.send(event);
    }
}

Setelah order dibuat, service memanggil terbitkan(...). Consumer (misal layanan notifikasi) mendengarkan order-created dan mengirim email — tanpa coupling langsung.

Reactive Messaging untuk Skala

Konfigurasi connector membuat event berjalan di Kafka:

Channel event di Kafka
mp.messaging.outgoing.order-created.connector=smallrye-kafka
mp.messaging.outgoing.order-created.topic=order-created

Event-driven membuat aplikasi lebih resilient: jika consumer down, event tetap antri di broker dan diproses saat consumer kembali.

CQRS, Event Sourcing, dan Publish/Subscribe Patterns

CQRS

CQRS (Command Query Responsibility Segregation) memisahkan model tulis dari model baca. Tulis memakai command dan database transaksional; baca memakai query teroptimasi:

JavaCommand dan query terpisah
@ApplicationScoped
public class OrderCommandService {
    @Transactional
    public void buatOrder(BuatOrderCommand cmd) { ... }
}
 
@ApplicationScoped
public class OrderQueryService {
    public List<OrderView> cariOrder(String keyword) { ... }
}

CQRS memberi fleksibilitas: model baca bisa memakai view, cache, atau database khusus baca tanpa mempengaruhi integritas tulis.

Event Sourcing

Event sourcing menyimpan seluruh perubahan state sebagai event, bukan hanya state terakhir. State sekarang dihitung dengan replaying event. Cocok untuk domain yang perlu audit trail lengkap, seperti keuangan.

Publish/Subscribe

Publish/subscribe memungkinkan satu event dikonsumsi banyak subscriber. Di Reactive Messaging, gunakan group dan topik berbeda:

Subscriber terpisah per concern
mp.messaging.incoming.order-events.connector=smallrye-kafka
mp.messaging.incoming.order-events.topic=orders
mp.messaging.incoming.order-events.group.id=notifikasi-group

Setiap service memakai group id sendiri, sehingga satu event orders bisa memicu notifikasi, audit, dan analytics secara independen.

Penutup

Episode 18 membekali kalian cetak biru arsitektur: feature-based organization untuk modularitas, DDD dan hexagonal untuk memisahkan domain dari teknologi, event-driven architecture dengan reactive messaging untuk decoupling, serta CQRS, event sourcing, dan publish/subscribe untuk skenario lanjutan.

Inti yang harus dibawa pulang:

  • Struktur berbasis fitur membuat setiap fitur mandiri.
  • DDD menempatkan model domain sebagai pusat aplikasi.
  • Hexagonal architecture memisahkan inti dari adapter teknis.
  • Event-driven memecah coupling producer dan consumer.
  • Reactive Messaging menghubungkan service lewat broker pesan.
  • CQRS memisahkan model tulis dan model baca.
  • Publish/subscribe memungkinkan satu event dikonsumsi banyak service.

Di episode 19 selanjutnya kita akan membahas tooling modern dan build automation — Quarkus CLI, Maven plugin, dan Gradle plugin, Dev Services untuk database dan observability, live coding dan Dev UI, serta reproducible artifacts dan native image pipeline.