เลิกใช้ DTO ในทางที่ผิดกันเถอะ!

บทความต้อนรับวันวาเลนไทน์ตามสไตล์คนมีเวลาประสาคนโสดด้วยเนื้อหาหนักๆ หล่ะกัน สิ่งหนึ่งที่คนออกแบบระบบทำเวลาดึงข้อมูลจากฐานข้อมูลคือการสร้าง Object ที่เรียกว่า DTO แล้วเก็บค่าเหล่านั้นไว้ จากนั้นก็ส่งออกไป layer ที่ร้องขอข้อมูล เป็นเรื่องปกติสำหรับคนใช้ JDBC ธรรมดา แต่จะเริ่มมีปัญหากับคนที่ใช้ ORM Framework อย่าง JPA หรือ Hibernate จะพบว่าเราต้องสร้าง Class ที่หน้าตาแทบจะเหมือนกับ Entity ทุกประการ และชอบเรียกสิ่งนี้ว่า DTO (Data Transfer Object) นี่คือสิ่งที่ผมขัดใจมากเวลาทำงานและเห็นคำว่า DTO เพราะอะไรตามมาอ่านต่อได้เลยครับ

Data Transfer Object


Data Transfer Object เกิดขึ้นในยุค Distributed Application ซึ่งการติดต่อระหว่าง Client และ Server มักจะเป็นแบบ RMI (Remote Method Invocation) ความหมายของมันคือการที่ Object ใน JVM เครื่องของเราสามารถไปโผล่อีก JVM ของเครื่องอื่นได้ และปัญหาก็มีอยู่ว่า พอเราใช้ EJB ชนิด Entity Bean (หรือ Session Bean) ที่เป็นแบบ Remote Object ดึงข้อมูลขึ้นมาจากฐานข้อมูลแล้วส่งกลับไปให้ Client นั้น เวลาที่ Client สั่ง get ค่าใน object จะเกิดการ Call กลับมาหา Server ทุกครั้ง (เพราะฉะนั้นหาก Object นั้นมีตัวแปรเยอะ มันก็เกิดการ Call กลับไปหา Server ตามจำนวนที่เราสั่ง get ค่าตัวแปรซึ่งกว่าจะได้ค่าตัวแปรครบก็ใช้ั Overhead พอสมควร เขาจึงคิดวิธีการส่ง Object เพียวๆ ที่ไม่ใช่ Remote Object เพื่อแก้ปัญหานี้จึงได้ pattern ที่เรียกว่า Data Transfer Object แล้วบรรจุใน Core J2EE Pattern ในตอนนั้น

ปัจจุบัน


เราพัฒนา Web Application ที่ส่วนมากเป็น Standalone ทำงานบนเครื่องเดียวอยู่แล้ว แทบไม่มีการเปิดใช้งาน Remote Call แต่อย่างไร แล้วเวลาที่เราต้องการแลกเปลี่ยนข้อมูลกับ Server เครื่องอื่นส่วนมากเราก็จะใช้ Web Service หรือส่งเป็น Batch file ด้วยซ้ำ

ดังนั้นหากเราใช้ ORM ดึงข้อมูลที่เป็น Entity ขึ้นมา เราสามารถใช้ Object นั้นได้ทันที โดยไม่ต้องลงทุนไปสร้าง Class ชื่อ DTO ที่หน้าตาเหมือนกับ Entity แทบจะ clone กันมา

ตอบปัญหาความเข้าใจผิด


  • ถ้าเกิดว่ามีการแก้ไขค่าตัวแปรใน Entity ที่ดึงขึ้นมา มันก็จะตามไปแก้ไขในฐานข้อมูลด้วยนะ ซึ่งตอนนั้น User ยังไม่ทันได้กดบันทึกข้อมูลด้วยซ้ำ
    เวลาดึงข้อมูลขึ้นมา เราสามารถตัดการเชื่อมต่อได้โดยใช้หลักการที่ชื่อ Detach Object ได้ครับ เพราะฉะนั้นเวลามีการแก้ไขค่าในตัวแปรของ Entity ก็จะไม่กระทบกับข้อมูลจริงแล้ว
  • แล้วถ้าต้องการข้อมูลที่ต้องมีการดึงจากหลาย table หล่ะ ก็ต้องสร้าง Class ใหม่เพื่อเก็บไว้ซิ
    ถ้าคุณศึกษา ORM Framework จริงจังแล้วคุณจะรู้ว่าคุณไปยึดติดกับโลกของ Relational Database ถ้าหากคุณมองมันเป็น Object เมื่อไหร่คุณจะ Design class เพื่อเก็บข้อมูลพวกนี้ให้เป็น Entity ได้เลย อย่างเช่นในตัวอย่างแรกของ Hibernate Document ก็เป็นตัวอย่างที่ดีเลย
  • ถ้า DTO ไม่ดีจริง ทำไมยังมีคนใช้เยอะอยู่หล่ะ
    มันยังมีประโยชน์สำหรับคนที่ต้องเขียนโปรแกรมที่เป็น Distributed Application อยู่ครับ ส่วนคนที่พัฒนา Web Application เขาสร้าง DTO เพราะเขาไปยึดติดกับข้อมูลที่เขาค้นได้จาก Google ในตอนนั้นแล้วไปเจอโค้ดตัวอย่างการดึงข้อมูลแบบ Entity Bean ก็เลยใช้แบบนี้กันต่อมาเรื่อยๆ

ส่งท้าย


หากท่านใช้ Hibernate Framework อยู่ และยังต้องสร้าง Entity และ DTO ที่หน้าตายังคล้ายกันอยู่ ผมขอแนะนำว่าถ้าได้สร้าง project ใหม่ขอให้เลิกใช้ DTO ได้แล้วนะครับ เพราะแม้แต่ทางทีม Hibernate เองยังไม่ทำ DTO เลย เพราะคนสร้าง Hibernate เบื่อความวุ่นวายกับการติดต่อฐานข้อมูลด้วย EJB ส่วนท่านจะทำหรือไม่ทำก็แล้วแต่ ผมห้ามไม่ได้อยู่แล้ว

อ้างอิง


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