Posted on July 17, 2015
By Karun Siritheerathamrong
…Duck Typing คืออะไร?…
Duck Typing เป็นลักษณะหนึ่งของการเขียนโปรแกรม ที่ไม่ได้พึ่งการทำงานแบบ Strong Typing มักปรากฏในภาษาโปรแกรมสมัยใหม่ที่เป็น Dynamic Language
สำหรับ Strong Typing ความเหมาะสมของออบเจ็กต์หรือตัวแปรในการใช้งาน จะถูกพิจารณาจากประเภทของออบเจ็กต์นั้น แต่สำหรับ Duck Typing แล้ว ความเหมาะสมของออบเจ็กต์หรือตัวแปรจะถูกพิจารณาจาก สิ่งที่ออบเจ็กต์นั้น “ทำได้” (method) และข้อมูลภายในที่ออบเจ็กต์นั้น “ถืออยู่” (attributes)
คำว่า Duck Typing นี้มีที่มาจากคำว่า Duck Test ซึ่งเป็นการให้เหตุผลแบบ “อุปมาน” ที่อาจมีที่มาจากงานเขียนของ James Whitcomb Riley ที่ว่า
“เมื่อฉันเห็นนกที่เดินแบบเป็ด ว่ายน้ำแบบเป็ด และร้องแบบเป็ด ฉันเรียกนกตัวนั้นว่า เป็ด”
ตัวอย่างของโค้ดที่เป็นแบบ Duck Typing (ตัวอย่างแสดงด้วย Ruby)
[code language="ruby"] require "pp" def calculate(a, b, c) return (a + b) * c end pp calculate(1, 2, 3) # => 9 pp calculate([1, 2], [3, 4], 2) # => [1, 2, 3, 4, 1, 2, 3, 4] pp calculate('Hello ', 'World ', 2) # => "Hello World Hello World " [/code]
สังเกตว่าในบรรทัดที่ 7 8 และ 9 นั้น พารามิเตอร์ที่ส่งไปยัง calculate นั้นเป็นคนละประเภทกันทั้งสิ้น แต่สามารถทำงานจนจบโปรแกรมได้ด้วยไม่เกิดข้อผิดพลาด
นั่นเพราะว่า ออบเจ็กต์ประเภท Fixnum (ตัวเลข) Array (อาเรย์) และ String (ชุดตัวอักษร) นั้น สามารถเรียกใช้เมธอด `+’ และ `*’ ได้ทั้งหมด
ข้อดีของการเขียน / ออกแบบโปรแกรมแบบนี้คือ เราไม่ต้องกังวลเกี่ยวกับการแปลงประเภทของตัวแปร หรือ ออบเจ็กต์ ที่ส่งผ่านเป็นพารามิเตอร์ไป-มา ระหว่าง runtime มากนัก เพราะเพียงแค่เราสร้างออบเจ็กต์หรือตัวแปรนั้นให้สามารถเรียกใช้ method ที่ต้องใช้ หรือ ให้มี attribute ที่จำเป็นต้องใช้ได้ ไม่ว่าด้วยวิธีการอะไรก็ตามแต่ ก็จะทำให้โปรแกรมสามารถทำงานต่อไปได้
ส่วนข้อเสียของการเขียน / ออกแบบโปรแกรมที่เป็น Duck Typing คือ….
- การแก้บั๊กอาจจะยากขึ้นเนื่องจาก ข้อผิดพลาดจะปรากฏขึ้นมาเมื่อตอน runtime เท่านั้น ตอนที่ออบเจ็กต์หรือตัวแปรที่ส่งไป-มา ไม่ได้ประกาศ หรือ สืบทอด method ที่จำเป็นต้องใช้เอาไว้
- การไล่โค้ดเพื่อทำความเข้าใจในการทำงานอาจจะยากลำบากขึ้นเล็กน้อย เพราะเราอาจจะต้องเปิดดูไฟล์ หรือคลาส หรือโมดูลที่เกี่ยวข้อง เพื่อไล่ตามการทำงานของการเรียกใช้ method หรือ attribute ที่ใช้งาน
แต่เราก็สามารถลดข้อผิดพลาดข้างต้นได้ ด้วยการมีการทดสอบ และ/หรือ เอกสารกำกับที่ค่อนข้างชัดเจน เพื่อลดข้อผิดพลาดที่อาจเกิดขึ้น และเพื่อเป็นการง่ายต่อการทำความเข้าใจในลำดับการทำงานของโค้ดด้วย
ต่อไปเป็นตัวอย่างของ Duck Typing แบบที่มีการจัดการและ แยกส่วนของโค้ดออกจากกันให้เรียบร้อยขึ้น และนำเอาการทำงานแยกออกมาเป็นโค้ดส่วนเล็ก จะแสดงด้วยภาษา Ruby
ไฟล์ singable.rb
[code language="ruby"] # singable.rb module Singable def sing_a_song puts "Singing ...#{voice}" end end [/code]
ไฟล์ main.rb
[code language="ruby" highlight="4,12"] require "singable.rb" class Human include Singable def voice "I am a pretty Hoooooman!" end end class Bird include Singable def voice "Tweety, tweety, tweet" end end def sing(singer) singer.sing_a_song end human = Human.new bird = Bird.new puts sing(human) # => "Singing ...I am a pretty Hoooooman!" puts sing(bird) # => "Singing ...Tweety, tweety, tweet" [/code]
สังเกตบรรทัดที่ไฮไลท์เอาไว้… เป็นวิธีการหนึ่งในการทำ Duck Typing ให้กับคลาส Human และ Bird โดยการรวมเอาโมดูล Singable เข้ามาในคลาสทั้งสอง นั่นเอง 🙂