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

1 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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s