คำจำกัดความที่ดีที่สุดสำหรับการพึ่งพาการฉีดคืออะไร?


10

ทุกครั้งที่มีคนมาถึงฉันและขอให้ฉันกำหนด Dependency Injection ตามแนวคิดและอธิบายข้อดีข้อเสียของการใช้ DI ในการออกแบบซอฟต์แวร์ ฉันยอมรับว่าฉันมีปัญหาในการอธิบายแนวคิดของ DI ทุกครั้งที่ฉันต้องบอกพวกเขาเกี่ยวกับประวัติศาสตร์เกี่ยวกับหลักการความรับผิดชอบเดียวองค์ประกอบการสืบทอด ฯลฯ

ใครสามารถช่วยฉันอธิบายวิธีที่ดีที่สุดในการอธิบาย DI สำหรับนักพัฒนา


2
ความท้าทายที่นี่คือมีคำจำกัดความที่ขัดแย้งกันของ DI ฉันใช้ท่าทาง "บริสุทธิ์ DI": ถ้าฉันมีฟังก์ชั่นที่ต้องอาศัยพารามิเตอร์ของมันเพื่อให้ทุกสถานะข้อมูล ฯลฯ ฟังก์ชั่นนั้นใช้ DI ที่อื่น ๆ ที่รุนแรงบางคนจะโต้แย้งว่าไม่มีกรอบ DI ไม่มีการพึ่งพาการฉีด (แม้ว่าพวกเขาจะผิดแน่นอน;) ดังนั้นหากคุณไม่สามารถนิยามคำจำกัดความได้คุณจะไม่สามารถอธิบายได้ว่ามันคืออะไร
David Arno

อย่างที่ฉันเข้าใจนี่ไม่ได้เป็นเพียงปัญหาของฉันเท่านั้น
Tiago Sampaio


1
ที่เกี่ยวข้อง: stackoverflow.com/questions/1638919/…
Liath

ทุกอย่างลงมาที่นี่: ฉีดพึ่งพาเป็นหนึ่งในเทคนิคที่ใช้เพื่อให้เกิดการผกผันพึ่งพา; ทุกสิ่งทุกอย่างเป็นเพียงสิ่งพิเศษที่สร้างขึ้นจากนั้น โปรดทราบว่าในคำสองคำนี้คำว่า "การพึ่งพา" มีความหมายแตกต่างกันเล็กน้อย ในการฉีดพึ่งพามันหมายถึงองค์ประกอบที่รหัสขึ้นอยู่กับ ในการผกผันอ้างอิงมันหมายถึงความสัมพันธ์ (กำกับ) ตัวเอง - หนึ่งที่เราต้องการที่จะกลับ หลังคือเป้าหมายดังนั้นข้อดีและข้อเสียหลักเหมือนกัน รวมถึงข้อกังวลเพิ่มเติมที่เกี่ยวข้องกับการใช้งานจริงเช่นการจัดการอายุการใช้งานวัตถุ
Filip Milovanović

คำตอบ:


22

พึ่งพาการฉีดเป็นชื่อที่น่ากลัว(IMO) 1สำหรับแนวคิดที่ค่อนข้างตรงไปตรง นี่คือตัวอย่าง:

  1. คุณมีเมธอด (หรือคลาสพร้อมเมธอด) ที่ทำ X (เช่นดึงข้อมูลจากฐานข้อมูล)
  2. ในฐานะส่วนหนึ่งของการทำ X วิธีดังกล่าวจะสร้างและจัดการทรัพยากรภายใน (เช่นกDbContext) ทรัพยากรภายในนี้คือสิ่งที่เรียกว่าการพึ่งพา
  3. คุณลบการสร้างและการจัดการทรัพยากร (เช่นDbContext) ออกจากวิธีการและทำให้เป็นความรับผิดชอบของผู้โทรเพื่อให้ทรัพยากรนี้ (เป็นพารามิเตอร์วิธีการหรือตามการเริ่มชั้นเรียน)
  4. ตอนนี้คุณกำลังทำการฉีดพึ่งพา


[1] : ผมมาจากพื้นหลังในระดับต่ำกว่าและเอาฉันเดือนที่จะนั่งลงและเรียนรู้การพึ่งพาการฉีดเพราะชื่อที่แสดงถึงมันจะเป็นสิ่งที่มีความซับซ้อนมากขึ้นเช่นDLL ฉีด ความจริงที่ว่า Visual Studio (และเราเป็นผู้พัฒนาโดยทั่วไป) หมายถึงไลบรารี. NET (DLLs หรือแอสเซมบลี ) ที่โครงการขึ้นอยู่กับว่าการพึ่งพาไม่ได้ช่วยเลย มีสิ่งแม้เช่นเป็นพึ่งพาวอล์คเกอร์ (depends.exe)


[แก้ไข] ฉันคิดว่าบางรหัสการสาธิตจะมีประโยชน์สำหรับบางคนดังนั้นนี่คือรหัส (ใน C #)

โดยไม่ต้องพึ่งพาการฉีด:

public class Repository : IDisposable
{
    protected DbContext Context { get; }

    public Repository()
    {
        Context = new DbContext("name=MyEntities");
    }

    public void Dispose()
    {
        Context.Dispose();
    }
}

ผู้บริโภคของคุณจะทำสิ่งที่ชอบ:

using ( var repository = new Repository() )
{
    // work
}

ชั้นเรียนเดียวกันที่นำมาใช้กับรูปแบบการฉีดพึ่งพาจะเป็นเช่นนี้:

public class RepositoryWithDI
{
    protected DbContext Context { get; }

    public RepositoryWithDI(DbContext context)
    {
        Context = context;
    }
}

ขณะนี้เป็นความรับผิดชอบของผู้โทรที่จะยกตัวอย่าง a DbContextและ pass (errm, inject ) ให้กับชั้นเรียนของคุณ:

using ( var context = new DbContext("name=MyEntities") )
{
    var repository = new RepositoryWithDI(context);

    // work
}

3
สิ่งนี้ควรเพิ่มใน Wikipedia
Evorlor

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

@Fabio มันอาจจะเป็น (ในกรณีนั้นความรับผิดชอบของผู้โทรจะให้ทรัพยากรที่ถูกสร้างอินสแตนซ์เมื่อเริ่มต้นแอปพลิเคชันกับวิธีการ / คลาสที่ถูกเรียก) ในตัวอย่างของฉันมันไม่ได้เป็นอย่างนั้นเพราะนั่นไม่ใช่ข้อกำหนดในการอธิบายแนวคิดของการฉีด .
Marc.2377

5

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

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

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

ดังนั้นคุณจึงกำหนดกฎใหม่: ลูกค้านำขนมปังของตัวเอง คุณไม่ได้จัดหาขนมปังเองอีกต่อไป นี่เป็นสถานการณ์แบบ win-win: ลูกค้าจะได้รับขนมปังที่แน่นอนที่พวกเขาต้องการและคุณไม่ต้องกังวลกับการจัดหาขนมปังที่คุณไม่สนใจอีกต่อไป หลังจากทั้งหมดคุณเป็นผู้ผลิตแซนวิชไม่ใช่คนทำขนมปัง

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

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


1
ผมชอบแบบนี้ แต่ OP ที่กำลังมองหาคำอธิบายสำหรับนักพัฒนา การเริ่มต้นที่เป็นนามธรรมนั้นดี แต่ไม่ช้าก็เร็วมันจะต้องมีตัวอย่างชีวิตจริง
Robbie Dee

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

2
คุณแน่นอน แต่ฉันไม่สามารถช่วยได้ แต่คิดว่าฉันต้องการตัวอย่างที่จับต้องได้ - เช่นไม่มีระบบไฟล์จริงหรือฐานข้อมูลเพื่อกระตุ้นความอยากอาหารของฉัน แต่อาจเป็นเพียงมุมมองนักพัฒนาที่แคบของฉัน :)
Robbie ดี

1

คำตอบง่ายๆที่:

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

.Net Core เป็นตัวอย่างที่ดีที่คุณสามารถให้ได้เนื่องจากกรอบการทำงานนี้ใช้การฉีดที่ต้องพึ่งพาอาศัยกันจำนวนมาก โดยทั่วไปบริการที่คุณต้องการฉีดจะอยู่ที่startup.csไฟล์

แน่นอนว่านักเรียนควรตระหนักถึงแนวคิดบางอย่างเช่นความหลากหลายรูปแบบส่วนต่อประสานและหลักการออกแบบ OOP


0

มีปุยและบังเกอร์จำนวนมากอยู่รอบ ๆ สิ่งที่เป็นสาระสำคัญแนวคิดง่าย ๆ

นอกจากนี้ยังง่ายมากที่จะจมอยู่กับ " กรอบที่ฉันควรใช้ " เมื่อคุณสามารถทำได้ง่ายๆในรหัส

นี่คือคำจำกัดความที่ฉันใช้เป็นการส่วนตัว:

พฤติกรรมที่กำหนด X ที่มีการขึ้นต่อกันของ Y การพึ่งพาการฉีดเกี่ยวข้องกับสิ่งอำนวยความสะดวกในการจัดหา Y ใด ๆ ที่เป็นไปตามเกณฑ์สำหรับการเป็นตัวอย่างของ Y แม้ว่าคุณจะไม่มี

ตัวอย่างบางส่วนอาจเป็นที่ที่ Y เป็นระบบไฟล์หรือการเชื่อมต่อฐานข้อมูล

เฟรมเวิร์กเช่นmoqอนุญาตให้กำหนดเป็นสองเท่า (ทำท่าเวอร์ชัน Y) โดยใช้อินเตอร์เฟสดังนั้นจึงสามารถฉีดอินสแตนซ์ของ Y ได้โดยที่ Y เป็นตัวอย่างเช่นการเชื่อมต่อฐานข้อมูล

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


0

เราจัดเตรียมพฤติกรรมของฟังก์ชันที่รันไทม์ผ่านวิธีการแทรกพฤติกรรมนั้นลงในฟังก์ชันผ่านพารามิเตอร์

รูปแบบกลยุทธ์เป็นตัวอย่างที่ดีของการฉีดพึ่งพา


0

ในการทำสิ่งนี้ถูกต้องอันดับแรกเราต้องนิยามการพึ่งพาและการฉีด

  • การพึ่งพา: ทรัพยากรใด ๆ ที่การดำเนินการต้องการ
  • การฉีด: การส่งผ่านทรัพยากรนั้นไปยังการดำเนินการโดยปกติแล้วจะเป็นอาร์กิวเมนต์ไปยังวิธีการ

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

สมมติว่าคุณใช้คุณสมบัติแทนและคุณตั้งชื่อพวกเขาเป็น A และ B หากคุณเปลี่ยนชื่อเป็น Op1 และ Op2 คุณจะต้องทำลายเมธอด Add หรือ IDE ของคุณจะอัปเดตชื่อทั้งหมดให้กับคุณจุดคือวิธีที่จำเป็นต้องได้รับการอัปเดตเช่นกันเนื่องจากมีการอ้างอิงกับทรัพยากรภายนอก

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

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

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

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