Sunday, December 7, 2008

Object Cloning di PHP 5

Beberapa waktu lalu sempat ada yang bertanya tentang apa efektifnya menggunakan object cloning di PHP 5. Untuk mengetahui efektifitasnya, maka mungkin ada baiknya untuk mengetahui kenapa PHP 5 support object cloning.

Jawaban gue atas thread ini, gue masukin ke blog gue sebagai referensi gue. Dan gue harap juga bisa membantu yang lain kalau sedang belajar tentang object cloning di PHP 5. Apabila ada yang perlu di koreksi, ditambahkan atau dikritik, gue terima dengan senang hati.

Pada dasarnya informasi tentang object cloning bisa dibaca di dokumentasi PHP 5. Untuk mengetahui kenapa ada clone object, perlu kita ketahui, bahwa di php 5 sekarang object itu sudah gak pass by value, tapi pass by reference.

Apa artinya itu? Mungkin bisa gue jelaskan seperti ini. Misalnya kita bekerja di sebuah gudang Laptop. Apabila kita menyimpan sebuah laptop, maka kita dapat secarik kertas kecil yang berisi catatan laptop tersebut ada di bagian mana di gudang. Misalnya Blok 5, Rak 3, Kotak nomer 8. Catatan ini kita bisa istilahkan sebagai "referensi" kita pada obyek laptop tersebut.

Apabila kita ingin memberikan obyek tersebut kepada orang lain (variabel lain). Maka kita sebenarnya membuat fotokopi dari catatan kita, dan memberikannya kepada orang tersebut. Disini kita lihat, kita hanya mengkopi "referensi" kita. Obyeknya tetap mengacu pada laptop yang sama. Artinya apabila orang lain melakukan perubahan pada laptop tersebut, maka sewaktu kita melihat kembali laptop tersebut, kondisinya sudah berubah.

Object Cloning dalam contoh ini berarti. Kita membuat satu cloning dari laptop tersebut. Bentuk dan kondisinya sama persis. Akan tetapi, karena Kotak nomer 8 pada Rak 3 di Blok 5 sudah diisi sama laptop pertama tadi, maka laptop cloningan ini harus ditaruh di kotak yang lain. Misalnya saja Kotak nomer 2 pada Rak 4 di Blok 5. Setelah itu kita membuat catatan kecil tentang alamat laptop tersebut, dan memberikannya pada teman kita. Dengan ini apabila teman kita melakukan perubahan pada laptop tersebut, dia tidak merubah laptop (obyek) kita, tapi laptop kloningan.

Sekarang mari kita coba mengggunakan contoh code.
<?php
class Account {
    public $balance;

    function __construct($balance) {
        $this->balance = $balance;
    }
}

class Person {
    private $name;
    private $age;
    private $id;
    public $account;

    function __construct($name,$age, Account $account) {
        $this->name = $name;
        $this->age = $age;
        $this->account = $account;
    }

    function setId($id) {
        $this->id = $id;
    }

    function getId() {
        return $this->id;
    }

    $account = new Account(0);
    $person = new Person('Oka', 21, $account);
    $person->setId(2);
    $person2 = $person;
    $person2->setId(4);
    echo $person->getId().' '.$person2->getId();
?>

Di PHP 4 hasil dari echo tersebut adalah "2 4"; Akan tetapi di PHP 5 hasil dari echo tersebut adalah "4 4"; ini disebabkan di PHP 5 pada statement $person2 = $person object Person pada $person di pass by reference ke $person2, dalam arti di dalam variable $person2 isinya bukan copy (clone) dari object $person, tapi isinya hanyalah sebuah pointer yang menunjuk ke memory, dimana object $person di simpan.

Oleh karena itu setiap perubahan yang dilakukan di object $person2 akan ikut mempengaruhi object $person. Kenapa dibuat seperti ini di php5? nampaknya php5 berusaha untuk menyamakan behaviour syntax nya pada bahasa2 berparadigma OOP lainnya. CMIIW. supaya orang yang biasa kerja di java, .net atau sejenisnya tidak kaget waktu kerja ber OOP pakai PHP dan sudah biasa dengan asumsi bahwa statement "=" untuk object itu, pasti parse by reference.

Tambahan info. Dalam bahasa pemrogramman berorientasi obyek. Biasanya orang mengenal tipe data "primitiv" dan tipe data "obyek". Tipe data primitiv seperti integer itu selalu pass by value, sedangkan tipe data obyek itu pass by reference. Oleh karena ini, apabila kita di PHP5 ingin memiliki copy utuh dari sebuah object, dimana apabila kita merubah state dari object kopian tersebut tidak mempengaruhi object aslinya, kita diberikan solusi clone.

Mari kita coba merubah code gue diatas dengan clone:
<?php
$account = new Account(0);

$person = new Person('Oka', 21, $account);

$person->setId(2);

$person2 = clone $person;

$person2->setId(4);

echo $person->getId().' '.$person2->getId();
?>

Dengan ini di PHP 5 hasil echonya bisa sama dengan PHP 4 yaitu "2 4". Di thread milist ada yang bertanya, kenapa gak di instance ulang saja seperti ini?
<?php
$person = new Person("Oka", 21, new Account(200));
$person2 = new Person("Oka", 21, new Account(200));
$person3 = new Person("Oka", 21, new Account(200));
?>

Mari kita lihat keefektivan dari clone. Dengan clone kita mendapat copy yang sama persis dari object yang di clone. sedangkan contoh pada contoh diatas, untuk membuat 3 object yang statenya sama, kita harus memasukkan kembali nilai dari parameter tersebut.

Kasusnya mungkin bisa seperti ini. Bayangkan kalau object $person yang kita bikin itu mau digunakan di sebuah class yang bukan tanggung jawab kita. Misalnya (lagi2) kolega kerja kita.

Bekerja Object Oriented yang baik adalah dimana kolega kerja kita tidak perlu tahu menahu seluk beluk yang terjadi di dalam object yang kita bikin (loose coupled). Bisa jadi misalnya, ini misal ya, bahwa state dalam object tersebut seperti nama, umur dan account balancenya didapat dari $_POST (informasi yang diberikan user lewat user interface). Dan karena satu dan lain hal, kolega kita tidak bisa membaca atau tidak tahu menahu soal $_POST. Yang dia tahu hanya object yang di dapat dari kita. Satu-satunya state yang bisa dia ganti misalnya adalah Id nya dengan menggunakan public method setId().

Disini dia gak punya lagi kesempatan untuk bikin instance baru dari class Person yang statenya sama persis sama object $person yang kita berikan. Dia kan gak tahu bahwa waktu menginstance object $person kita memberikan nilai "Oka", 21 dan account balance 200 pada masing2 class attributenya. Maka dari itu, digunakanlah tehnik clone ini.

Mari kita coba ya pakai contoh code. Sebagai contoh kita bertanggung jawab untuk UI (Presentation Tier), dan kolega kita yang bertanggung jawab di bagian Database (Persistent Tier).
<?php
$person = new Person ($_POST['name'], $_POST['age'], new
Account($_POST['balance']));
$person->setId($_POST['id']);

$persistancePerson->insertNewPerson($person);
?>
Sampai disini tugas kita kelar dan kita memberikan object $person kepada kolega kita yang ngurusin insert ke database. Soal SQL statement mah dia jagonya lah, kita gak peduli. Nah sekarang sebelum die melakukan insert ke database, dia pengen coba-coba dulu periksa, udah ada belon data dengan id tersebut di database, kalau memang sudah ada maka akan diberikan id baru, lalu di save. Supaya dia gak mengganggu object state yang diterima dari kita, maka untuk coba-coba, dia bikin clone dari object tersebut.

Misalnya isi dari methode insertNewPerson(Person $person) seperti berikut:
<?php
public function insertNewPerson(Person $person){
   $person2 = clone $person;

  while($this->idAlreadyExist($person2->getId())){
         $person2->setId($this->getNextId());
  }

  $DBObject::getInstance()->execute('INSERT INTO person ......');
}
?>

Dengan ini dia mencoba-coba menggunakan object kopian dari $person. Pada $person2->setId() hanya object $person2 saja yang terganti statenya. Object $person tetap seperti sediakala, sewaktu dia menerima dari kita.

Manakah yang lebih cepat, membuat instance baru, atau mencopy. Disini kita bisa membaca kembali dokumentasinya. Disitu ditulis:

When an object is cloned, PHP 5 will perform a shallow copy of all of the object's properties. Any properties that are references to other variables, will remain references.

Menurut pemahaman gue tentang Computer system, untuk bikin instance baru itu pasti lebih ribet, mungkin ngecheck nilai dari parameternya bener tidak, nama classnya exist tidak, terus generate segalanya dalam bentuk object, lalu cari memory yang kosong untuk di simpan. Kalau copy object kan dia gak perlu ngejalanin semuanya itu. tinggal cari memory kosong, terus kopi ajah mentah-mentah (shallow copy) dari memory object aslinya.

Gue harap informasi ini bisa memberikan pencerahan.

10 comments:

stieven said...

Akhirnya setelah 4 bulan ada posting baru ya hehehe... btw, artikel yang menarik thx for share

Arthur Purnama said...

sibuk mas ^^, kayak gak tahu gue aje lo :P

Jawaad Alkaff said...

Waw.. super mantap neh om Arthur penjelasannya :)
sangat memberi pencerahan banget neh di OOP.

thx

M. Rizki Romdoni said...

Thx Informasinya Tambah-Tambah Elmu

stieven said...

posting lama tapi tidak basi (",), re-comment lagi ya. Skalian cuman bagi pengalaman. Kenapa banyak yg tidak/jarang menggunakan Object Cloning? karena kebanyakan PHP-ers masih bekerja individual alias project sendiri. Untuk beberapa dari mereka yang bekerja sebagai tim tentunya ini sangat berguna, ya apalagi project yang di bangun dengan model modul dan setiap modul di tangani orang yang berbeda, object cloning ini akan sering di gunakan. Btw mas Arthur thx artikel ini aku jadiin references buat anggota tim yg baru hihihi malas aku jelasin panjang lebar mending suruh baca ini aja hahhahahaa

Arthur Purnama said...

senang bisa membantu om stieven...

Edwin said...

artikelnya bagus mas, kebetulan saya mau belajar penggunaan class di PHP. Terima kasih artikelnya.

Arthur Purnama said...

sama sama.
senang bisa membantu

apep said...

Saya cuma mau comment: Oke banget Artikelnya.

alrisjualan said...

Wah saya gak ngerti blas. Salam kenal dari tukang bangunan. Sukses selalu.
salam
http://PakOsu.wordpress.com
http://alrisblog.wordpress.com