Liskov Substitution Principle (LSP)
drajatisme
Posted on September 8, 2023
Robert C. Martin menjelaskan:
Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.
Dave Cheney menjelaskan:
The Liskov Substitution Principle encourages you to express the dependencies between your packages in terms of interfaces, not concrete types. By defining small interfaces, we can be more confident that implementations will faithfully satisfy their contract.
Karena pada golang tidak ada konsep inheritance, maka LSP bisa dicapai dengan menggunakan interface.
Agar lebih jelasnya, perhatikan kode yang ada pada contoh OCP sebelumnya:
package main
import (
"fmt"
)
// User adalah tipe data yang mewakili informasi pengguna.
type User struct {
ID int
Username string
Email string
}
type UserRepository interface {
GetUserByUsername(username string) (User, error)
Save() error
}
// UserRepository bertanggung jawab untuk berinteraksi dengan basis data pengguna.
type UserMySQLRepository struct{}
func (r *UserMySQLRepository) GetUserByUsername(username string) (User, error) {
// Logika untuk mengambil pengguna berdasarkan username
return User{}, nil
}
func (r *UserMySQLRepository) Save() error {
// Logika untuk menyimpan ke basis data
return nil
}
type UserOracleRepository struct{}
func (r *UserOracleRepository) GetUserByUsername(username string) (User, error) {
// Logika untuk mengambil pengguna berdasarkan username
return User{}, nil
}
func (r *UserOracleRepository) Save() error {
// Logika untuk menyimpan ke basis data
return nil
}
// UserValidator bertanggung jawab untuk memvalidasi data pengguna.
type UserValidator struct{}
func (uv *UserValidator) Validate() error {
// Logika validasi pengguna seperti validasi email, kata sandi, dsb.
return nil
}
// UserService adalah layanan yang berfungsi sebagai penghubung antara klien dan data pengguna.
type UserService struct {
Repository UserRepository
Validator UserValidator
}
// CreateUser membuat pengguna baru dengan menggunakan Repository dan Validator.
func (us *UserService) CreateUser(user User) error {
// Validasi pengguna menggunakan Validator
if err := us.Validator.Validate(); err != nil {
return err
}
// Simpan pengguna ke basis data menggunakan Repository
if err := us.Repository.Save(); err != nil {
return err
}
return nil
}
// GetUserByID mengambil pengguna berdasarkan ID dari Repository.
func (us *UserService) GetUserByUsername(username string) (User, error) {
return us.Repository.GetUserByUsername(username)
}
func main() {
// Inisialisasi layanan pengguna
userService := UserService{
Repository: &UserOracleRepository{}, // Contoh sederhana, seharusnya menggunakan koneksi basis data nyata.
Validator: UserValidator{}, // Contoh sederhana, seharusnya ada validasi yang lebih lengkap.
}
// Membuat pengguna baru
newUser := User{ID: 1, Username: "john_doe", Email: "john@example.com"}
err := userService.CreateUser(newUser)
if err != nil {
fmt.Println("Error:", err)
return
}
// Mengambil pengguna berdasarkan username
user, err := userService.GetUserByUsername("myUser")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("User:", user)
}
Kode ini sudah menerapkan LSP, karena struct UserOracleRepository
dan UserMySQLRepository
dapat digunakan pada UserService
.
Referensi
Posted on September 8, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.