Facade Pattern #

Dalam sistem yang berkembang, kompleksitas sering kali muncul bukan karena satu komponen yang rumit, tetapi karena banyaknya subsistem yang saling berinteraksi. Setiap subsistem mungkin memiliki API sendiri, dependensi sendiri, dan urutan pemanggilan yang tidak sederhana. Facade Pattern hadir untuk menyederhanakan interaksi ini dengan menyediakan satu antarmuka terpadu.

Facade Pattern adalah salah satu Structural Design Pattern yang sangat sering digunakan di dunia nyata, terutama pada aplikasi backend, integrasi library, dan sistem legacy.

Apa itu Facade Pattern? #

Facade Pattern adalah design pattern yang menyediakan antarmuka sederhana (facade) untuk sekumpulan interface yang lebih kompleks di dalam suatu subsistem.

Facade tidak menghilangkan kompleksitas, tetapi menyembunyikannya dari client. Client cukup berinteraksi dengan facade tanpa perlu memahami detail internal subsistem.

Secara sederhana:

Facade = pintu depan yang rapi untuk sistem yang rumit di belakangnya.


Tujuan Pattern #

Tujuan utama penggunaan Facade Pattern adalah:

  1. Menyederhanakan penggunaan subsistem Client tidak perlu tahu urutan pemanggilan atau detail implementasi.

  2. Mengurangi coupling antara client dan subsistem Client bergantung pada facade, bukan langsung ke banyak komponen.

  3. Meningkatkan readability dan maintainability Kode client menjadi lebih bersih dan fokus pada use-case.

  4. Isolasi perubahan Perubahan di subsistem tidak memengaruhi client selama facade tetap stabil.


Kapan Cocok Digunakan? #

Facade Pattern sangat cocok digunakan ketika:

  • Sistem memiliki banyak subsistem dengan API kompleks
  • Client harus memanggil banyak komponen secara berurutan untuk satu use-case
  • Ingin menyediakan API tingkat tinggi (high-level API)
  • Bekerja dengan library pihak ketiga atau legacy system
  • Ingin memisahkan business logic orchestration dari detail teknis

Contoh Kasus Nyata #

  • Service pembayaran (validasi user, cek saldo, debit, logging, notifikasi)
  • Proses order (inventory, pricing, discount, payment, shipping)
  • Wrapper SDK untuk API eksternal

Struktur Pattern #

Komponen utama:

  • Facade Kelas/struct yang menyediakan API sederhana

  • Subsystem Classes Kelas-kelas kompleks yang melakukan pekerjaan sebenarnya

  • Client Menggunakan facade, bukan subsistem langsung

Client → Facade → Subsystems


Contoh Implementasi (Golang) #

Studi Kasus: Proses Checkout #

Checkout membutuhkan beberapa subsistem:

  • UserService
  • InventoryService
  • PaymentService
  • NotificationService

Tanpa facade, client harus mengatur semuanya sendiri.

Subsystem Implementation #

package checkout

import "fmt"

type UserService struct{}

func (u *UserService) ValidateUser(userID string) error {
	fmt.Println("Validating user", userID)
	return nil
}

type InventoryService struct{}

func (i *InventoryService) CheckStock(productID string) error {
	fmt.Println("Checking stock for product", productID)
	return nil
}

type PaymentService struct{}

func (p *PaymentService) Pay(userID string, amount float64) error {
	fmt.Println("Processing payment for", userID)
	return nil
}

type NotificationService struct{}

func (n *NotificationService) SendReceipt(userID string) {
	fmt.Println("Sending receipt to", userID)
}

Facade Implementation #

package checkout

type CheckoutFacade struct {
	userService         *UserService
	inventoryService    *InventoryService
	paymentService      *PaymentService
	notificationService *NotificationService
}

func NewCheckoutFacade() *CheckoutFacade {
	return &CheckoutFacade{
		userService:         &UserService{},
		inventoryService:    &InventoryService{},
		paymentService:      &PaymentService{},
		notificationService: &NotificationService{},
	}
}

func (c *CheckoutFacade) Checkout(userID, productID string, amount float64) error {
	if err := c.userService.ValidateUser(userID); err != nil {
		return err
	}

	if err := c.inventoryService.CheckStock(productID); err != nil {
		return err
	}

	if err := c.paymentService.Pay(userID, amount); err != nil {
		return err
	}

	c.notificationService.SendReceipt(userID)
	return nil
}

Client Code #

func main() {
	checkout := checkout.NewCheckoutFacade()
	err := checkout.Checkout("user-1", "product-1", 150_000)
	if err != nil {
		panic(err)
	}
}

Client sekarang hanya tahu satu method: Checkout().


Facade Pattern vs Pattern Lain #

Facade vs Adapter #

  • Facade: menyederhanakan sistem kompleks
  • Adapter: mengubah interface agar kompatibel

Facade vs Mediator #

  • Facade: satu arah (client → subsistem)
  • Mediator: komunikasi dua arah antar objek

Kelebihan dan Kekurangan #

Kelebihan #

  • API lebih sederhana
  • Client code lebih bersih
  • Mengurangi coupling

Kekurangan #

  • Risiko facade menjadi terlalu besar
  • Bisa menyembunyikan performa atau side-effect

Best Practices #

Facade Bukan God Object #

Facade bertugas mengorkestrasi, bukan mengimplementasikan logic berat.

❌ Salah:

  • Semua business logic dipindahkan ke facade

✅ Benar:

  • Logic tetap di subsistem
  • Facade hanya memanggil dan mengatur alur

Jangan Memaksa Semua Akses Lewat Facade #

Subsystem tetap boleh diakses langsung jika dibutuhkan oleh use-case khusus.

Facade adalah opsional convenience layer, bukan pembatas mutlak.

Gunakan Interface untuk Subsystem #

Agar mudah di-test dan di-mock.

type PaymentService interface {
	Pay(userID string, amount float64) error
}

Ini sangat membantu untuk unit test facade.

Facade Cocok untuk Boundary Layer #

Gunakan facade di:

  • Application service
  • Use-case layer
  • API handler
  • Command / job processor

Hindari menaruh facade di layer domain murni jika tidak perlu.


Penutup #

Facade Pattern adalah solusi elegan untuk menghadapi kompleksitas sistem tanpa harus mengubah struktur internalnya. Dengan menyediakan antarmuka yang sederhana dan fokus pada use-case, facade membantu menjaga kode tetap bersih, terstruktur, dan mudah dirawat.

Dalam Golang, facade sangat natural digunakan karena Go mendorong komposisi dan eksplisit orchestration. Digunakan dengan bijak, Facade Pattern adalah salah satu pattern paling praktis dan bernilai tinggi di dunia software engineering.

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact