การตั้งคำถามหนึ่งในข้อโต้แย้งสำหรับกรอบการฉีดพึ่งพา: ทำไมการสร้างกราฟวัตถุอย่างหนัก


13

กรอบการฉีดที่พึ่งพาเช่น Google Guice ให้แรงจูงใจต่อการใช้งาน (ที่มา ):

ในการสร้างวัตถุคุณต้องสร้างการขึ้นต่อกันก่อน แต่ในการสร้างการพึ่งพาแต่ละครั้งคุณจำเป็นต้องมีการพึ่งพาและอื่น ๆ ดังนั้นเมื่อคุณสร้างวัตถุคุณจำเป็นต้องสร้างกราฟวัตถุ

การสร้างกราฟวัตถุด้วยมือนั้นเป็นเรื่องยากสำหรับแรงงาน (... ) และทำให้การทดสอบเป็นเรื่องยาก

แต่ฉันไม่ได้ซื้ออาร์กิวเมนต์นี้: แม้จะไม่มีกรอบการฉีดพึ่งพาฉันสามารถเขียนชั้นเรียนซึ่งทั้งง่ายต่อการ instantiate และสะดวกในการทดสอบ เช่นตัวอย่างจากหน้าแรงจูงใจของ Guiceสามารถเขียนใหม่ด้วยวิธีต่อไปนี้:

class BillingService
{
    private final CreditCardProcessor processor;
    private final TransactionLog transactionLog;

    // constructor for tests, taking all collaborators as parameters
    BillingService(CreditCardProcessor processor, TransactionLog transactionLog)
    {
        this.processor = processor;
        this.transactionLog = transactionLog;
    }

    // constructor for production, calling the (productive) constructors of the collaborators
    public BillingService()
    {
        this(new PaypalCreditCardProcessor(), new DatabaseTransactionLog());
    }

    public Receipt chargeOrder(PizzaOrder order, CreditCard creditCard)
    {
        ...
    }
}

ดังนั้นอาจมีข้อโต้แย้งอื่น ๆ สำหรับกรอบการฉีดพึ่งพา ( ซึ่งอยู่นอกขอบเขตสำหรับคำถามนี้ !) แต่การสร้างกราฟวัตถุที่ทดสอบได้ง่ายไม่ใช่หนึ่งในนั้นใช่ไหม


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

โปรดทราบว่าฉันไม่ได้มองหาข้อได้เปรียบอื่น ๆ ของการฉีดที่ต้องพึ่งพา - ฉันเพียง แต่สนใจที่จะเข้าใจว่า "การสร้างอินสแตนซ์ของวัตถุนั้นทำได้ยากโดยไม่ต้องอาศัยการฉีดที่พึ่งพา"
oberlies

คำตอบนี้ดูเหมือนจะเป็นตัวอย่างที่ดีว่าทำไมคุณถึงต้องการคอนเทนเนอร์แบบกราฟของวัตถุของคุณ (ในระยะสั้นคุณไม่ได้คิดใหญ่พอโดยใช้เพียงวัตถุ 3 ชิ้น)
Izkata

@ อิซกาตะไม่นี่ไม่ใช่เรื่องของขนาด ด้วยวิธีการอธิบายรหัสจากโพสต์ที่new ShippingService()ก็จะเป็น
oberlies

@oberlies ยังคงเป็น; จากนั้นคุณต้องไปขุดในคำจำกัดความของคลาส 9 เพื่อพิจารณาว่าคลาสใดที่จะถูกใช้สำหรับ ShippingService นั้นแทนที่จะเป็นหนึ่งแห่ง
Izkata

คำตอบ:


12

มีการถกเถียงกันอย่างต่อเนื่องเกี่ยวกับวิธีที่ดีที่สุดในการฉีดการพึ่งพา

  • การตัดแบบสปริงดั้งเดิมนั้นทำให้วัตถุเป็นชิ้นเรียบแล้วฉีดการพึ่งพาผ่านวิธีเซ็ตเตอร์

  • แต่จากนั้นผู้คนจำนวนมากยืนยันว่าการฉีดการพึ่งพาผ่านพารามิเตอร์คอนสตรัคเตอร์เป็นวิธีที่ถูกต้องในการทำ

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

ดังนั้นคอนสตรัคเตอร์แรกของคุณจึงสอดคล้องกับวิธีที่สองในการฉีดพึ่งพา ช่วยให้คุณทำสิ่งที่ดีเช่นการฉีด mocks สำหรับการทดสอบ

แต่ตัวสร้างไม่มีอาร์กิวเมนต์มีปัญหานี้ เนื่องจากเป็นการยกระดับชั้นเรียนการดำเนินการให้รวดเร็วขึ้นPaypalCreditCardProcessorและDatabaseTransactionLogจะสร้างการพึ่งพาอย่างหนักและรวบรวมใน PayPal และฐานข้อมูล มันจะรับผิดชอบในการสร้างและกำหนดค่าทรีการพึ่งพาทั้งหมดให้ถูกต้อง

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

  • ไอเท็มเหล่านั้นจำนวนมากในแผนผังการพึ่งพาจะมีความโปร่งใส แต่ส่วนมากจะต้องมีอินสแตนซ์ ราคาต่อรองคุณจะไม่สามารถยกตัวอย่างกPaypalCreditCardProcessor.

  • นอกเหนือจากการสร้างอินสแตนซ์วัตถุแต่ละชิ้นจะต้องการคุณสมบัติที่ใช้จากการกำหนดค่า

หากคุณมีเพียงการพึ่งพาส่วนต่อประสานและอนุญาตให้โรงงานภายนอกสร้างและฉีดการพึ่งพาพวกเขาจะตัดการพึ่งพาต้นกำเนิด PayPal ทั้งหมดและความซับซ้อนของรหัสของคุณจะหยุดที่ส่วนต่อประสาน

มีประโยชน์อื่น ๆ เช่นการระบุคลาสการใช้งานที่ในการกำหนดค่า (เช่นที่รันไทม์มากกว่าเวลารวบรวม) หรือมีข้อกำหนดการพึ่งพาแบบไดนามิกมากขึ้นที่แตกต่างกันพูดตามสภาพแวดล้อม (ทดสอบการรวมการผลิต)

ตัวอย่างเช่นสมมติว่า PayPalProcessor มีวัตถุที่ต้องพึ่งพา 3 รายการและการอ้างอิงแต่ละรายการนั้นมีอีกสองรายการ และวัตถุเหล่านั้นทั้งหมดจะต้องดึงคุณสมบัติจากการกำหนดค่า รหัสตามที่เป็นจะรับผิดชอบในการสร้างสิ่งที่ออกการตั้งค่าคุณสมบัติจากการกำหนดค่า ฯลฯ - ทั้งหมดกังวลว่ากรอบ DI จะดูแล

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

...

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

นั่นคือการแยกข้อกังวลออกเพื่อให้ชั้นของฉันสามารถทำสิ่งนั้นได้และชั้นโรงงานต้องรับผิดชอบในการสร้างและกำหนดค่าสิ่งของ

ไม่ใช่วิธีที่จำเป็น แต่เป็น FWIW

...

โดยทั่วไปรูปแบบ DI / อินเตอร์เฟสจะลดความซับซ้อนของรหัสของคุณโดยทำสองสิ่ง:

  • สรุปการพึ่งพาดาวน์สตรีมลงในอินเตอร์เฟส

  • "การยก" การพึ่งพาต้นน้ำออกจากรหัสของคุณและลงในคอนเทนเนอร์บางประเภท

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


รหัสจะรับผิดชอบในการสร้างสิ่งต่าง ๆ ทั้งหมด - คลาสจะรับผิดชอบเฉพาะการรู้ว่าการใช้งานร่วมกันของมันคืออะไร ไม่จำเป็นต้องรู้ว่าผู้ทำงานร่วมกันเหล่านี้ต้องการอะไรในทางกลับกัน ดังนั้นนี่ไม่มาก
oberlies

1
แต่ถ้าตัวสร้างโพรเซสของ PayPal มี 2 อาร์กิวเมนต์มันจะมาจากไหน?
Rob

มันไม่ได้ เช่นเดียวกับ BillingService PayPalProcessor มีคอนสตรัคเตอร์แบบ zero-args ซึ่งสร้างผู้ทำงานร่วมกันที่ต้องการ
oberlies

สรุปการพึ่งพาดาวน์สตรีมลงในอินเตอร์เฟส - โค้ดตัวอย่างทำสิ่งนี้ด้วย ฟิลด์ตัวประมวลผลเป็นประเภท CreditCardProcessor ไม่ใช่ประเภทการใช้งาน
oberlies

2
@oberlies: ตัวอย่างโค้ดของคุณเลาะเลียบไประหว่างสองรูปแบบลักษณะอาร์กิวเมนต์ของตัวสร้างและรูปแบบที่สร้างได้แบบ zero-args การเข้าใจผิดคือการที่ไม่สามารถสร้างสิ่งที่เป็นศูนย์ได้เสมอไป ความสวยงามของ DI หรือ Factory คือพวกมันยอมให้วัตถุถูกสร้างด้วยสิ่งที่ดูเหมือนว่าเป็นตัวสร้างศูนย์
ร. ว.

4
  1. เมื่อคุณว่ายน้ำที่ปลายสุดตื้นของสระว่ายน้ำทุกอย่าง "ง่ายและสะดวกสบาย" เมื่อคุณผ่านวัตถุโหลหรือมากกว่านั้นไปมันจะไม่สะดวกอีกต่อไป
  2. ในตัวอย่างของคุณคุณผูกพันกระบวนการเรียกเก็บเงินของคุณตลอดไปและวันกับ PayPal สมมติว่าคุณต้องการใช้ตัวประมวลผลบัตรเครดิตอื่นหรือไม่? สมมติว่าคุณต้องการสร้างตัวประมวลผลบัตรเครดิตแบบพิเศษที่มีข้อ จำกัด ในเครือข่าย หรือคุณต้องการทดสอบการจัดการหมายเลขบัตรเครดิต? คุณได้สร้างโค้ดที่ไม่สามารถพกพาได้: "เขียนครั้งเดียวใช้เพียงครั้งเดียวเพราะมันขึ้นอยู่กับกราฟวัตถุเฉพาะที่มันถูกออกแบบมา"

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

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


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

1
ผมคิดว่าถ้าคุณลดคำถามที่จะ "สร้างกราฟวัตถุ ..." แล้วมันจะตรงไปตรงมา ประเด็นของฉันคือ DI ระบุปัญหาที่คุณไม่เคยจัดการกับกราฟวัตถุเพียงอันเดียว คุณจัดการกับครอบครัวของพวกเขา
BobDalgleish

อันที่จริงเพียงแค่การสร้างกราฟวัตถุหนึ่งแล้วสามารถหากินถ้าทำงานร่วมกันที่ใช้ร่วมกัน
oberlies

4

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

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


1
แต่ต้นไม้ที่พึ่งพาต้องเป็นต้นไม้ในความหมายทางทฤษฎีกราฟ มิฉะนั้นคุณจะมีวัฏจักรซึ่งไม่น่าพอใจ
Xion

1
@Xion กราฟอ้างอิงต้องเป็นกราฟแบบวงกลมกำกับ ไม่มีข้อกำหนดว่าจะมีเพียงหนึ่งเส้นทางเท่านั้นระหว่างสองโหนดเหมือนในต้นไม้
oberlies

@Xion: ไม่จำเป็นต้อง พิจารณา a UnitOfWorkซึ่งมีที่เก็บเอกพจน์DbContextและหลายที่ ที่เก็บทั้งหมดเหล่านี้ควรใช้DbContextวัตถุเดียวกัน ด้วย OP ของการเสนอ "การสร้างอินสแตนซ์ด้วยตนเอง" ทำให้ไม่สามารถทำได้
Flater

1

ฉันไม่ได้ใช้ Google Guice แต่ฉันใช้เวลานานในการโยกย้ายแอปพลิเคชัน N-tier เก่าใน. Net ไปยังสถาปัตยกรรม IoC เช่น Onion Layer ที่ขึ้นอยู่กับ Dependency Injection เพื่อแยกสิ่งต่าง ๆ

ทำไมต้องพึ่งพาการฉีด?

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

ทำไมฉันต้องกังวลเกี่ยวกับการแต่งงานกันทั้งหมด

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

ทำไมฉันต้องใช้การฉีดอ้างอิงเพื่อการทดสอบที่เหมาะสม

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

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

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

แนวคิดคือคุณต้องการตรวจสอบให้แน่ใจว่าการทำงานทั้งหมดนั้นใช้งานได้หากไม่ต้องการทราบรหัสที่แน่นอนที่ไม่ทำงาน

สิ่งนี้สามารถทำได้โดยไม่ต้องพึ่งพาการฉีด แต่โดยปกติเมื่อโครงการของคุณเติบโตขึ้นมันจะยุ่งยากมากขึ้นเรื่อย ๆ โดยไม่ต้องพึ่งพาการฉีดพึ่งพา (คิดเสมอว่าโครงการของคุณจะเติบโต! จะดีกว่าหากมีการฝึกฝนทักษะที่มีประโยชน์โดยไม่จำเป็นกว่าการหาโครงการที่เพิ่มขึ้นอย่างรวดเร็วและต้องมีการปรับโครงสร้างและการรื้อปรับระบบอย่างจริงจังหลังจากสิ่งต่าง ๆ เริ่มหมดไป)


1
การทดสอบการเขียนโดยใช้ส่วนใหญ่ แต่ไม่ใช่กราฟการพึ่งพาทั้งหมดในความเป็นจริงเป็นข้อโต้แย้งที่ดีสำหรับ DI
oberlies

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

0

ดังที่ฉันพูดถึงในคำตอบอื่นปัญหาของที่นี่คือคุณต้องการให้คลาสAขึ้นอยู่กับคลาสที่Bไม่มีการเข้ารหัสอย่างหนักซึ่งคลาสBใดที่ใช้เป็นซอร์สโค้ดของ A. สิ่งนี้เป็นไปไม่ได้ใน Java และ C # เพราะวิธีเดียวในการนำเข้าคลาส คือการอ้างถึงโดยใช้ชื่อที่ไม่ซ้ำกันทั่วโลก

การใช้อินเทอร์เฟซคุณสามารถแก้ปัญหาการพึ่งพาคลาสฮาร์ดโค้ด แต่คุณยังต้องใช้อินสแตนซ์ของอินเทอร์เฟซและคุณไม่สามารถเรียกคอนสตรัคเตอร์ได้ ที่สามารถสร้างการพึ่งพาของมันผลักดันความรับผิดชอบนั้นให้คนอื่น และการพึ่งพาของมันกำลังทำสิ่งเดียวกัน ดังนั้นตอนนี้ทุกครั้งที่คุณต้องการอินสแตนซ์ของคลาสที่คุณสร้างต้นไม้อ้างอิงทั้งหมดด้วยตนเองในขณะที่ในกรณีที่คลาส A ขึ้นอยู่กับ B โดยตรงคุณสามารถโทรnew A()และรับสายคอนสตรัคnew B()เตอร์นั้นได้

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


0

ฉันคิดว่านี่เป็นความเข้าใจผิดครั้งใหญ่ที่นี่

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

คอนสตรัคนี้:

BillingService(CreditCardProcessor processor, TransactionLog transactionLog)
{
    this.processor = processor;
    this.transactionLog = transactionLog;
}

ใช้การฉีดพึ่งพาแล้ว คุณเพียงแค่บอกว่าการใช้ DI นั้นง่าย

ปัญหาที่ Guice แก้ได้คือการใช้ Constructor นั้นตอนนี้คุณต้องมีรหัส Constructor กราฟวัตถุอยู่ที่ไหนสักแห่งโดยผ่านวัตถุ instantiated แล้วเป็นอาร์กิวเมนต์ของ Constructor นั้น Guice ช่วยให้คุณมีที่เดียวที่คุณสามารถกำหนดค่าคลาสการใช้งานจริงที่ตรงกับที่CreditCardProcessorและ TransactionLogส่วนต่อประสาน หลังจากการกำหนดค่านั้นทุกครั้งที่คุณสร้างBillingServiceโดยใช้ Guice คลาสเหล่านั้นจะถูกส่งผ่านไปยังตัวสร้างโดยอัตโนมัติ

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

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