ฉันควรสร้างอินเตอร์เฟสสำหรับวัตถุการถ่ายโอนข้อมูลหรือไม่


19

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

แม้ว่าตัวอย่างของฉันจะเป็นภาษาจาวา แต่ก็ควรใช้กับภาษาอื่นที่มีแนวคิดคล้ายกัน

interface DataTransferObject  {
    String getName();
    void setName(String name);
}

class RealDataTransferObject  implements DataTransferObject {

    String name;
    String getName() {
        return name;
    } 
    void setName(String name) {
        this.name = name;
    }
}

แน่นอนว่านี่เป็นตัวอย่างที่ง่ายในชีวิตจริงอาจมีหลายสาขา

คำตอบ:


24

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

ที่ถูกกล่าวว่าบางครั้งอาจมีเหตุผลที่ดี แต่ในทุกกรณีที่ฉันได้เห็นอินเทอร์เฟซเหล่านี้มีบางส่วนครอบคลุมคุณสมบัติเพียงหนึ่งหรือสองสามที่แบ่งใช้โดยหลายคลาสที่ฉันต้องการใช้ polymporphically โดยไม่ต้องให้ซูเปอร์คลาสทั่วไป ตัวเลือกทั่วไปเป็นIdคุณสมบัติที่ใช้ในการจัดเรียงรีจิสทรีหรือNameคุณสมบัติที่จะแสดงต่อผู้ใช้ แต่มันจะมีประโยชน์ในกรณีใด ๆ ที่คุณต้องการให้บางโค้ดจัดการทุกอย่างที่มี X - เพียงแค่สร้างXSourceอินเทอร์เฟซที่มีเมธอดgetX(และเฉพาะเมื่อจำเป็นsetX)

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

Sidenote: โปรดหลีกเลี่ยงการใช้คำว่า "value object" เพื่ออธิบาย Java beans ด้วย getters และ setters เพียงเล็กน้อยเท่านั้นมันขัดแย้งกับนิยามทั่วไปของobject valueเป็นสิ่งที่ไม่มีตัวตนที่ไม่เปลี่ยนแปลง คำที่ดีกว่าคือDTOหรือคลาสโมเดล - แม้ว่าในกรณีหลังหมายเหตุว่าโมเดลโดเมนโลหิตจางถือว่าเป็นปฏิปักษ์


3
"โมเดลโดเมนโลหิตจางถือเป็นปฏิปักษ์" - โดย Martin Fowler ผู้ซึ่งใน PEAA ยอมรับว่าเขารู้ว่าคนที่ทำงานด้วยวิธีนี้มานานหลายทศวรรษ "ประสบความสำเร็จอย่างมาก" ดังนั้นฉันขอแนะนำให้ลดรูปแบบการต่อต้านให้น้อยลงและชอบที่จะทำงานแบบ Fowler อย่างไรก็ตามคำตอบที่ดี +1
pdr

4
@pdr: ฟาวเลอร์อาจมีคำประกาศเกียรติคุณ แต่เขาไม่เคยมีเพียงคนเดียวที่คิดว่าพวกเขาเป็นปฏิปักษ์ ฉันไม่คิดว่าใครก็ตามที่เข้าใจ OO จริง ๆ คิดว่าเป็นความคิดที่ดีที่จะกำจัดตรรกะเฉพาะโดเมนออกจากโมเดลโดเมน
Michael Borgwardt

ขอบคุณสำหรับการแก้ไขคำศัพท์ DTO เป็นคำที่ฉันมองหาเมื่อคืน แต่จำไม่ได้ว่าชีวิตของฉัน ด้วยการเปลี่ยนชื่อไปรอบ ๆ สิ่งต่าง ๆ ทำให้การออกแบบที่ชาญฉลาดยิ่งขึ้น
Archimedes Trajano

@pdr ฉันคิดว่าวิธีที่ดีที่สุดที่จะกล่าวคือมันเป็นปฏิปักษ์ในบริบทของการเขียนโปรแกรม OO มีกระบวนทัศน์อื่น ๆ อีกมากมายที่คุณสามารถทำได้อย่างสมบูรณ์แบบและคุณสามารถทำงานในภาษา OO ได้สำเร็จ
Daniel B

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

2

การสร้างอินเทอร์เฟซนั้นใช้ได้ แต่ไม่ใช่ตัวอย่างของคุณ คุณควรลบ setter ออกจากอินเทอร์เฟซและมันก็จะโอเค:

interface ValueObject {
  String getName();
};

นี้ช่วยให้การใช้งานที่แตกต่างกันของมันเช่นชื่อสามารถดึงข้อมูลจากฐานข้อมูล ... Setter ควรอยู่ในอินเตอร์เฟซที่แตกต่างกัน


2

อินเทอร์เฟซกำหนดสัญญาระหว่างคลาสที่ใช้อินเทอร์เฟซและไคลเอนต์ของพวกเขา พวกเขาจะใช้เป็นกลไกที่เป็นนามธรรมเพื่อให้ลูกค้าสามารถจัดการ "สิ่งที่มีพฤติกรรมที่กำหนด"

ดังนั้นคำตอบทั่วไปของคำถาม "ฉันควรสร้างและใช้ส่วนต่อประสานนี้หรือไม่?" คือ: ใช่หากคุณสามารถเชื่อมโยงแนวคิด (หนึ่งเดียว) ที่เกี่ยวข้องกับลูกค้าของคุณได้

ตัวอย่างเช่นComparableเป็นอินเทอร์เฟซที่ดีเพราะมันอธิบายได้ว่าสิ่งต่าง ๆ สามารถเปรียบเทียบได้ด้วยวิธีการอย่างใดอย่างหนึ่งและในฐานะลูกค้าที่ฉันสนใจที่จะจัดการกับวัตถุที่เทียบเคียงได้ (เช่นการเรียงลำดับ) contrario, CoolStuffไม่ใช่ส่วนต่อประสานที่ดีถ้าคุณยอมรับว่าวัตถุ cool ไม่มีพฤติกรรมที่เฉพาะเจาะจง (อันที่จริงแล้วคุณสามารถจินตนาการถึงซอฟต์แวร์ที่จัดการกับวัตถุ cool ได้เพราะมันมีพฤติกรรมทั่วไปเช่นbeCoolวิธี).

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

หากสิ่งที่คุณต้องการคือการจัดการกับวัตถุที่มีค่าไม่แน่นอนที่สามารถเข้าถึงได้ด้วยวิธีการสองสามวิธีให้ดูแนวคิดของ Java bean และวิธีที่คุณสามารถบังคับให้คลาสของคุณใช้ระเบียบแบบแผน


2

ดังที่ Michael กล่าวว่าไม่ต้องเพิ่มอินเทอร์เฟซเว้นแต่คุณมีความต้องการเฉพาะ

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


1
อินเทอร์เฟซไม่จำเป็นสำหรับการใช้กรอบการเยาะเย้ยในวัย
Michael Borgwardt

ดูเหมือนว่าคุณกำลังให้การสนับสนุนการจับลิง ฉันลงไปที่ถนนด้วยโมลใน C # และมันก็ไม่สวย ดีกว่าที่จะผ่านในผู้ทำงานร่วมกันของคุณถ้าเป็นไปได้
jhewlett

1
แม้ว่ากรอบการเยาะเย้ยทั้งสองฉันใช้ Mockito และ easyMock ไม่สามารถเยาะเย้ยชั้นเรียนสุดท้ายเมื่อทำให้พวกเขาไม่เปลี่ยนรูป
Archimedes Trajano

1

หากคุณต้องการให้วัตถุนี้มีการตรวจสอบความถูกต้องของเขตข้อมูลบางประเภทในอนาคตคุณควรปิดทับสิ่งเหล่านี้ในระยะแรก


0

'อินเทอร์เฟซสำหรับวัตถุค่า' คือสิ่งที่ฉันใช้เรียกผู้เข้าถึง

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

ปันส่วนบางส่วนสำหรับ accessors (หรือการใช้ค่าโดยตรง) มีดังต่อไปนี้:

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

ฉันแนะนำให้ลดจำนวน accessors และใช้พวกเขาเป็นการส่วนตัวเมื่อคุณคาดหวังว่า setter (setName) จะกลายเป็นสิ่งที่ง่ายกว่าในภายหลัง


0

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

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