Inheritance, The Stupid Way

Inheritance bukan sekedar sharing state maupun behaviour. Programmer sangat mudah sekali untuk menyalahgunakan inheritance sehingga menghasilkan code "gila". Ini ilustrasinya:

class Monyet
def initialize
@jumlah_kaki = 2
@jumlah_tangan = 2
@jumlah_jari = 5
end
def makan
#...
end
def minum
#...
end
def buang_air
#...
end
end

class Manusia < Monyet
def belajar
#...
end
def membaca
#...
end
end

Hey.. Manusia bukanlah Monyet yang dapat belajar dan membaca! :)

Prototype-based Programming

Dalam pemrograman berorientasi objek, class digunakan sebagai "cetakan" atau "pabrik" untuk membuat object. Umumnya, class dan object dipandang sebagai dua hal yang berbeda, dimana object merupakan instance dari suatu class. Pemahaman seperti ini tidak salah, namun dalam paradigma object-oriented programming ini bukanlah satu-satunya cara. Salah satunya adalah Prototype-based Programming, dimana object dan class dipandang sebagai hal yang sama!!! Dalam bahasa pemrograman Ruby, untuk menerapkan metode ini sangat mudah karena kita tahu bahwa pada ruby semua adalah Object, termasuk Class itu sendiri adalah Object. Anda bisa membuktikannya melalui irb seperti contoh di bawah ini:

irb(main):001:0> Class.kind_of?Object
=> true
irb(main):002:0> Object.kind_of?Class
=> true

Class adalah object dan Object (dalam konteks ini) adalah class. So, antara class dan object tidak dibeda-bedakan lagi.
OK, sekarang kita akan bandingkan metode "class-oriented" dengan prototyped-based. Pertama, kita membuat yang class-oriented dulu:
class Hewan
def jumlah_kaki=(kaki)
@jumlah_kaki = kaki
end
def jumlah_kaki
@jumlah_kaki
end
end

class Kucing < Hewan
def initialize
@jumlah_kaki = 4
end
end

manis = Kucing.new

puts manis.jumlah_kaki

Kode di atas kita membuat class Hewan yang di dalamnya terdapat setter dan getter untuk instance variable @jumlah kaki. Kemudian kita buat class Kucing yang menurun dari class Hewan dan memiliki method konstruktor untuk menjadikan @jumlah_kaki = 4. Jika kita eksekusi, maka pada layar akan tercetak angka 4.
OK, itu tadi class-oriented. Di bawah ini, kita buat yang model prototype-based untuk kita bandingkan.
hewan = Object.new

def hewan.jumlah_kaki=(kaki)
@jumlah_kaki = kaki
end
def hewan.jumlah_kaki
@jumlah_kaki
end

kucing = hewan.clone

kucing.jumlah_kaki = 4

manis = kucing.clone

puts manis.jumlah_kaki

Jika kode ini kita eksekusi, hasilnya akan sama dengan kode sebelumnya. Jika kita perhatikan, kita tidak menemukan pendefinisian class pada kode yang terakhir ini. Yang kita lakukan adalah membuat object baru kemudian memodifikasinya maupun melakukan kloning. Ya, inti dari Prototype-based programming pada Ruby adalah pada method clone. Object hewan kita kloning menjadi kucing kemudian kita tambahkan state baru berupa jumlah_kaki = 4. Kemudian kucing kita clone lagi menjadi manis, dan alhasil manis juga memiliki state dan behaviour yang sama persis dengan kucing.

Selamat mencoba.

Meta-Meta-Programming

Presentasi Dr. Nic tentang meta-meta-programming.

Hello Metaprogramming

Yuk... kini saatnya kita mempraktekan teknik metaprogramming. Semacam aplikasi 'hello world' gitu deh. Saya asumsikan komputer anda telah ter-install Interpreter Ruby (saya menggunakan Ruby 1.8.6). Saya juga mengasumsikan pembaca telah menguasai dasar-dasar bahasa pemrograman Ruby. Silahkan salin code di bawah ini menggunakan teks editor kesayangan anda kemudian beri nama manusia.rb

class Manusia
def self.umpat(bahasa, umpatan)
class_eval "def mengumpat_dalam_bahasa_#{bahasa}; puts '#{umpatan}'; end"
end
umpat("inggris", "Shit!")
umpat("jawa", "Jancok!")
end


Simpan file tersebut di lokasi favorit anda dan jalankan program irb di lokasi yang sama (melalui console). Kemudian ikuti langkah-langkah berikut ini pada irb anda:

irb(main):001:0> require 'manusia.rb'
=> true
irb(main):002:0> saya = Manusia.new
=> #
irb(main):003:0> saya.mengumpat_dalam_bahasa_inggris
Shit!
=> nil
irb(main):004:0> saya.mengumpat_dalam_bahasa_jawa
Jancok!
=> nil


Sampai di sini, kita telah melakukan metaprogramming sederhana. Dimana letak unwritten code-nya? Kita tidak pernah menulis method mengumpat_dalam_bahasa_inggris dan mengumpat_dalam_bahasa_jawa secara eksplisit, tapi kita bisa memanggilnya. Dari mana gerangan dia berasal? Inilah salah satu contoh "magic" yang ada dalam metaprogramming. Rahasianya ada di method ini:

class_eval "def mengumpat_dalam_bahasa_#{bahasa}; puts '#{umpatan}'; end"


Selalu ingat bahwa code is data, data is code. Berkat method class_eval, String yang terdapat pada method class_eval dieksekusi layaknya code walaupun kita tahu bahwa String yang "normal" itu adalah data bukan code yang harus dieksekusi oleh interpreter.

Sekarang kita menginginkan supaya manusia bisa mengumpat dalam bahasa Indonesia? Bagaimana caranya? Jangan tutup console irb anda, kita lanjutkan yang tadi:

irb(main):005:0> Manusia.umpat('indonesia','Kampret!')
=> nil
irb(main):006:0> saya.mengumpat_dalam_bahasa_indonesia
Kampret!
=> nil


Yay.. sekarang manusia bisa mengumpat dalam bahasa Indonesia. Hal ini dimungkinkan karena pada bahasa Ruby, class selalu terbuka (open). Kapanpun kita bisa menambahkan atribut ke dalam class yang kita inginkan.

Metaprogramming, Mengapa Ruby?

Metaprogramming:

  • program yang menulis program
  • tool yang sangat istimewa untuk membuat framework
  • kunci utama dalam pembuatan domain-specific languages (DSL)
Ruby cocok untuk metaprogramming, karena:
  • dynamic dan reflexive
  • open dan malleable
  • code is data, data is code
  • sintaks yang bersih
  • programming event model

Laws Of Ruby Weapon

Untuk mempraktekan "seni sulap" dengan teknik metaprogramming, saya memilih untuk menggunakan bahasa pemrograman Ruby. Dr. Nic, salah satu "ahli sulap" di dunia Ruby dan Ruby On Rails memberikan 3 aturan yang disebut Laws Of Ruby Weapon:
1. Made at runtime.
2. Access at runtime.
3. Fixed at runtime.
Bila diperhatikan, semua dikerjakan pada saat runtime..
That's The Ruby Way!!!

Metaprogramming?

Metaprogramming adalah teknik pemrograman dimana code yang kita tulis akan menulis code yang lain atau melakukan introspect terhadap dirinya sendiri. Kata meta yang merupakan awalan dari kata metaprogramming memiliki arti abstraksi. Teknik metaprogramming bekerja pada dua tingkatan abstraksi secara simultan. Untuk melakukan metaprogramming dapat digunakan berbagai macam bahasa pemrograman, tetapi yang paling populer adalah bahasa pemrograman dinamis. Mengapa bahasa dinamis? Karena bahasa dinamis memiliki kemampuan manipulasi code layaknya data pada saat runtime. Walaupun reflection juga tersedia pada bahasa statis seperti Java dan C#, akan tetapi tidak bisa setransparan seperti pada bahasa dinamis macam Ruby, Python, dan Lisp. Hal ini karena pada bahasa statis, code dan data memiliki tingkatan yang berbeda pada saat runtime.

Untuk mencegah duplikasi code yang sama biasanya kita membuat suatu fungsi. Hal ini disebut dengan instilah functional abstraction. Salah satu fungsi dari metaprogramming juga mirip dengan ini, namun bukan untuk mencegah duplikasi code melainkan mencegah duplikasi konsep. Singkat kata, redundansi code dapat difaktorkan menjadi fungsi, redundansi fungsi atau pattern dapat (walaupun tidak selalu) difaktorkan menggunakan teknik metaprogramming.

Metaprogramming dibuat untuk kesederhanaan. Namun metaprogramming memiliki berbagai resiko yang cukup berbahaya, misalnya:

  • Code sulit dipelihara
  • Performa turun drastis
Dengan pemahaman yang matang tentang teknik metaprogramming, hal-hal tersebut dapat dihindari. Selamat belajar metaprogramming.