Mengenal Layered Architecture di Golang untuk Aplikasi yang Mudah Dikembangkan
Panduan memahami Layered Architecture di Golang, struktur folder, pembagian tanggung jawab, dan contoh implementasi sederhana.
Ketika membangun aplikasi menggunakan Golang, salah satu tantangan terbesar adalah menjaga kode tetap rapi seiring bertambahnya fitur. Tanpa struktur yang jelas, kode akan sulit dipelajari, diuji, dan dikembangkan oleh tim.
Salah satu pendekatan yang banyak digunakan adalah Layered Architecture. Pola ini membagi aplikasi ke dalam beberapa lapisan (layer) yang memiliki tanggung jawab berbeda sehingga setiap bagian aplikasi dapat berkembang secara terpisah tanpa saling bergantung secara langsung.
Apa Itu Layered Architecture?
Layered Architecture adalah pola arsitektur perangkat lunak yang memisahkan aplikasi menjadi beberapa lapisan berdasarkan tanggung jawabnya.
Umumnya pada aplikasi Golang, layer yang digunakan terdiri dari:
- Handler / Controller Layer
- Service Layer
- Repository Layer
- Database Layer
Alur sederhananya:
Client Request
↓
Handler
↓
Service
↓
Repository
↓
Database
Berikut ilustrasi sederhana mengenai hubungan antar layer:
Struktur Folder yang Umum Digunakan
Berikut contoh struktur project Layered Architecture pada Golang:
project/
├── cmd/
│ └── main.go
├── internal/
│ ├── handler/
│ │ └── user_handler.go
│ ├── service/
│ │ └── user_service.go
│ ├── repository/
│ │ └── user_repository.go
│ ├── model/
│ │ └── user.go
│ └── database/
│ └── mysql.go
├── go.mod
└── go.sum
Dengan struktur tersebut, setiap folder memiliki tanggung jawab yang jelas dan tidak saling bercampur.
Handler Layer
Handler bertugas menerima request dari client dan mengembalikan response.
Contoh sederhana:
type UserHandler struct {
userService service.UserService
}
func (h *UserHandler) GetUsers(c *gin.Context) {
users, err := h.userService.GetAll()
if err != nil {
c.JSON(500, gin.H{
"message": err.Error(),
})
return
}
c.JSON(200, users)
}
Handler sebaiknya tidak berisi logika bisnis yang kompleks. Fokusnya hanya pada proses HTTP request dan response.
Service Layer
Service merupakan tempat logika bisnis aplikasi dijalankan.
Contoh:
type UserService struct {
repo repository.UserRepository
}
func (s *UserService) GetAll() ([]model.User, error) {
return s.repo.FindAll()
}
Jika terdapat validasi, perhitungan, atau aturan bisnis tertentu, semuanya sebaiknya ditempatkan pada layer ini.
Repository Layer
Repository bertugas berinteraksi langsung dengan database.
Contoh:
type UserRepository struct {
db *sql.DB
}
func (r *UserRepository) FindAll() ([]model.User, error) {
rows, err := r.db.Query(
"SELECT id, name, email FROM users",
)
if err != nil {
return nil, err
}
defer rows.Close()
var users []model.User
for rows.Next() {
var user model.User
err := rows.Scan(
&user.ID,
&user.Name,
&user.Email,
)
if err != nil {
return nil, err
}
users = append(users, user)
}
return users, nil
}
Dengan pola ini, perpindahan database dari MySQL ke PostgreSQL misalnya dapat dilakukan dengan perubahan yang lebih terisolasi.
Dependency Injection pada Layered Architecture
Agar setiap layer tidak membuat dependensinya sendiri, biasanya digunakan teknik Dependency Injection.
Contoh pada main.go:
db := database.Connect()
userRepo := repository.NewUserRepository(db)
userService := service.NewUserService(userRepo)
userHandler := handler.NewUserHandler(userService)
Dengan pendekatan ini, setiap komponen menerima dependensi dari luar sehingga lebih mudah diuji menggunakan mock saat unit testing.
Keuntungan Menggunakan Layered Architecture
Beberapa keuntungan yang diperoleh antara lain:
- Struktur kode lebih terorganisir.
- Tanggung jawab setiap komponen lebih jelas.
- Lebih mudah melakukan unit testing.
- Mempermudah pengembangan fitur baru.
- Cocok untuk pengembangan tim karena alur kerja lebih terstruktur.
- Mengurangi ketergantungan langsung antar komponen.
- Memudahkan penerapan prinsip SOLID.
Kekurangan Layered Architecture
Meskipun populer, Layered Architecture juga memiliki beberapa kekurangan:
- Membutuhkan lebih banyak file dan folder.
- Untuk proyek kecil terasa terlalu kompleks.
- Data sering harus melewati beberapa layer sekaligus.
- Membutuhkan disiplin tim agar setiap layer tetap sesuai tanggung jawabnya.
Karena itu, penting menyesuaikan arsitektur dengan kebutuhan proyek.
Perbedaan Layered Architecture dan Clean Architecture
Banyak developer pemula menganggap keduanya sama, padahal terdapat perbedaan.
| Layered Architecture | Clean Architecture |
|---|---|
| Struktur lebih sederhana | Struktur lebih kompleks |
| Cocok untuk proyek kecil hingga menengah | Cocok untuk proyek besar |
| Dependency biasanya mengarah ke bawah | Dependency mengarah ke domain |
| Implementasi lebih cepat | Lebih fleksibel dan scalable |
Layered Architecture sering menjadi langkah awal yang baik sebelum mempelajari Clean Architecture yang lebih kompleks.
Kapan Sebaiknya Digunakan?
Layered Architecture sangat cocok digunakan pada:
- REST API menggunakan Gin.
- REST API menggunakan Fiber.
- Backend aplikasi web.
- Sistem internal perusahaan.
- Dashboard administrasi.
- Aplikasi skala menengah hingga besar.
Untuk aplikasi yang hanya memiliki beberapa endpoint sederhana, penggunaan banyak layer terkadang tidak memberikan manfaat yang signifikan.
Kesimpulan
Layered Architecture merupakan salah satu pola arsitektur yang paling umum digunakan dalam pengembangan backend Golang. Dengan memisahkan tanggung jawab ke dalam layer seperti Handler, Service, dan Repository, kode menjadi lebih mudah dirawat, diuji, dan dikembangkan dalam jangka panjang.
Pola ini membantu developer menjaga struktur proyek tetap rapi serta mempermudah kolaborasi dalam tim. Meskipun bukan solusi untuk semua kasus, Layered Architecture tetap menjadi fondasi yang kuat untuk membangun aplikasi Golang yang terstruktur dan mudah dipelihara.