เหตุใดวัตถุการถ่ายโอนข้อมูล (DTO) จึงเป็นรูปแบบต่อต้าน


132

ผมเคยได้ยินคนบอกว่าเมื่อเร็ว ๆ นี้การถ่ายโอนข้อมูลวัตถุ (DTOs) เป็นต่อต้านรูปแบบ

ทำไม? ทางเลือกอื่นคืออะไร?


11
บางทีอาจเป็นเพราะวัตถุทางธุรกิจมีความสามารถในการขนส่งข้อมูลของตัวเองขอบคุณมาก!
Zoidberg

13
"แอนตี้ - แพทเทิร์น" อาจเป็นผู้เสนอชื่อ "วลีที่ 15 นาทีขึ้นเมื่อนานมาแล้ว" มีความหมายเหมือนกันกับ "ฉันไม่สนใจที่จะรบกวนการปรับความคิดของฉัน" ในตอนนี้เช่น "เป็นที่รู้กันดีว่า ... "
Craig Stuntz

6
Zoidberg การส่งวัตถุด้วยวิธีการผ่านสายทำให้เรามี CORBA, DCOM และประสบการณ์อื่น ๆ ที่ฉันพยายามลบความทรงจำของฉัน ปัญหาคือไม่ช้าก็เร็วคนต้องการเรียกวิธีการเหล่านั้น
Craig Stuntz

10
DTO ใช้หลักการ DRY ซึ่งโชคร้ายใน J2EE หมายถึงทำซ้ำด้วยตัวคุณเอง
joeforker

คุณอาจต้องการอ่านสิ่งนี้: Data Transfer Object Is a Shame
yegor256

คำตอบ:


139

บางโครงการมีข้อมูลทั้งหมดเป็นครั้งที่สอง เมื่อเป็นวัตถุโดเมนและอีกครั้งเป็นวัตถุการถ่ายโอนข้อมูล

การทำสำเนานี้มีค่าใช้จ่ายสูงดังนั้นสถาปัตยกรรมจึงจำเป็นต้องได้รับประโยชน์มหาศาลจากการแยกนี้จึงจะคุ้มค่า


5
โปรดอธิบายอย่างละเอียดเกี่ยวกับ "ต้นทุนมหาศาล" นอกจากนี้บอกว่าเหตุใดจึงไม่สามารถกำจัดต้นทุนได้โดยใช้เทคนิคการสร้างรหัสเพื่อสร้างคลาส DTO
John Saunders

70
+1 ครั้งที่สอง? เฉพาะในกรณีที่คุณโชคดี :-) โปรเจ็กต์ที่ทำซ้ำเอนทิตีโดเมนเป็น DTO ก็มีแนวโน้มที่จะมี UI bean ที่แตกต่างกันเกือบจะเหมือนกัน แต่โอ้เอ้อย่างละเอียดเพื่อเสริมพวกเขา นั่นคือ 3 และถ้าพระเจ้าห้ามมีการรีบูตบางอย่าง (บริการเว็บ / xml-rpc / อะไรก็ตาม) เกิดขึ้นคุณสามารถไปที่ 4 หรือ 5 ได้อย่างง่ายดาย
ChssPly76

17
ขณะนี้ฉันกำลังทำงานกับสถาปัตยกรรมลาซานญ่า 14 ชั้นที่มีความสามารถ (ไม่ใช่การคิด) ฉันมั่นใจได้ว่าเลเยอร์ 11 หรือมากกว่านั้นสำหรับตัวถ่ายโอนข้อมูลส่วนใหญ่ไม่ได้มาฟรี
KarlP

10
นอกจากนี้ในขณะที่ฉันรักเครื่องกำเนิดโค้ดอย่างมากเมื่อทำงานกับการออกแบบที่โง่เขลาพวกเขาเป็น) สิ่งที่แน่นอนว่าคุณทำผิดตั้งแต่เริ่มต้น b) พวกเขาไม่ได้มาฟรี
KarlP

7
ขออภัย แต่นี่ไม่ถูกต้องและคำตอบที่ผิดได้รับการโหวตและได้รับการยอมรับสูง ก่อนอื่นคุณสามารถใช้การสะท้อนเพื่อสร้าง DTO ได้ทันที ประการที่สองคุณสามารถใช้ "คำจำกัดความรูท" เช่นในระบบ CASE หรือใน OAW และสร้าง BO และ DTO (s) ประการที่สามคุณสามารถใช้ XSD และ JAXB เพื่อสร้าง DTO และใช้ DTO เป็นฐานสำหรับ BO หรือคุณสามารถสร้างทั้งสองอย่างจาก XSD ... อย่างไรก็ตามหากใครจะกล้าถ่ายโอน EJB ที่ดึงมาใหม่จากฐานข้อมูล ต่อสายไปยังโปรแกรมไคลเอนต์ ... ในสภาพแวดล้อมที่ฉันทำงานหัวของเขาจะอยู่บนแผ่นเงินเร็ว ๆ นี้ ...
Angel O'Sphere

128

DTO ไม่ใช่รูปแบบการต่อต้าน เมื่อคุณส่งข้อมูลข้ามสาย (เช่นไปยังหน้าเว็บในการโทร Ajax) คุณต้องการให้แน่ใจว่าคุณประหยัดแบนด์วิดท์โดยการส่งเฉพาะข้อมูลที่ปลายทางจะใช้ นอกจากนี้บ่อยครั้งที่เลเยอร์การนำเสนอจะสะดวกในการมีข้อมูลในรูปแบบที่แตกต่างจากออบเจ็กต์ทางธุรกิจดั้งเดิมเล็กน้อย

ฉันรู้ว่านี่เป็นคำถามที่เน้น Java แต่ในภาษา. NET ประเภทที่ไม่ระบุชื่อการทำให้เป็นอนุกรมและ LINQ อนุญาตให้สร้าง DTO ได้ทันทีซึ่งจะช่วยลดการตั้งค่าและค่าใช้จ่ายในการใช้งาน


15
@ จอห์นนี่ไม่ถูกต้อง ฉันทำมันตลอดเวลา การทำให้เป็นอนุกรมใช้การสะท้อนซึ่งใช้ได้ดีกับประเภทที่ไม่ระบุตัวตน เพียงแค่ส่งต่อไปยัง serializer เป็นวัตถุ และเมื่อมีการต่ออนุกรม (เป็น xml หรือ json เป็นต้น) แน่นอนว่าคุณสามารถส่งคืนได้จากวิธีการ
Gabe Moothart

8
อืมจอห์นนั่นไม่เป็นความจริง คุณสามารถจัดลำดับประเภทที่ไม่ระบุตัวตนเป็น JSON ได้ดี ลองใช้ในแอป MVC: ส่งคืน Json (ใหม่ {Foo = "Hi there!}) ฉันสัญญาว่าจะใช้งานได้ดีบางทีอาจจะดีกว่าประเภทที่ไม่ระบุตัวตนเนื่องจากโดยทั่วไปประเภทที่ไม่ระบุตัวตนจะไม่มีรอบในกราฟวัตถุ ซึ่งทำลายซีเรียลไลเซอร์ JSON
Craig Stuntz

1
Json serialization ไม่ใช่ DTO ในแง่นี้ดังนั้นจึงไม่มีผลบังคับใช้ แน่นอนว่าข้อโต้แย้งของฉันข้างต้นก็มีผลเช่นกันในบางครั้งพวกเขาก็หยุดที่จะคุ้มค่า
Jim Barrows

1
Gabe ถูกต้อง DTO ไม่ใช่ anti-pattern ต่อ se (แต่สามารถใช้ได้ถ้าใช้ไม่ถูกต้อง!) เมื่อไม่มีการทำสำเนาข้อมูล ตัวอย่างเช่น BO สามารถรวมข้อมูลจากแหล่งที่มาต่างๆเป็น DTO
astro

3
+1 และยังมีเหตุผลอื่น ๆ อีกมากมายนอกเหนือจากการอนุรักษ์แบนด์วิธที่คุณต้องการ DTO คุณได้รับอนุญาตแม้กระทั่ง (ตามนโยบายของ บริษัท หรือกฎหมาย) ในการส่งทุกฟิลด์ข้ามสายหรือไม่? นอกจากนี้ใน บริษัท ของเรา DAO ของเรามีความซับซ้อนมากเพราะต้องทำการปรับให้เหมาะสมทั้งหมด - การทำงานในชั้นบริการฉันดีใจมากที่พวกเขาใช้ DTO และไม่ทำให้เรากังวลเกี่ยวกับความสัมพันธ์ที่ Object X มี ไปยังตาราง n-to-n อื่น ๆ
user64141

25

DTO an AntiPattern ใน EJB 3.0พูดว่า:

ลักษณะที่มีน้ำหนักมากของ Entity Beans ในข้อกำหนด EJB ก่อน EJB 3.0 ทำให้เกิดการใช้รูปแบบการออกแบบเช่น Data Transfer Objects (DTO) DTO กลายเป็นอ็อบเจ็กต์ที่มีน้ำหนักเบา (ซึ่งควรจะเป็นเอนทิตีถั่วเองในตอนแรก) ใช้สำหรับส่งข้อมูลข้ามระดับ ... ตอนนี้ EJB 3.0 spec ทำให้ Entity bean model เหมือนกับ Plain old Java object (POJO) ด้วยโมเดล POJO ใหม่นี้คุณไม่จำเป็นต้องสร้าง DTO สำหรับแต่ละเอนทิตีหรือชุดของเอนทิตีอีกต่อไป ... หากคุณต้องการส่งเอนทิตี EJB 3.0 ข้ามระดับให้ใช้ java.io.Serialiazable


6
เป็นจริงเมื่อคุณถ่ายโอนวัตถุระหว่างวิธีการใน JVM เดียวกันในหน่วยความจำ ไม่เป็นความจริงเมื่อคุณทำการต่ออนุกรมผ่านสายไฟและต้องการควบคุมว่าจะทำให้เป็นอนุกรมได้ลึกแค่ไหนและ / หรือรักษาการโหลดแบบขี้เกียจ
wrschneider

ใช่และแม้จะอยู่ใน JVM เดียวกันคุณควรดูแลให้อยู่ในกลุ่มเดียวกันหากคุณใช้การจัดการธุรกรรม JEE / Spring
Marc

20

ฉันไม่คิดว่า DTO เป็นรูปแบบการต่อต้าน แต่มีการต่อต้านรูปแบบที่เกี่ยวข้องกับการใช้ DTO Bill Dudney อ้างถึงการระเบิดของ DTO เป็นตัวอย่าง:

http://www.softwaresummit.com/2003/speakers/DudneyJ2EEAntiPatterns.pdf

นอกจากนี้ยังมีการละเมิด DTO หลายประการที่กล่าวถึงที่นี่:

http://anirudhvyas.com/root/2008/04/19/abuses-of-dto-pattern-in-java-world/

มีต้นกำเนิดมาจากระบบสามชั้น (โดยทั่วไปใช้ EJB เป็นเทคโนโลยี) เป็นวิธีการส่งผ่านข้อมูลระหว่างชั้น ระบบ Java สมัยใหม่ส่วนใหญ่ที่ใช้เฟรมเวิร์กเช่น Spring ใช้มุมมองแบบง่ายทางเลือกอื่นโดยใช้ POJO เป็นอ็อบเจ็กต์โดเมน (มักใส่คำอธิบายประกอบด้วย JPA เป็นต้น ... ) ในระดับเดียว ... การใช้ DTO ที่นี่ไม่จำเป็น


3
คุณเข้าใจถูกแล้วว่า DTO เป็นรูปแบบที่ดีไม่ใช่รูปแบบการต่อต้านเมื่อใช้ในบริบทที่เหมาะสม ลิงก์ที่สองของคุณดูเหมือนจะตายในขณะนี้ แต่การละเมิดที่ยิ่งใหญ่ที่สุดที่ฉันเห็นคือที่ที่ทุกออบเจ็กต์ของโดเมนมี "DTO" ที่เกี่ยวข้องสำหรับการโต้ตอบกับฐานข้อมูลซึ่งไม่ได้เพิ่มมูลค่าและไม่ใช่ DTO เลย!
เดวิด


9

บางคนคิดว่า DTO เป็นรูปแบบการต่อต้านเนื่องจากอาจเกิดการละเมิดได้ มักใช้เมื่อไม่ควร / ไม่จำเป็นต้องเป็น

บทความนี้อธิบายการละเมิดบางอย่างอย่างคลุมเครือ


1
บทความนี้อธิบาย DTO ได้อย่างถูกต้องมากขึ้นว่าเป็นรูปแบบที่สามารถนำไปใช้ในทางที่ผิดได้
Craig Stuntz

จำนวนนี้เป็นคำตอบแบบลิงก์เท่านั้นอย่างน้อยก็ต้องมีใบเสนอราคาจากบทความ ไม่รู้ว่าสิ่งนี้จัดการอย่างไรเพื่อไม่ให้ถูกตั้งค่าสถานะว่าไม่ใช่คำตอบ
Nathan Hughes


7

หากคุณกำลังสร้างระบบแบบกระจาย DTO ไม่ใช่รูปแบบการต่อต้านอย่างแน่นอน ไม่ใช่ทุกคนที่จะพัฒนาในแง่นั้น แต่ถ้าคุณมี (ตัวอย่าง) เปิดแอปโซเชียลทั้งหมดที่รัน JavaScript

จะโพสต์ข้อมูลจำนวนมากไปยัง API ของคุณ จากนั้นจะถูก deserialized เป็นอ็อบเจ็กต์บางรูปแบบโดยทั่วไปคืออ็อบเจ็กต์ DTO / Request จากนั้นสามารถตรวจสอบความถูกต้องเพื่อให้แน่ใจว่าข้อมูลที่ป้อนนั้นถูกต้องก่อนที่จะถูกแปลงเป็นออบเจ็กต์แบบจำลอง

ในความคิดของฉันมันถูกมองว่าเป็นการต่อต้านรูปแบบเพราะใช้ผิดวิธี หากคุณไม่ได้สร้างระบบแบบกระจายโอกาสที่คุณจะไม่ต้องการมัน


4

วัตถุประสงค์ของData Transfer Objectคือการจัดเก็บข้อมูลจากแหล่งต่างๆแล้วถ่ายโอนไปยังฐานข้อมูล (หรือRemote Facade ) ในครั้งเดียว

อย่างไรก็ตามรูปแบบ DTO นั้นละเมิดหลักการความรับผิดชอบเดียวเนื่องจาก DTO ไม่เพียง แต่จัดเก็บข้อมูลเท่านั้น แต่ยังถ่ายโอนจากหรือไปยังฐานข้อมูล / ซุ้ม

ความจำเป็นในการแยกออบเจ็กต์ข้อมูลออกจากอ็อบเจ็กต์ทางธุรกิจไม่ใช่แอนตี้แพตเทิร์นเนื่องจากอาจจำเป็นต้องแยกเลเยอร์ฐานข้อมูลอยู่ดี

แทนที่จะใช้ DTO คุณควรใช้ Aggregate and Repository Patterns ซึ่งจะแยกการรวบรวมวัตถุ ( Aggregate ) และการถ่ายโอนข้อมูล ( Repository )

ในการถ่ายโอนกลุ่มของอ็อบเจ็กต์คุณสามารถใช้รูปแบบUnit Of Workซึ่งเก็บชุดของที่เก็บและบริบทธุรกรรม เพื่อถ่ายโอนแต่ละออบเจ็กต์ในการรวมแยกกันภายในธุรกรรม


4

DTO กลายเป็นสิ่งจำเป็นและไม่ใช่ ANTI-PATTERN เมื่อคุณมีอ็อบเจ็กต์โดเมนทั้งหมดของคุณโหลดอ็อบเจ็กต์ที่เกี่ยวข้อง EAGERly

หากคุณไม่ได้สร้าง DTO คุณจะมีการถ่ายโอนออบเจ็กต์ที่ไม่จำเป็นจากชั้นธุรกิจของคุณไปยังเลเยอร์ไคลเอนต์ / เว็บของคุณ

หากต้องการ จำกัด ค่าโสหุ้ยสำหรับกรณีนี้ให้โอน DTO


1

คำถามไม่ควรเป็น "ทำไม" แต่เป็น " เมื่อ "

แน่นอนว่ามันเป็นการต่อต้านรูปแบบเมื่อเพียงผลจากการใช้งานเท่านั้นที่มีค่าใช้จ่ายสูงขึ้น - เวลาทำงานหรือการบำรุงรักษา ฉันทำงานในโครงการที่มี DTO หลายร้อยตัวเหมือนกับคลาสเอนทิตีฐานข้อมูล ทุกครั้งที่คุณต้องการเพิ่มฟิลด์เดียวที่คุณโฆษณาเพื่อเพิ่ม id เช่นสี่ครั้ง - เป็น DTO เป็นเอนทิตีไปจนถึงการแปลงจาก DTO เป็นคลาสโดเมนหรือเอนทิตีการแปลงผกผัน ... คุณลืมสถานที่และข้อมูลบางส่วนที่ได้รับ ไม่แน่นอน

มันไม่ได้ต่อต้านรูปแบบเมื่อคุณต้องการการแสดงที่แตกต่างกันของการเรียนโดเมนจริงๆ - แบนเพิ่มเติมที่อุดมไปด้วยมากขึ้นแคบมากขึ้น ...

โดยส่วนตัวแล้วฉันเริ่มต้นด้วยคลาสโดเมนและผ่านมันไปโดยมีการตรวจสอบที่ถูกต้อง ฉันสามารถใส่คำอธิบายประกอบและ / หรือเพิ่มคลาส "ตัวช่วย" เพื่อสร้างการแมปฐานข้อมูลไปยังรูปแบบอนุกรมเช่น JSON หรือ XML ... ฉันสามารถแบ่งคลาสเป็นสองคลาสได้ตลอดเวลาหากฉันรู้สึกว่าต้องการ

มันเกี่ยวกับมุมมองของคุณ - ฉันชอบที่จะมองวัตถุโดเมนเป็นวัตถุชิ้นเดียวที่มีบทบาทต่าง ๆ แทนที่จะเป็นวัตถุหลายชิ้นที่สร้างจากกันและกัน หากออบเจ็กต์มีบทบาทเดียวคือการขนส่งข้อมูลแสดงว่าเป็น DTO


1

ฉันคิดว่าผู้คนหมายความว่ามันอาจเป็นการต่อต้านรูปแบบหากคุณใช้วัตถุระยะไกลทั้งหมดเป็น DTO DTO เป็นเพียงชุดของแอตทริบิวต์และหากคุณมีวัตถุขนาดใหญ่คุณจะโอนแอตทริบิวต์ทั้งหมดเสมอแม้ว่าคุณจะไม่ต้องการหรือใช้ก็ตาม ในกรณีหลังควรใช้รูปแบบ Proxy

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.