แรงจูงใจที่อยู่เบื้องหลังคำอธิบายประกอบ @ImplementedBy ใน Guice คืออะไร


10

ฉันเพิ่งอ่านเกี่ยวกับ@ImplementedByคำอธิบายประกอบที่มีอยู่ในGoogle Guice อนุญาตให้โปรแกรมเมอร์ระบุการเชื่อมโยงระหว่างอินเตอร์เฟสและการนำไปใช้เพื่อใช้ในอนาคตในการฉีดพึ่งพา มันเป็นตัวอย่างของหนึ่งเพียงในเวลาที่มีผลผูกพัน

ฉันค่อนข้างคุ้นเคยกับการกำหนดการผูกอย่างชัดเจนในโมดูลของฉันโดยใช้ไวยากรณ์ต่อไปนี้:

bind(SomeInterface.class).to(SomeInterfaceImplementation.class);

ตามเอกสารนี้เทียบเท่ากับการใช้@ImplementedByคำอธิบายประกอบต่อไปนี้:

@ImplementedBy(SomeInterfaceImplementation.class)
public interface SomeInterface {
    //method declarations
}

กำไรเดียวที่ฉันเห็นที่นี่คือรหัสสั้นลงเล็กน้อย ในเวลาเดียวกันวิธีการนี้มีข้อเสียเปรียบชี้ให้เห็นอย่างถูกต้องโดยเอกสารเดียวกัน:

ใช้@ImplementedByอย่างระมัดระวัง มันเพิ่มการพึ่งพาเวลารวบรวมจากอินเทอร์เฟซเพื่อการใช้งาน

การพึ่งพาดังกล่าวอาจไม่เป็นปัญหาในหลายกรณี แต่โดยส่วนตัวแล้วฉันเห็นว่ามันเป็นกลิ่นรหัส

กรณีการใช้งานใดที่ทำให้การเพิ่มความคิดเห็นมี@ImplementedByค่าควรใช้

วิธีหนึ่งที่เป็นไปได้คือการใช้มันในโค้ดของไลบรารีหรือกรอบงาน ดังที่อธิบายไว้ในเอกสารคำอธิบายประกอบสามารถจัดเตรียมการโยงดีฟอลต์ได้ง่าย ๆ

หากประเภทอยู่ในทั้งสองbind()คำสั่ง (เป็นอาร์กิวเมนต์แรก) และมี@ImplementedByคำอธิบายประกอบคำbind()สั่งจะถูกนำมาใช้ คำอธิบายประกอบแนะนำการใช้งานเริ่มต้นที่สามารถแทนที่ด้วยการผูก

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

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


2
ที่เกี่ยวข้องอาจเป็นคำถามซ้ำกัน (แม้ว่าชื่อของคุณจะชัดเจนกว่า): @ImplementedBy เป็นความชั่วร้ายของ Guice หรือไม่?
Jeff Bowman

ไม่ซ้ำกันอย่างเข้มงวด แต่มีการอภิปรายที่น่าสนใจเกี่ยวกับเรื่องนี้ที่นี่: stackoverflow.com/questions/6197178/ …
Richard Vodden

คำตอบ:


8

ผมคิดว่าอันตรายที่นี่คือการใช้เพียง@ImplementedByคำอธิบายประกอบ ใช้อย่างเหมาะสมร่วมกับbind()คำสั่งในโมดูลของคุณและอื่น ๆ มันก็โอเค

การเริ่มต้นใช้งานนั้นดีมากสำหรับการทดสอบ คุณไม่จำเป็นต้องกำหนดการฉีดจำลองอย่างชัดเจนทุกครั้งที่คุณทำการทดสอบคลาสที่มีการพึ่งพาจำนวนมากหรือถ้าคุณมีคลาสที่มีหลายสิ่งที่ต้องพึ่งพา (ดังนั้นคุณต้องกำหนดจำลองทุกครั้ง )

ตัวอย่างเช่นคุณอาจมีคลาส:

@ImplementedBy(NoOpDataService.class)
interface DataService {
    Map<String, MyPOJO> getData();
}

จากนั้นNoOpDataServiceคือ:

class NoOpDataService implements DataService {
    @Override
    public Map<String, MyPOJO> getData() {
        return Collections.emptyMap();
    }
}

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

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


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