DEV Community

drajatisme
drajatisme

Posted on

Liskov Substitution Principle (LSP)

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)
}
Enter fullscreen mode Exit fullscreen mode

Kode ini sudah menerapkan LSP, karena struct UserOracleRepository dan UserMySQLRepository dapat digunakan pada UserService.

Referensi

Top comments (0)