Langsung ke konten utama

SOLID - Prinsip Desain Arsitektur Di Dalam Pemrograman Object Oriented (Liskov's Substitution Principal)

Liskov's Subtitution Principal

Pada prinsip ketiga ini, berkaitan erat dengan prinsip kedua yaitu Open / CLose Principal, namun lebih fokus terhadap behaviour antara Parent Class dan Child Class.

Let Î¦(x) be a property provable about objects x of type T. Then Î¦(y) should be true for objects y of type S where S is a subtype of T

 bingung ? oke kira-kira simpelnya gini: 

Object dari Parent Class bisa diganti dengan Object dari Child Class tanpa merusak aplikasi / membuat aplikasi berhenti (error)

Jadi suatu object dari Parent Class atau turunannya, harus bisa dengan mudah diganti dengan Object / Instance dari Class Turunan tanpa mengganggu jalannya program. Kita bisa menerapkan konsep ini dengan menggunakan abstraksi / interface. Kalau masih bingung, mari kita belajar langsung dengan contoh.

Contoh Kasus

Bayangkan kita punya 1 soket lampu di teras rumah yang mati dan akan kita ganti dengan yang baru. Lampu yang kita gunakan sebelumnya adalah bohlam lampu pijar yang fungsinya adalah untuk penerangan. Karena gunanya untuk penerangan, mungkin bisa saja kita ganti dengan lampu warna warni namun tidak sesuai dengan kegunaannya. Akan lebih tepat jika kita ganti dengan lampu LED yang memang kegunaannya untuk penerangan. Dari analogi ini, kita akan membuat Class Lampu yang akan mempunyai beberapa Class turunan yaitu Class LampuPijar, LampuLED, dan LampuDisko. Kemudian saya juga punya Class SocketLampuTeras yang digunakan untuk menyalakan lampu.
<?php

namespace Kematjaya\PhpLsp\Lampu;

/**
 * Description of AbstractLampu
 *
 * @author programmer
 */
abstract class AbstractLampu 
{
    abstract public function nyalakan();
}
<?php

namespace Kematjaya\PhpLsp\Lampu;

/**
 * Description of LampuPijar
 *
 * @author programmer
 */
class LampuPijar extends AbstractLampu 
{
    public function nyalakan() 
    {
        return "Nyala Terang";
    }

}
<?php

namespace Kematjaya\PhpLsp\Lampu;

/**
 * Description of LampuLED
 *
 * @author programmer
 */
class LampuLED extends AbstractLampu 
{
    public function nyalakan() 
    {
        return "Nyala Terang";
    }

}
<?php

namespace Kematjaya\PhpLsp\Lampu;

/**
 * Description of LampuDisko
 *
 * @author programmer
 */
class LampuDisko extends AbstractLampu 
{
    
    public function nyalakan() 
    {
        return "Nyala Kelap Kelip";
    }

}
<?php

namespace Kematjaya\PhpLsp;

use Kematjaya\PhpLsp\Lampu\AbstractLampu;

/**
 * Description of SocketLampuTeras
 *
 * @author programmer
 */
class SocketLampuTeras 
{
    private AbstractLampu $lampu;
    
    public function __construct(AbstractLampu $lampu) 
    {
        $this->lampu = $lampu;
    }
    
    public function gantiLampu(AbstractLampu $lampu):self
    {
        $this->lampu = $lampu;
        
        return $this;
    }
    
    public function on():string 
    {
        return $this->lampu->nyalakan();
    }
}
dari contoh diatas, bisa saja lampuPijar kita ganti dengan LampuDisko. Namun setelah dilakukan testing maka hasilnya seperti berikut:
<?php

namespace Kematjaya\PhpLsp\Tests;

use Kematjaya\PhpLsp\Lampu\LampuDisko;
use Kematjaya\PhpLsp\Lampu\LampuLED;
use Kematjaya\PhpLsp\Lampu\LampuPijar;
use Kematjaya\PhpLsp\SocketLampuTeras;
use PHPUnit\Framework\TestCase;

/**
 * Description of LampuTamanTest
 *
 * @author programmer
 */
class LampuTamanTest extends TestCase 
{
    public function testNyalakanLampu()
    {
        $pijar = new LampuPijar();
        $socket = new SocketLampuTeras($pijar);
        $this->assertEquals("Nyala Terang", $socket->on());
        
        $socket->gantiLampu(new LampuLED());
        $this->assertEquals("Nyala Terang", $socket->on());
        
        $socket->gantiLampu(new LampuDisko());
        $this->assertEquals("Nyala Terang", $socket->on());
    }
}

dari testing diatas, didapatkan hasil yang kurang sesuai karena peruntukannya untuk penerangan. Ini bisa anggap bug karena hasil yang kurang sesuai dengan yang diharapkan. Oleh karena itu kita perlu buat beberapa modifikasi pada kode Class SocketLampuTeras nya dengan menambahkan Interface / Abstract Class seperti kode berikut.
<?php

namespace Kematjaya\PhpLsp\Lampu;

/**
 * Description of AbstractLampuPenerangan
 *
 * @author programmer
 */
abstract class AbstractLampuPenerangan extends AbstractLampu 
{
    public function nyalakan()
    {
        return "Nyala Terang";
    }
}
<?php

namespace Kematjaya\PhpLsp\Lampu;

/**
 * Description of AbstractlampuHiburan
 *
 * @author programmer
 */
abstract class AbstractlampuHiburan extends AbstractLampu 
{
    public function nyalakan() 
    {
        return "Nyala Kelap Kelip";
    }
}
Kemudian kita ubah Class LampuDisko menjadi turunan dari Class AbstractLampuHiburan
<?php

namespace Kematjaya\PhpLsp\Lampu;

/**
 * Description of LampuDisko
 *
 * @author programmer
 */
class LampuDisko extends AbstractlampuHiburan 
{

}
dan Class LampuPijar dan LampuLED menjadi turunan Class AbstractLampuPenerangan
<?php

namespace Kematjaya\PhpLsp\Lampu;

/**
 * Description of LampuLED
 *
 * @author programmer
 */
class LampuLED extends AbstractLampuPenerangan 
{

}

class LampuPijar extends AbstractLampuPenerangan
{
    
}

Kemudian kita ubah Class SocketLampuTeras
<?php

namespace Kematjaya\PhpLsp;

use Kematjaya\PhpLsp\Lampu\AbstractLampuPenerangan;


/**
 * Description of SocketLampuTeras
 *
 * @author programmer
 */
class SocketLampuTeras 
{
    private AbstractLampuPenerangan $lampu;
    
    public function __construct(AbstractLampuPenerangan $lampu) 
    {
        $this->lampu = $lampu;
    }
    
    public function gantiLampu(AbstractLampuPenerangan $lampu):self
    {
        $this->lampu = $lampu;
        
        return $this;
    }
    
    public function on():string 
    {
        return $this->lampu->nyalakan();
    }
}

karena di Class SocketLampuTeras kita spesifik menggunakan class AbstractLampuPenerangan, maka class LampuDisko tidak bisa kita masukkan sebagai lampu di socket ini, jadi testing kita menjadi seperti ini.
<?php

namespace Kematjaya\PhpLsp\Tests;

use Kematjaya\PhpLsp\Lampu\LampuDisko;
use Kematjaya\PhpLsp\Lampu\LampuLED;
use Kematjaya\PhpLsp\Lampu\LampuPijar;
use Kematjaya\PhpLsp\SocketLampuTeras;
use PHPUnit\Framework\TestCase;

/**
 * Description of LampuTamanTest
 *
 * @author programmer
 */
class LampuTamanTest extends TestCase 
{
    public function testNyalakanLampu()
    {
        $pijar = new LampuPijar();
        $socket = new SocketLampuTeras($pijar);
        $this->assertEquals("Nyala Terang", $socket->on());
        
        $socket->gantiLampu(new LampuLED());
        $this->assertEquals("Nyala Terang", $socket->on());
    }
}
setelah dilakukan beberapa modifikasi, sekarang kita jalankan lagi unit test nya, maka hasilnya seperti berikut:

Kesimpulan

LSP bertujuan untuk menghindari error / bug ketika suatu object diganti dengan object yang lain. Karena itu LSP mengharuskan agar suatu object mempunyai perilaku yang sama dengan object yang digantikan. Untuk mencapai tujuan ini, kita bisa menggunakan abstraksi / interface untuk memastikan object mempunyai perilaku yang sama sehingga tidak mengganggu jalannya program.

Kira-kira cukup sekian ya tulisan ini. Jika ada yang perlu diperbaiki, bisa tulis di komentar

Komentar

Postingan populer dari blog ini

Contoh Perhitungan Algoritma Perceptron

      Melanjutkan tulisan saya sebelumnya tentang algoritma perceptron,kali ini saya akan menulis tentang conto perhitungan manual algoritma perceptron. Untuk contoh kasusnya saya menggunakan data logika AND. Cekidot.... Algoritma      Data yang kita gunakan sebagai contoh adalah data logika AND sebagai berikut: x1 x2 target 0 0 0 0 1 0 1 0 0 1 1 1       tentukan bobot awal secara acak, saya pakai contoh w1 = 0,w2 =0, learning rate = 1, bias = 0,maksimal epoh = 10. Disini saya memakai fungsi aktivasi undak biner. Epoh ke 1 Data ke satu x = {0,0}, bobot w = {0,0},b=0,target = 0 y_in = (x1*w1)+(x2*w2)+b = (0*0)+(0*0)+0 = 0 y = sign(0) = 1 karena y != target maka hitung error dan update bobot  error = target - y = 0 - 1 = -1 w1_baru = w1_lama +(learning_rate*error*x1)                = 0 + (1*(-1)*0) = 0 w2_baru = w2_lama +(learning_rate*error*x2)                = 0+(1*(-1)*0) = 0

Contoh Perhitungan Algoritma Learning Vector Quantization

Melanjutkan tulisan saya tentang algoritma Learning Vector Quantization yang lalu, kali ini saya akan melanjutkan dengan contoh perhitungan manual. Berikut ini contoh data yang akan kita hitung. No X1 X2 X3 X4 target 1 0 1 1 0 0 2 0 0 1 1 1 3 1 1 1 1 0 4 1 0 0 1 1 pada contoh di atas, saya menggunakan 4 data sebagai data training beserta target yang bertujuan untuk mendapatkan bobot yang akan digunakan pada proses klasifikasi. Bobot awal adalah { 1, 1, 1, 0} dan { 1, 0, 1, 1} dengan learning rate 0,05 dengan fungsi pembelajaran = 0,1. Pelatihan Iterasi ke 1 1. Data ke 1 { 0, 1, 1, 0} dengan target 0, bobot = {{ 1, 1, 1, 0},{ 1, 0, 1, 1}}      - menghitung bobot untuk masing masing output :          kelas 0 = sqrt(((0-1)^2)+((1-1)^2)+((1-1)^2)+((0-0)^2)) = 1         kelas 1 = sqrt(((0-1)^2)+((1-0)^2)+((1-

Pemrograman Berorientasi Object - Overloading dan Overriding

       Function atau method overloading dan override adalah fitur yang sangat mendasar dan berguna dari bahasa OOP manapun. Dalam tutorial ini kita akan membahas implementasi metode overloading dan override di php. Di sini pertama kita akan membahas dasar-dasar overloading dan override. Setelah eksplorasi dasar kita akan menerapkan overloading dan override di php. Sebelum melangkah lebih jauh, saya mengasumsikan bahwa Anda memiliki pengetahuan dasar tentang class dan pewarisan di php. Anda juga memiliki pemahaman tentang magic method di php. Magic method karena overloading di php bisa di implmentasikan dengan menggunakan magic method. Overriding        Arti dasar dari overriding di OOP sama dengan arti kata sebenarnya. Dalam arti kata sebenarnya dari overriding adalah menggantikan perilaku orang tua yang sama pada anak. Ini sama dengan override method di OOP. Dalam arti OOP, override adalah mengganti method class induk di class anak. Atau dengan method kata kunci sederhana yang me