ภาชนะบรรจุ IOC ทำลายหลักการ OOP


51

วัตถุประสงค์ของ IOC Containers คืออะไร? เหตุผลที่รวมกันสามารถทำให้เป็นดังต่อไปนี้:

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

ไม่มีวิธี OOP / SOLID ในการดำเนินการนี้และมีรหัสสวยมาก

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

ตู้ IOC ทำลายหลักการต่อไปนี้หรือไม่? นี่เป็นคำถามจริงเนื่องจากฉันมีความเข้าใจที่ดี แต่มีความรู้สึกว่ามีคนอื่นมีความเข้าใจที่ดีขึ้น:

  1. การควบคุมขอบเขต ขอบเขตคือเหตุผลสำหรับเกือบทุกการตัดสินใจของฉันในการออกแบบรหัสของฉัน บล็อกท้องถิ่นโมดูลคงที่ / ทั่วโลก ขอบเขตควรชัดเจนมากที่สุดเท่าที่ระดับบล็อกและน้อยที่สุดที่คงที่ที่สุด คุณควรเห็นการประกาศการสร้างอินสแตนซ์และการสิ้นสุดวงจรชีวิต ฉันเชื่อมั่นในภาษาและ GC ในการจัดการขอบเขตตราบใดที่ฉันชัดเจนด้วย จากการวิจัยของฉันฉันพบว่า IOC Containers ตั้งค่าการพึ่งพาส่วนใหญ่หรือทั้งหมดเป็นแบบคงที่และควบคุมพวกมันผ่านการใช้งาน AOP เบื้องหลัง ดังนั้นจึงไม่มีอะไรโปร่งใส
  2. encapsulation จุดประสงค์ของการห่อหุ้มคืออะไร? ทำไมเราควรรักษาสมาชิกส่วนตัวเอาไว้? ด้วยเหตุผลที่ปฏิบัติได้จริงมันคือผู้ดำเนินการของ API ของเราไม่สามารถทำลายการใช้งานได้โดยการเปลี่ยนสถานะ (ซึ่งควรได้รับการจัดการโดยเจ้าของคลาส) แต่ด้วยเหตุผลด้านความปลอดภัยมันจึงไม่สามารถเกิดการฉีดขึ้นมาได้ทันที่รัฐสมาชิกของเราและหลีกเลี่ยงการตรวจสอบและควบคุมชั้นเรียน ดังนั้นสิ่งใด (กรอบการเยาะเย้ยกรอบหรือกรอบ IOC) อย่างใดที่ฉีดรหัสก่อนที่จะรวบรวมเวลาเพื่อให้การเข้าถึงจากภายนอกให้กับสมาชิกส่วนตัวมีขนาดใหญ่มาก
  3. หลักการ Single รับผิดชอบ บนพื้นผิวภาชนะบรรจุของ IOC ดูเหมือนจะทำให้ทุกอย่างสะอาดขึ้น แต่ลองจินตนาการว่าคุณจะทำสิ่งเดียวกันให้สำเร็จได้อย่างไรโดยไม่ต้องมีกรอบตัวช่วย คุณจะมีคอนสตรัคเตอร์ที่มีการอ้างอิงเป็นโหลหรือมากกว่านั้นซึ่งไม่ได้แปลว่าครอบคลุมด้วยตู้คอนเทนเนอร์ IOC มันเป็นสิ่งที่ดี! มันเป็นสัญญาณที่บ่งบอกถึงรหัสของคุณอีกครั้งและติดตาม SRP
  4. เปิด / ปิด เช่นเดียวกับ SRP ไม่ใช่ Class-Only (ฉันใช้ SRP ลงไปที่บรรทัดความรับผิดชอบเดี่ยวและวิธีการเพียงอย่างเดียว) Open / Closed ไม่ได้เป็นเพียงทฤษฎีระดับสูงเท่านั้นที่จะไม่เปลี่ยนรหัสของคลาส เป็นการฝึกทำความเข้าใจเกี่ยวกับการกำหนดค่าโปรแกรมของคุณและควบคุมสิ่งที่ได้รับการเปลี่ยนแปลงและสิ่งที่เพิ่มขึ้น ภาชนะบรรจุ IOC สามารถเปลี่ยนวิธีการทำงานของชั้นเรียนของคุณทั้งหมดบางส่วนเพราะ:

    • รหัสหลักไม่ได้ทำการตัดสินใจของการสลับการพึ่งพาการกำหนดค่ากรอบคือ

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

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

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

ฉันสามารถเชื่อถือ C # และ. NET GC เพื่อทำสิ่งที่ฉันคาดหวัง แต่ฉันไม่สามารถไว้วางใจแบบเดียวกันนี้ได้ในเครื่องมือของบุคคลที่สามซึ่งกำลังเปลี่ยนรหัสที่คอมไพล์ของฉันเพื่อแก้ไขปัญหากับสิ่งที่ฉันไม่สามารถทำได้ด้วยตนเอง

EG: Entity Framework และ ORM อื่น ๆ สร้างวัตถุที่มีการพิมพ์อย่างมากและแมปไปยังเอนทิตีฐานข้อมูลรวมถึงมีฟังก์ชั่นพื้นฐานจานจานหม้อไอน้ำเพื่อดำเนินการ CRUD ทุกคนสามารถสร้าง ORM ของตนเองและทำตามหลักการ OOP / SOLID ต่อไปได้ด้วยตนเอง แต่กรอบเหล่านั้นช่วยเราได้ดังนั้นเราจึงไม่ต้องคิดค้นวงล้อใหม่ทุกครั้ง ในขณะที่ IOC ดูเหมือนว่าช่วยให้เราทำงานโดยมีหลักการ OOP / SOLID และครอบคลุมมัน


13
+1 ความสัมพันธ์ระหว่างIOCและExplicitness of codeเป็นสิ่งที่ฉันมีปัญหา แมนนวล DI สามารถกลายเป็นงานที่น่าเบื่อได้ง่าย แต่อย่างน้อยมันก็ทำให้การไหลของโปรแกรมชัดเจนขึ้นเองในที่เดียว - "คุณได้สิ่งที่คุณเห็นคุณเห็นว่าคุณได้อะไร" ในขณะที่การผูกและการประกาศคอนเทนเนอร์ของ IOC สามารถกลายเป็นโปรแกรมคู่ขนานที่ซ่อนอยู่ได้อย่างง่ายดาย
Eugene Podskal

6
นี่เป็นคำถามได้อย่างไร
สตีเฟ่น

8
ดูเหมือนว่าจะเป็นโพสต์ในบล็อกมากกว่าคำถาม
Bart van Ingen Schenau

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

3
@ BenAaronson ขอบคุณเบ็น ฉันพยายามสื่อสารสิ่งที่เรียนรู้ผ่านการวิจัยของฉันและรับคำตอบเกี่ยวกับธรรมชาติของ IOC Containers จากการวิจัยของฉันฉันพบว่าหลักการเหล่านี้ขาด คำตอบที่ดีที่สุดสำหรับคำถามของฉันจะยืนยันหรือปฏิเสธว่าคอนเทนเนอร์ IOC สามารถทำสิ่งที่เราไม่สามารถทำได้ด้วยตนเองโดยไม่ทำลายหลักการ OOP / SOLID เนื่องจากความคิดเห็นที่ยอดเยี่ยมของคุณฉันได้สร้างคำถามของฉันอีกครั้งด้วยตัวอย่างเพิ่มเติม
Suamere

คำตอบ:


35

ฉันจะไปถึงจุดที่คุณตัวเลข แต่แรกมีสิ่งที่คุณควรจะระมัดระวังมาก: ไม่ conflate วิธีการที่ผู้บริโภคใช้ห้องสมุดที่มีวิธีการที่ห้องสมุดมีการดำเนินการ ตัวอย่างที่ดีของสิ่งนี้คือ Entity Framework (ซึ่งคุณอ้างว่าเป็นไลบรารีที่ดี) และ MVC ของ ASP.NET ทั้งสองอย่างนี้ทำสิ่งที่น่ากลัวมากภายใต้ประทุนด้วยตัวอย่างเช่นการสะท้อนซึ่งจะไม่ถือว่าเป็นการออกแบบที่ดีอย่างแน่นอนถ้าคุณแพร่กระจายผ่านรหัสประจำวัน

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

ดังนั้นเพื่อผ่านจุด:

  1. ทันทีที่เราไปถึงสิ่งที่ฉันสามารถสันนิษฐานได้ว่าเป็นตัวอย่างของข้างต้น คุณบอกว่าคอนเทนเนอร์ IOC ตั้งค่าการพึ่งพาส่วนใหญ่เป็นแบบคงที่ บางทีรายละเอียดการนำไปปฏิบัติบางอย่างเกี่ยวกับวิธีการทำงานของพวกเขารวมถึงที่เก็บข้อมูลแบบสแตติก (แม้ว่าพวกเขามีแนวโน้มที่จะมีอินสแตนซ์ของวัตถุเช่น Ninject IKernelเป็นที่เก็บข้อมูลหลักของพวกเขา แต่นี่ไม่ใช่ความกังวลของคุณ!

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

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

    ตอนนี้คอนเทนเนอร์ IoC ล่ะ? คุณทำเช่นเดียวกัน! อีกครั้งโดยจะ Ninject ศัพท์คุณมองไปที่ที่มีผลผูกพันการตั้งค่าและหาไม่ว่าจะพูดอะไรบางอย่างเช่นInTransientScope, InSingletonScopeหรืออะไรก็ตาม หากมีสิ่งใดที่อาจชัดเจนกว่านี้เพราะคุณมีรหัสอยู่ตรงนั้นประกาศขอบเขตของมันแทนที่จะต้องมองหาวิธีการติดตามสิ่งที่เกิดขึ้นกับวัตถุบางอย่าง (วัตถุอาจถูกกำหนดขอบเขตไปยังบล็อก แต่มันใช้หลายครั้งในนั้น บล็อกหรือเพียงแค่ครั้งเดียวเช่น) ดังนั้นบางทีคุณอาจถูกรังเกียจโดยความคิดที่จะต้องใช้คุณสมบัติบนคอนเทนเนอร์ IoC แทนที่จะเป็นภาษาดิบเพื่อกำหนดขอบเขต แต่ตราบใดที่คุณเชื่อถือห้องสมุด IoC ของคุณ - ซึ่งคุณควร! - ไม่มีข้อเสียที่แท้จริง .

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

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

  3. จุดสูงสุดที่นี่คล้ายกับ 2 เวลาส่วนใหญ่คอนเทนเนอร์ IoC ใช้ตัวสร้าง! Setter injection มีไว้สำหรับสถานการณ์ที่เฉพาะเจาะจงซึ่งไม่สามารถใช้การสร้างคอนสตรัคเตอร์ได้ ใครก็ตามที่ใช้ setter injection ตลอดเวลาเพื่อปกปิดจำนวนการพึ่งพาที่ถูกส่งผ่านเข้ามา นั่นไม่ใช่ความผิดของเครื่องมือ แต่เป็นของพวกเขา

    ทีนี้ถ้านี่เป็นความผิดพลาดง่าย ๆ ที่จะทำอย่างไร้เดียงสาและสิ่งที่ IoC ให้การสนับสนุนนั้นโอเคคุณอาจมีประเด็น มันเหมือนกับการทำให้สมาชิกทุกคนในชั้นเรียนของฉันเปิดเผยต่อหน้าคนอื่นเมื่อพวกเขาปรับเปลี่ยนสิ่งที่พวกเขาไม่ควรใช่ไหม แต่ใครก็ตามที่ใช้ setter injection เพื่อปกปิดการฝ่าฝืน SRP อาจเพิกเฉยหรือเพิกเฉยต่อหลักการออกแบบพื้นฐานโดยสิ้นเชิง มันไม่มีเหตุผลที่จะกล่าวโทษเรื่องนี้ในคอนเทนเนอร์ IoC

    นี่เป็นเรื่องจริงโดยเฉพาะอย่างยิ่งเพราะเป็นสิ่งที่คุณสามารถทำได้อย่างง่ายดายด้วย DI ของชายยากจน:

    var myObject 
       = new MyTerriblyLargeObject { DependencyA = new Thing(), DependencyB = new Widget(), Dependency C = new Repository(), ... };
    

    ดังนั้นความกังวลนี้ดูเหมือนจะสมบูรณ์โดยสิ้นเชิงว่าจะใช้คอนเทนเนอร์ IoC หรือไม่

  4. การเปลี่ยนวิธีการที่คลาสของคุณทำงานร่วมกันไม่ใช่การละเมิด OCP ถ้าเป็นเช่นนั้นการผกผันของการพึ่งพาทั้งหมดจะสนับสนุนให้มีการละเมิด OCP หากเป็นกรณีนี้พวกเขาจะไม่อยู่ในคำย่อของ SOLID เดียวกัน!

    นอกจากนี้ไม่มีคะแนน a) หรือ b) ใกล้เคียงกับการทำอะไรกับ OCP ฉันไม่รู้ด้วยซ้ำว่าจะตอบคำถามเหล่านี้อย่างไรเกี่ยวกับ OCP

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

และสิ่งสุดท้ายที่คุณพูดว่า:

แต่ฉันไม่สามารถไว้วางใจแบบเดียวกันนี้ได้ในเครื่องมือของบุคคลที่สามซึ่งกำลังเปลี่ยนรหัสที่คอมไพล์ของฉันเพื่อแก้ไขปัญหากับสิ่งที่ฉันไม่สามารถทำได้ด้วยตนเอง

ใช่คุณสามารถ ไม่มีเหตุผลใดที่คุณจะคิดว่าเครื่องมือเหล่านี้ที่พึ่งพาโครงการจำนวนมหาศาลนั้นมีพฤติกรรมที่ไม่คาดคิดหรือมีพฤติกรรมที่ไม่คาดคิดมากกว่าห้องสมุดบุคคลที่สามอื่น ๆ

ภาคผนวก

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

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

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

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

void Bind(Type interfaceType, Type concreteType, bool singleton);
T Resolve<T>();

Bindพูดว่า "ที่คุณเห็นอาร์กิวเมนต์ตัวสร้างประเภทinterfaceTypeผ่านในตัวอย่างconcreteType" singletonพารามิเตอร์เพิ่มเติมบอกว่าจะใช้อินสแตนซ์เดียวกันของconcreteTypeแต่ละครั้งหรือสร้างใหม่เสมอ

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

คุณสามารถลองใช้สิ่งนี้ด้วยตัวคุณเองแล้วคุณจะพบว่าคุณต้องมีการไตร่ตรองและมีการแคชสำหรับการผูกที่singletonจริง แต่ก็ไม่มีอะไรรุนแรงหรือน่ากลัวอย่างแน่นอน และเมื่อคุณทำเสร็จแล้วvoilaคุณจะมีแกนหลักของคอนเทนเนอร์ IoC ของคุณเอง! มันน่ากลัวจริงๆเหรอ? ข้อแตกต่างที่แท้จริงระหว่างสิ่งนี้กับ Ninject หรือ StructureMap หรือ Castle Windsor หรือสิ่งที่คุณต้องการก็คือสิ่งเหล่านั้นมีฟังก์ชั่นการใช้งานที่ครอบคลุมมากกว่า (มาก!) กรณีการใช้งานที่รุ่นพื้นฐานนี้จะไม่เพียงพอ แต่ในหัวใจของมันสิ่งที่คุณมีคือสิ่งสำคัญของคอนเทนเนอร์ IoC


ขอบคุณเบ็น ฉันทำงานกับ IOC Containers ได้เพียงปีเดียวเท่านั้นและถึงแม้ว่าฉันจะไม่ทำแบบฝึกหัดและเพื่อนรอบตัวฉันก็ให้ความสำคัญกับการฉีดคุณสมบัติ (รวมถึงส่วนตัว) มันบ้าและมันก็นำมาซึ่งคะแนนทั้งหมดที่ฉันทำ แต่ถึงแม้ว่าคนอื่นจะอยู่ในสถานการณ์เช่นนี้ฉันคิดว่าสิ่งที่ดีที่สุดที่พวกเขาสามารถทำได้คือเรียนรู้เพิ่มเติมเกี่ยวกับวิธีที่ IOC บรรจุควรทำงานตามหลักการและชี้ให้เห็นถึงตัวแบ่งหลักการในการตรวจสอบรหัส อย่างไรก็ตาม ... (ต่อ)
Suamere

ความกังวลที่ใหญ่ที่สุดของฉันไม่จำเป็นต้องอยู่ในรายชื่อหลักการ OOP / SOLID และนั่นคือขอบเขตที่ชัดเจน ฉันยังคงเรากำลังขว้างบล็อกขอบเขตท้องถิ่นโมดูลและขอบเขตระดับโลกเพื่อทำความเข้าใจกับหน้าต่างสำหรับคำหลัก แนวคิดทั้งหมดของการใช้บล็อกและการประกาศกำหนดเมื่อบางสิ่งบางอย่างเกินขอบเขตหรือถูกกำจัดมีขนาดใหญ่มากสำหรับฉันและฉันคิดว่านั่นเป็นส่วนที่น่ากลัวที่สุดของ IOC Containers สำหรับฉันเพื่อแทนที่ชิ้นส่วนพื้นฐานที่สำคัญมากในการพัฒนา .
Suamere

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

2
ในเรื่องที่เกี่ยวกับ 4 การพึ่งพาการฉีดไม่ได้อยู่ในคำย่อของโซลิด 'D' = 'หลักการผกผันของการพึ่งพา' ซึ่งเป็นแนวคิดที่ไม่เกี่ยวข้องทั้งหมด
astreltsov

@astr จุดดี ฉันได้แทนที่ "การฉีด" ด้วย "การผกผัน" เนื่องจากฉันคิดว่านั่นคือสิ่งที่ฉันต้องการจะเขียนตั้งแต่แรก นั่นยังคงเป็นเรื่องง่ายเกินไปเนื่องจากการผกผันของการพึ่งพาไม่จำเป็นต้องบ่งบอกถึงการใช้งานที่เป็นรูปธรรมหลายอย่าง แต่ฉันคิดว่าความหมายชัดเจนเพียงพอ มันจะเป็นอันตรายที่จะขึ้นอยู่กับนามธรรม abstraction polymorphic หากเปลี่ยนการใช้งานเป็นการละเมิด OCP
Ben Aaronson

27

คอนเทนเนอร์ของ IOC ไม่ทำลายหลักการเหล่านี้มากมายใช่ไหม

ในทางทฤษฎี ไม่ IoC container เป็นเพียงเครื่องมือ คุณสามารถมีวัตถุที่มีความรับผิดชอบเดียวส่วนติดต่อที่แยกจากกันไม่สามารถปรับเปลี่ยนพฤติกรรมของพวกเขาเมื่อเขียน ฯลฯ

ในทางปฏิบัติ อย่างแน่นอน

ฉันหมายความว่าฉันไม่ได้ยินโปรแกรมเมอร์บางคนบอกว่าพวกเขาใช้คอนเทนเนอร์ IoC โดยเฉพาะเพื่อให้คุณใช้การกำหนดค่าบางอย่างเพื่อเปลี่ยนพฤติกรรมของระบบ - ละเมิดหลักการเปิด / ปิด เคยมีเรื่องตลกที่ทำเกี่ยวกับการเข้ารหัสใน XML เพราะ 90% ของงานของพวกเขากำลังแก้ไขการกำหนดค่าสปริง และแน่นอนว่าคุณถูกต้องที่ซ่อนการพึ่งพา (ที่ยอมรับไม่ใช่คอนเทนเนอร์ IoC ทั้งหมดที่ทำ) เป็นวิธีที่รวดเร็วและง่ายดายในการสร้างรหัสที่มีความเป็นคู่และบอบบางมาก

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

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

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

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

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


3
ขวา. และร้านค้าจำนวนมากจะอ้างว่าผลิตภัณฑ์ของพวกเขาซับซ้อนจนพวกเขาตกอยู่ในหมวดหมู่นั้นเมื่อพวกเขาไม่ทำ เช่นเดียวกับความจริงในหลาย ๆ สถานการณ์
Suamere

12
แต่ IoC ตรงข้ามกับที่คุณพูด มันใช้ Open / Closeness ของโปรแกรม หากคุณสามารถเปลี่ยนพฤติกรรมของโปรแกรมทั้งหมดโดยไม่ต้องเปลี่ยนรหัสเอง
สุข

6
@Euphoric - เปิดเพื่อขยายปิดการแก้ไข หากคุณสามารถเปลี่ยนพฤติกรรมทั้งหมดของโปรแกรมมันไม่ได้ปิดเพื่อการปรับเปลี่ยนใช่หรือไม่ การกำหนดค่า IoC ยังคงเป็นซอฟต์แวร์ของคุณ แต่ยังคงเป็นรหัสที่คลาสของคุณใช้ในการทำงานแม้ว่าจะอยู่ใน XML แทนที่จะเป็น Java หรือ C # หรืออะไรก็ตาม
Telastyn

4
@Tastastyn "ปิดเพื่อแก้ไข" หมายความว่าไม่จำเป็นต้องเปลี่ยน (แก้ไข) รหัสเพื่อเปลี่ยนพฤติกรรมทั้งหมด ด้วยการกำหนดค่าภายนอกคุณสามารถชี้ไปที่ dll ใหม่และมีพฤติกรรมของการเปลี่ยนแปลงทั้งหมด
สุข

12
@Telastyn นั่นไม่ใช่สิ่งที่หลักการเปิด / ปิดกล่าวไว้ มิฉะนั้นวิธีที่ใช้พารามิเตอร์จะละเมิด OCP เพราะฉันสามารถ "แก้ไข" พฤติกรรมของมันโดยผ่านพารามิเตอร์ที่แตกต่างกัน ในทำนองเดียวกันภายใต้ OCP เวอร์ชันของคุณมันจะขัดแย้งโดยตรงกับ DI ซึ่งจะทำให้ค่อนข้างแปลกที่ทั้งคู่จะปรากฏในตัวย่อของ SOLID
Ben Aaronson

14

การใช้คอนเทนเนอร์ IoC นั้นละเมิดหลักการของ OOP / SOLID หรือไม่ ไม่

คุณสามารถใช้คอนเทนเนอร์ IoC ในลักษณะที่พวกเขาละเมิดหลักการ OOP / SOLID ได้หรือไม่? ใช่แล้ว

คอนเทนเนอร์ IoC เป็นเพียงเฟรมเวิร์กสำหรับการจัดการการพึ่งพาในแอปพลิเคชันของคุณ

คุณระบุ Lazy injections, setters property และคุณสมบัติอื่น ๆ อีกสองสามอย่างที่ฉันยังไม่รู้สึกว่าจำเป็นต้องใช้ซึ่งฉันเห็นด้วยกับสามารถให้การออกแบบที่เหมาะสมน้อยกว่าคุณ อย่างไรก็ตามการใช้งานคุณสมบัติเฉพาะเหล่านี้เกิดจากข้อ จำกัด ในเทคโนโลยีที่คุณใช้งาน IoC container

ตัวอย่างเช่น ASP.NET WebForms คุณจะต้องใช้การฉีดคุณสมบัติเนื่องจากไม่สามารถสร้างอินสแตนซ์Pageได้ สิ่งนี้สามารถเข้าใจได้เพราะ WebForms ไม่เคยออกแบบด้วย OOP ที่เข้มงวดในใจ

ASP.NET MVC นั้นเป็นไปได้ที่จะใช้คอนเทนเนอร์ IoC โดยใช้การสร้างคอนสตรัคที่เป็นมิตรกับ OOP / SOLID

ในสถานการณ์นี้ (โดยใช้การฉีดคอนสตรัคเตอร์) ฉันเชื่อว่ามันสนับสนุนหลักการของ SOLID ด้วยเหตุผลดังต่อไปนี้:

  • หลักการความรับผิดชอบเดี่ยว - การมีชั้นเรียนขนาดเล็กจำนวนมากช่วยให้ชั้นเรียนเหล่านี้มีความเฉพาะเจาะจงมากและมีเหตุผลเดียวที่มีอยู่ การใช้คอนเทนเนอร์ IoC ทำให้การจัดระเบียบง่ายยิ่งขึ้น

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

  • หลักการทดแทน Liskov - ไม่เกี่ยวข้องจริงๆ

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

  • Dependency Inversion - คอนเทนเนอร์ IoC ช่วยให้คุณสามารถพึ่งพาการผกผันได้อย่างง่ายดาย

คุณกำหนดกลุ่มของการอ้างอิงและประกาศความสัมพันธ์และขอบเขตและ bing bang boom: คุณมี addon บางอย่างที่สามารถเปลี่ยนแปลงรหัสหรือ IL ของคุณในบางจุดและทำให้สิ่งต่าง ๆ ทำงานได้อย่างน่าอัศจรรย์ นั่นไม่ชัดเจนหรือโปร่งใส

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

ฉันยอมรับว่าเมื่อฉันเขียนหรืออ่านรหัสโดยใช้ IOC container มันจะกำจัดโค้ดที่ไม่เหมาะสมออกไปเล็กน้อย

นี่คือเหตุผลทั้งหมดสำหรับ OOP / SOLID เพื่อให้ระบบสามารถจัดการได้ การใช้คอนเทนเนอร์ IoC นั้นสอดคล้องกับเป้าหมายนั้น

ผู้เขียนชั้นนั้นบอกว่า "ถ้าเราไม่ได้ใช้ IOC Container ตัวสร้างจะมีพารามิเตอร์หลายโหล !!! มันแย่มาก!"

คลาสที่มีการอ้างอิง 12 อาจเป็นการละเมิด SRP ไม่ว่าคุณจะใช้บริบทใด


2
คำตอบที่ยอดเยี่ยม นอกจากนี้ฉันคิดว่าคอนเทนเนอร์ IOC หลักทั้งหมดยังรองรับ AOP ซึ่งสามารถช่วยเหลือ OCP ได้เป็นอย่างมาก สำหรับข้อกังวลที่ตัดข้ามกัน AOP มักเป็นเส้นทางที่เป็นมิตรกับ OCP มากกว่ามัณฑนากร
Ben Aaronson

2
@BenAaronson พิจารณาว่า AOP อัดรหัสเข้าไปในชั้นเรียนฉันจะไม่เรียกมันว่าเป็นมิตรกับ OCP มากขึ้น คุณกำลังเปิดและเปลี่ยนคลาสอย่างคอมไพล์ / รันไทม์
Doval

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

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

ฉันไม่ได้รับเหตุผลของการอธิบายว่าสิ่งที่ไม่เลวบนพื้นฐานของความจริงที่ว่ามันเป็นกรอบ ServiceLocators ถูกสร้างขึ้นเป็นเฟรมเวิร์กด้วยและถือว่าแย่มาก :)
ipavlu

5

IOC ไม่บรรจุทั้งตัวแบ่งและอนุญาตให้ตัวถอดรหัสทำลายหลักการ OOP / SOLID มากมายใช่ไหม

staticคำหลักใน C # ช่วยให้นักพัฒนาที่จะทำลายจำนวนมากของ OOP / หลักการที่มั่นคง แต่ก็ยังคงเป็นเครื่องมือที่ถูกต้องในสถานการณ์ที่เหมาะสม

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

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


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

2
@Suamere - ฉันคิดว่าคุณอาจใช้คำจำกัดความของ IOC ในวงกว้างเกินไป สิ่งที่ฉันใช้ไม่ได้แก้ไขโค้ดที่คอมไพล์แล้ว มีเครื่องมือที่ไม่ใช่ IOC อื่น ๆ อีกมากมายซึ่งยังแก้ไขโค้ดที่คอมไพล์ด้วย บางทีชื่อของคุณควรเป็นเหมือน: "ทำการแก้ไขตัวแบ่งรหัสที่คอมไพล์แล้ว ... "
Cerad

@Suamere ฉันไม่ได้มีประสบการณ์กับ IoC แต่ฉันไม่เคยได้ยินเกี่ยวกับการเปลี่ยนรหัสที่รวบรวม IoC คุณช่วยกรุณาให้ข้อมูลเกี่ยวกับสิ่งที่คุณพูดถึงแพลตฟอร์ม / ภาษา / กรอบ
Euphoric

1
"คอนเทนเนอร์ IoC สามารถใช้เพื่อทำให้หลักการของ SOLID ง่ายขึ้น" - คุณช่วยอธิบายได้ไหม? การอธิบายว่าการช่วยเหลือเป็นพิเศษกับแต่ละหลักการจะเป็นประโยชน์อย่างไร และแน่นอนว่าการใช้ประโยชน์จากสิ่งที่ไม่เหมือนกับการช่วยเหลือบางสิ่งเกิดขึ้น (เช่น DI)
Den

1
@Eurhoric ฉันไม่รู้เกี่ยวกับ. net frameworks suamere กำลังพูดถึง แต่ Spring แน่นอนจะทำการแก้ไขโค้ดที่ต่ำกว่าจริง ตัวอย่างที่ชัดเจนที่สุดคือการสนับสนุนการฉีดตามวิธี (โดยจะแทนที่วิธีนามธรรมในชั้นเรียนของคุณเพื่อส่งคืนการพึ่งพาที่มันจัดการ) นอกจากนี้ยังใช้พร็อกซีที่สร้างขึ้นโดยอัตโนมัติเพื่อห่อรหัสของคุณเพื่อให้มีพฤติกรรมเพิ่มเติม (เช่นสำหรับการจัดการธุรกรรมโดยอัตโนมัติ) สิ่งนี้ไม่ได้เกี่ยวข้องกับบทบาทของ DI Framework อย่างแท้จริง
จูลส์

3

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

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

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

ดังนั้นคำตอบสำหรับคำถามของคุณคือไม่ คอนเทนเนอร์ IoC ไม่ทำลายหลักการออกแบบของ OOP ค่อนข้างจะแก้ปัญหาที่เกิดจากการปฏิบัติตามหลักการของ SOLID (โดยเฉพาะอย่างยิ่งหลักการพึ่งพา - การกลับกัน)


พยายามใช้ IoC (Autofac) กับโครงการที่ไม่สำคัญเมื่อเร็ว ๆ นี้ ตระหนักว่าฉันต้องทำงานที่คล้ายกันกับการสร้างที่ไม่ใช่ภาษา (ใหม่ () vs API): การระบุสิ่งที่ควรได้รับการแก้ไขในการเชื่อมต่อและสิ่งที่ควรได้รับการแก้ไขในชั้นเรียนที่เป็นรูปธรรมระบุสิ่งที่ควรเป็นตัวอย่าง ตรวจสอบให้แน่ใจว่าการฉีดคุณสมบัติทำงานถูกต้องเพื่อบรรเทาการพึ่งพาแบบวงกลม ตัดสินใจละทิ้ง ทำงานได้ดีกับตัวควบคุมใน ASP MVC
Den

@Den โครงการของคุณไม่ได้รับการออกแบบอย่างชัดเจนด้วยการพึ่งพาการผกผันในใจ และไม่มีที่ไหนเลยที่ฉันพูดว่าการใช้ IoC นั้นไม่สำคัญ
ร่าเริง

ที่จริงแล้วสิ่งนั้น - ฉันใช้ Dependency Inversion ตั้งแต่เริ่มต้น IoC ส่งผลกระทบต่อการออกแบบที่เกินความคาดหมายของฉัน เช่นเหตุใดฉันจึงต้องใช้อินเทอร์เฟซทุกที่เพื่อทำให้ IoC ง่ายขึ้น ดูความเห็นสูงสุดของคำถาม
Den

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