Data Transfer Object คืออะไร


218

Data Transfer Object คืออะไร

ใน MVC เป็นโมเดลคลาส DTO และหากไม่ใช่ความแตกต่างและเราต้องการทั้งสองอย่างนี้หรือไม่


@ yegor256 และความจริงหนังสือเล่มนั้นในบทความรู้วิธีการดึงข้อมูลจาก API และวิธีการจัดเก็บข้อมูลลงในฐานข้อมูลและการละเมิด SRP นั้นตกลงไหม
Betlista

คำตอบ:


222

Data Transfer Object เป็นวัตถุที่ใช้ห่อหุ้มข้อมูลและส่งจากระบบย่อยหนึ่งของแอปพลิเคชันไปยังอีกระบบหนึ่ง

DTO มักใช้โดยเลเยอร์บริการในแอปพลิเคชัน N-Tier เพื่อถ่ายโอนข้อมูลระหว่างตัวเองและเลเยอร์ UI ประโยชน์หลักที่นี่คือช่วยลดปริมาณข้อมูลที่ต้องส่งข้ามสายในการใช้งานแบบกระจาย พวกเขายังสร้างโมเดลที่ยอดเยี่ยมในรูปแบบ MVC

การใช้งาน DTOs อีกประการหนึ่งคือการห่อหุ้มพารามิเตอร์สำหรับการเรียกใช้เมธอด สิ่งนี้มีประโยชน์หากเมธอดใช้พารามิเตอร์มากกว่า 4 หรือ 5 ตัว

เมื่อใช้รูปแบบ DTO คุณจะต้องใช้แอสเซมเบลอร์ DTO ด้วย แอสเซมเบลอร์ถูกใช้เพื่อสร้าง DTO จาก Domain Objects และในทางกลับกัน

การแปลงจาก Domain Object เป็น DTO และกลับมาอีกครั้งอาจเป็นกระบวนการที่มีค่าใช้จ่ายสูง หากคุณไม่ได้สร้างแอพพลิเคชั่นแบบกระจายคุณอาจไม่เห็นประโยชน์ที่ยิ่งใหญ่จากรูปแบบดังที่Martin Fowler อธิบายไว้ที่นี่


7
"DTO สร้างแบบจำลองที่ยอดเยี่ยมในรูปแบบ MVC" - แต่แบบจำลองไม่ควรมีข้อมูลทั้งหมดของวัตถุและ DTO จะได้รับการปรับให้เหมาะสมกับส่วนของข้อมูลหรือไม่ หากฉันมีโมเดล A และฉันต้องส่งไปยังระบบย่อยสองระบบจะมี A_DTO_1 และ A_DTO_2 พร้อมฟิลด์ที่เกี่ยวข้องของแต่ละระบบหรือไม่ "DTO สามารถ encapsulate พารามิเตอร์สำหรับการเรียกเมธอด" -> ดังนั้นทุกคลาสที่ล้อมรอบพารามิเตอร์คือ DTO แม้ว่านี่จะไม่ใช่ระบบแบบกระจาย โมเดลไม่ใช่วัตถุในโดเมนหรือไม่
Yaron Naveh

2
เพื่อตอบคำถามแรกของคุณฉันไม่คิดว่าจะพูดเรื่องเดียวกัน โมเดลใน MVC ไม่จำเป็นต้องเป็นคลาสจาก Domain Model ของคุณ ต้องบอกว่ามันอาจเป็นไปได้ การใช้ DTO ดึงเอาสิ่งที่ไม่จำเป็นออกทั้งหมด ขึ้นอยู่กับสถาปัตยกรรมที่คุณต้องการ ฉันไม่แน่ใจว่าจะตอบคำถามที่สองของคุณได้อย่างไร ไม่ว่าจะผ่านสายหรือไม่ก็ยังคงเป็นวัตถุที่ห่อหุ้มข้อมูลจำนวนมากที่จะถ่ายโอนระหว่างระบบ (ย่อย) ดังนั้นฉันจึงเถียงว่าเป็น DTO
Benny Hallett

12
"การใช้งาน DTOs อีกวิธีหนึ่งคือการห่อหุ้มพารามิเตอร์สำหรับการเรียกใช้เมธอดซึ่งจะมีประโยชน์หากเมธอดใช้พารามิเตอร์มากกว่า 4 หรือ 5 ตัว" นี่เป็นรูปแบบต่อต้านที่เรียกว่าคลาส Poltergeist หรือ Gypsy Wagon หากวิธีการของคุณต้องการ 4 ข้อโต้แย้งจากนั้นให้มัน 4 อย่าสร้างชั้นเรียนเพียงเพื่อย้ายวัตถุไปยังวิธีการหรือชั้นเรียน
Wix

2
@Wix จุดดี ฉันจะเถียง แต่นี้เป็น ok หากถูกต้อง semantically (พูดว่าถ้าคุณผ่านชั้นเรียนการตั้งค่าที่มีคุณสมบัติมากกว่าคุณสมบัติตัวเองเป็นค่า) สิ่งที่คุณไม่ควรทำคือส่งข้อโต้แย้งทั้งหมดเพื่อผ่านวัตถุชิ้นเดียวเนื่องจากมันอาจไม่เกี่ยวข้องกันมากและทำให้ฝันร้ายหลุดพ้นในภายหลัง
Aram Kocharyan

3
ไม่ควรใช้ DTO เพื่อห่อหุ้มพารามิเตอร์สำหรับการเรียกเมธอด (ซึ่งจะทำให้ LocalDTO) พวกเขาถูกนำมาใช้ในบริบทของอินเทอร์เฟซระยะไกล: martinfowler.com/bliki/LocalDTO.html
Rui

28

ความหมายสำหรับ DTO สามารถพบได้บนเว็บไซต์ของฟาวเลอร์มาร์ติน DTOs ใช้เพื่อถ่ายโอนพารามิเตอร์ไปยังเมธอดและเป็นชนิดส่งคืน ผู้คนจำนวนมากใช้สิ่งเหล่านี้ใน UI แต่คนอื่น ๆ ขยายวัตถุโดเมนจากพวกเขา


22

DTO เป็นวัตถุที่เป็นใบ้ - มันมีคุณสมบัติและมี getters และ setters แต่ไม่มีตรรกะอื่นใดที่มีนัยสำคัญ (นอกเหนือจากการนำไปใช้อาจเปรียบเทียบ () หรือเท่ากับ ()

โดยทั่วไปโมเดลคลาสใน MVC (สมมติว่า. net MVC ที่นี่) คือ DTOs หรือคอลเล็กชัน / การรวมของ DTOs


3
สิ่งที่คุณกำลังอธิบายคือ LocalDTO: martinfowler.com/bliki/LocalDTO.html
Rui

3
กรณีหนึ่งที่มีประโยชน์ในการใช้บางอย่างเช่น DTO คือเมื่อคุณมีความไม่ตรงกันอย่างมากระหว่างโมเดลในเลเยอร์การนำเสนอและโมเดลโดเมนต้นแบบ ในกรณีนี้การสร้างซุ้ม / เกตเวย์เฉพาะงานนำเสนอที่แมปจากรูปแบบโดเมนและนำเสนออินเทอร์เฟซที่สะดวกสำหรับงานนำเสนอ
Amitābha

14

โดยทั่วไปวัตถุค่าควรจะไม่เปลี่ยนรูป เช่นเดียวกับจำนวนเต็มหรือวัตถุสตริงใน Java เราสามารถใช้พวกเขาสำหรับการถ่ายโอนข้อมูลระหว่างเลเยอร์ซอฟต์แวร์ หากเลเยอร์ซอฟต์แวร์หรือบริการที่ทำงานในโหนดระยะไกลที่แตกต่างกันเช่นในสภาพแวดล้อมแบบไมโครไซต์หรือใน Java Enterprise App แบบเดิม เราต้องทำสำเนาเกือบสองชั้นอย่างแน่นอน นี่คือที่ที่เราพบ DTO

|-----------|                                                   |--------------|
| SERVICE 1 |--> Credentials DTO >--------> Credentials DTO >-- | AUTH SERVICE |
|-----------|                                                   |--------------|

ในระบบ Java Enterprise Systems DTOs แบบดั้งเดิมสามารถมี EJB หลายอย่างในนั้น

ฉันไม่ทราบว่านี่เป็นแนวปฏิบัติที่ดีที่สุดหรือไม่ แต่ฉันใช้Value Objectsในโครงการ Spring MVC / Boot ของฉันแบบนี้:

        |------------|         |------------------|                             |------------|
-> Form |            | -> Form |                  | -> Entity                   |            |
        | Controller |         | Service / Facade |                             | Repository |
<- View |            | <- View |                  | <- Entity / Projection View |            |
        |------------|         |------------------|                             |------------|

เลเยอร์คอนโทรลเลอร์ไม่ทราบว่าเอนทิตีคืออะไร สื่อสารกับแบบฟอร์มและวัตถุดูราคา Form Objects มีหมายเหตุประกอบการตรวจสอบ JSR 303 (เช่น @NotNull) และView Value Objectsมี Jackson Annotations สำหรับการทำให้เป็นอนุกรมที่กำหนดเอง (เช่น @JsonIgnore)

Service layer สื่อสารกับ repository เลเยอร์ผ่านการใช้ Entity Objects วัตถุเอนทิตีมีหมายเหตุประกอบ JPA / Hibernate / Spring Data อยู่ ทุกชั้นสื่อสารกับชั้นล่างเท่านั้น ห้ามการสื่อสารระหว่างเลเยอร์เนื่องจากการขึ้นต่อกันแบบวงกลม / แบบวงกลม

User Service ----> XX CANNOT CALL XX ----> Order Service

ORM Frameworks บางตัวมีความสามารถในการฉายภาพผ่านการใช้อินเทอร์เฟซหรือคลาสเพิ่มเติม ดังนั้นที่เก็บสามารถส่งคืนมุมมองวัตถุได้โดยตรง ที่นั่นสำหรับคุณไม่จำเป็นต้องมีการเปลี่ยนแปลงเพิ่มเติม

เช่นนี้เป็นเอนทิตีผู้ใช้ของเรา:

@Entity
public final class User {
    private String id;
    private String firstname;
    private String lastname;
    private String phone;
    private String fax;
    private String address;
    // Accessors ...
}

แต่คุณควรคืนค่ารายชื่อผู้ใช้ที่รวมเฉพาะ id, ชื่อและนามสกุล จากนั้นคุณสามารถสร้างมุมมองค่าวัตถุสำหรับการประมาณการ ORM

public final class UserListItemView {
    private String id;
    private String firstname;
    private String lastname;
    // Accessors ...
}

คุณสามารถรับผลลัพธ์การแบ่งหน้าจากเลเยอร์พื้นที่เก็บข้อมูลได้อย่างง่ายดาย ขอบคุณสปริงคุณยังสามารถใช้อินเทอร์เฟซสำหรับการคาดการณ์ได้อีกด้วย

List<UserListItemView> find(Pageable pageable);

ไม่ต้องกังวลกับBeanUtils.copyวิธีการแปลงอื่น ๆใช้งานได้ดี


11
  1. ให้ฉันตอบที่ดีที่สุดกับคำถามสิ่งที่เป็น DTOคือว่าDTO เป็นวัตถุที่เรียบง่ายที่ไม่ควรมีเหตุผลทางธุรกิจหรือการดำเนินการตามวิธีการใด ๆ ที่จะต้องมีการทดสอบ
  2. โดยปกติโมเดลของคุณ (ใช้รูปแบบ MVC) เป็นรุ่นที่ชาญฉลาดและพวกเขาสามารถมี / วิธีการบางอย่างที่ดำเนินการที่แตกต่างกันบางอย่างสำหรับรุ่นนั้นโดยเฉพาะ (ไม่ใช่ตรรกะทางธุรกิจนี่ควรเป็นตัวควบคุม) อย่างไรก็ตามเมื่อคุณถ่ายโอนข้อมูล (เช่นเรียกจุดปลายทางREST ( GET/ POST/ อะไรก็ตาม) จากที่อื่นหรือใช้ webservice โดยใช้ SOA เป็นต้น ... ) คุณไม่ต้องการส่งวัตถุขนาดใหญ่ด้วยรหัสที่ไม่จำเป็นสำหรับ ปลายทางจะใช้ข้อมูลและชะลอการถ่ายโอน

เหตุใดตรรกะทางธุรกิจจึงควรเป็นตัวควบคุม
Alexio

6

ด้วยออบเจ็กต์การถ่ายโอนข้อมูล MVC มักจะใช้ในการจับคู่โมเดลโดเมนกับวัตถุที่ง่ายกว่าซึ่งจะแสดงผลในที่สุดด้วยมุมมอง

จากWikipedia :

Data transfer object (DTO) เดิมชื่อ value objects หรือ VO เป็นรูปแบบการออกแบบที่ใช้ในการถ่ายโอนข้อมูลระหว่างระบบย่อยของแอปพลิเคชันซอฟต์แวร์ DTO มักใช้ร่วมกับ data access objects เพื่อดึงข้อมูลจากฐานข้อมูล


3
วัตถุค่าไม่ได้เป็นDTO
coderpc

0

Data transfer Object (DTO) อธิบาย“ วัตถุที่นำข้อมูลระหว่างกระบวนการ” (Wikipedia) หรือ“ วัตถุที่ใช้ในการห่อหุ้มข้อมูลและส่งจากระบบย่อยหนึ่งของแอปพลิเคชันไปยังระบบอื่น” (คำตอบของ Stack Overflow)


0

DefN

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

ในทางตรงกันข้ามแบบไดนามิกหรือ "ถุงสมบัติ" แก้ปัญหาของการสร้างแบบจำลองบันทึกข้อมูลเมื่อกระบวนการผลิตถูกสร้างขึ้นที่รันไทม์

The Cvar

DTO สามารถสร้างแบบจำลองด้วยเขตข้อมูลหรือคุณสมบัติ แต่มีคนคิดค้นที่เก็บข้อมูลที่มีประโยชน์มากที่เรียกว่า Cvar มันเป็นการอ้างอิงถึงค่า เมื่อ DTO ถูกสร้างโมเดลด้วยสิ่งที่ฉันเรียกว่าคุณสมบัติการอ้างอิงโมดูลสามารถกำหนดค่าให้ใช้หน่วยความจำฮีปร่วมกันและทำงานร่วมกันได้ สิ่งนี้จะกำจัดการผ่านพารามิเตอร์และการสื่อสาร O2O จากรหัสของคุณ ในคำอื่น ๆDTOs มีคุณสมบัติอ้างอิงให้รหัสเพื่อให้บรรลุศูนย์การมีเพศสัมพันธ์

    class Cvar { ... }

    class Cvar<T> : Cvar
    {
        public T Value { get; set; }
    }

    class MyDTO
    {
        public Cvar<int> X { get; set; }
        public Cvar<int> Y { get; set; }
        public Cvar<string> mutableString { get; set; } // >;)
    }

ที่มา: http://www.powersemantics.com/

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

    // a dynamic DTO
    class CvarRegistry : Dictionary<string, Cvar> { }

ข้อโต้แย้ง

หมายเหตุ: เนื่องจาก Wix ระบุว่าการใช้ DTOs สำหรับการจัดระเบียบพารามิเตอร์เป็น "anti-pattern" ฉันจะให้ความเห็นอย่างมีสิทธิ์

    return View(model);  // MVC disagrees

สถาปัตยกรรมการทำงานร่วมกันของฉันแทนที่รูปแบบการออกแบบ อ้างถึงบทความบนเว็บของฉัน

พารามิเตอร์ช่วยให้สามารถควบคุมเครื่องกรอบสแต็กได้ทันที หากคุณใช้การควบคุมอย่างต่อเนื่องดังนั้นจึงไม่จำเป็นต้องควบคุมทันทีโมดูลของคุณไม่ต้องการพารามิเตอร์ สถาปัตยกรรมของฉันไม่มีเลย การกำหนดค่าระหว่างดำเนินการของเครื่องจักร (วิธีการ) เพิ่มความซับซ้อน แต่ยังให้คุณค่า (ประสิทธิภาพ) เมื่อพารามิเตอร์เป็นประเภทค่า อย่างไรก็ตามพารามิเตอร์ประเภทการอ้างอิงทำให้ผู้บริโภคทำให้แคชหายไปเพื่อรับค่าออกจากฮีปอยู่แล้วดังนั้นเพียงกำหนดคอนซูเมอร์ด้วยคุณสมบัติการอ้างอิง ความจริงจากวิศวกรรมเครื่องกล: การพึ่งพาพารามิเตอร์เป็นชนิดของการเพิ่มประสิทธิภาพก่อนกำหนดเนื่องจากการประมวลผล (การทำส่วนประกอบ) ตัวเองเป็นของเสีย อ้างถึงบทความ W ของฉันสำหรับข้อมูลเพิ่มเติม http://www.powersemantics.com/w.html

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

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

ไม่มีอะไรผิดปกติกับการประมวลผลการสร้างแบบจำลองเป็นกลุ่มของพนักงานสำนักงานที่ไร้ประโยชน์ซึ่งทำงานกับอีเมลโดยไม่มีการติดตามอีเมลยกเว้นงานพิเศษและปวดหัวที่สร้างขึ้นในการจัดการโลจิสติกส์และปัญหาการส่งคืน กระบวนการกระจายแบบจำลองที่ถูกต้องจะแนบเอกสาร (การกำหนดเส้นทางที่ใช้งานอยู่) กับผลิตภัณฑ์ที่อธิบายถึงการดำเนินการที่มาจากและจะไปที่ การเราต์ที่แอ็คทีฟคือสำเนาของการเราต์ซอร์สกระบวนการซึ่งถูกเขียนก่อนกระบวนการเริ่มต้น ในกรณีที่มีข้อบกพร่องหรือการเปลี่ยนแปลงฉุกเฉินอื่น ๆ การเราต์ที่แอ็คทีฟจะถูกแก้ไขเพื่อรวมขั้นตอนการดำเนินการที่จะถูกส่งไป บัญชีนี้สำหรับแรงงานทั้งหมดที่เข้าสู่การผลิต

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