closure, FP และ OOP

เมื่อวานนี้พูดถึงคำนิยามของ closure ไป วันนี้ผมจะนำมันมาใช้สร้างโค้ดที่มีลักษณะคล้ายโค้ดจากภาษา Object-oriented programming (OOP) ให้ดูครับ

เริ่มต้นด้วยโค้ด OOP บน Ruby ก่อน

class Prepend
  def initialize(start_word)
    @start_word = start_word
  end

  def prepend_for(end_word)
    @start_word + " " + end_word  # Not idiomatic Ruby but should be more familiar for other languages user
  end
end

hello = Prepend.new("Hello")
hello.prepend_for("Tap") # => "Hello Tap"
hello.prepend_for("OOP") # => "Hello OOP"

ผมทำสร้างคลาส Prepend ซึ่งมี constructor method ที่รับพารามิเตอร์ 1 ตัวคือคำแรก (start_word) เก็บไว้เป็น instance variable และสร้างเมท็อด prepend_for ที่รับพารามิเตอร์หนึ่งตัวคือคำท้าย (end_word) นำคำแรกและคำท้ายต่อกัน

ลองมาดูตัวอย่างของโปรแกรมเดียวกันบน Clojure ซึ่งเป็นภาษา Functional programming (FP) กันดูบ้าง

(defn prepender [start-word]
  (fn [end-word] (str start-word " " end-word)))

(def hello (prepender "Hello"))
(hello "Tap") ; => "Hello Tap"
(hello "FP") ; => "Hello FP"

จะเห็นได้ว่าเราสามารถนำ closure (fn … start-word …) มาใช้สร้างโค้ดที่มีลักษณะคล้ายกับโค้ดในภาษา OOP ได้ ค่า “Hello” ซึ่งถูก closure ผูกเอาไว้ ถูกนำไปใช้ด้วยฟังก์ชัน hello กี่คร้ังก็ได้ในลักษณะเดียวกัน instance variable start_word ในตัวอย่างโค้ดภาษา ​OOP

มาถึงตรงนี้หลายคนอาจจะมีข้อสงสัยหลายข้อ ผมขออนุญาตลองเดาข้อสงสัยนั้นและอธิบายดูครับ

ตัวอย่างโค้ด OOP นี้มีแค่เมท็อดเดียว ถ้าเป็นโค้ดที่มีหลายเมท็อดหละ
รูปแบบการเขียนโค้ดแบบนี้ เลียนแบบ OOP ได้แค่โค้ดที่มีเมท็อดเดียวครับ แต่มันเพียงพอแล้ว
เชื่อว่าหลายคนคงเคยได้ SRP (Single Responsibility Principle) ซึ่งเป็นตัว S ของ SOLID กันมาบ้าง คลาส Prepender นี้ถือว่าปฏิบัติตาม SRP อย่างเคร่งครัดเลยทีเดียว

แล้วถ้าโค้ด OOP มี inheritance หละจะทำอย่างไร
พยายามอย่าใช้ inheritance ครับ โค้ด OOP ที่เขียนอยู่ในรูป inheritance สามารถเปลี่ยนมาเป็น composition ได้เสมอครับ
หลายคนอาจจะสงสัยว่าทำไมถึงควรหลีกเลี่ยง inheritance หละ
– Josh Bloch ผู้เขียน Java Collections Framework เขียนไว้ในหนังสือ Effective Java Programming Language Guide ข้อหนึ่งว่า Favor composition over inheritance ลองไปหาอ่านกันดูนะครับ
– ภาษา Go ซึ่งเป็นภาษาสมัยใหม่ ไม่มี inheritance ครับ

อย่างนี้ก็ไม่สามารถเปลี่ยนค่า start-word เป็นอย่างอื่นได้สิ ต้องสร้างฟังก์ชันใหม่ตลอดสิ
ครับ บน FP เราจะใช้การสร้างฟังก์ชันใหม่เสมอ ในขณะเดียวก็มีคนพูดถึงประโยชน์ของการสร้างคลาสบนภาษา OOP ที่ไม่อนุญาตให้เปลี่ยนค่า instance variable เหมือนกันครับ
– ใน Effective Java Programming Language Guide เล่มเดิมมีข้อหนึ่งที่แนะนำให้ Minimize mutability ครับ
Value object

สุดท้ายแล้วการนำ closure ในภาษา FP มาใช้สร้างโค้ดในลักษณะเดียวกับโค้ดภาษา OOP อาจจะเลียนแบบได้เพียงแค่ส่วนหนึ่ง แต่แค่ส่วนนั้นอาจจะเพียงพอสำหรับการตอบคำถามว่า จะนำ FP มาใช้งานในชีวิตจริงได้อย่างไรแล้วนะครับ

Advertisements

One thought on “closure, FP และ OOP

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s