Poor Man's Dependency Injection เป็นวิธีที่ดีในการแนะนำความสามารถในการทดสอบกับแอปพลิเคชันรุ่นเก่าหรือไม่?


14

ในปีที่ผ่านมาฉันสร้างระบบใหม่โดยใช้ Dependency Injection และ IOC container เรื่องนี้สอนฉันมากมายเกี่ยวกับ DI!

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

เป้าหมายของหลักสูตรคือการนำการทดสอบหน่วยมาใช้ในตรรกะทางธุรกิจ!
ตรรกะทางธุรกิจที่เกี่ยวพันกับการเรียกการป้องกันฐานข้อมูลการทดสอบ

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

คำถาม:การใช้ DI ของ Poor Man เพื่อแนะนำการทดสอบกับแอปพลิเคชั่นรุ่นเก่าและเริ่มต้นการหมุนลูกบอลได้หรือไม่?

นอกจากนี้การใช้ Poor Man's DI เป็นวิธีรากหญ้าในการฉีด Dependency ที่แท้จริงเป็นวิธีที่มีคุณค่าในการให้ความรู้เกี่ยวกับความต้องการและประโยชน์ของหลักการหรือไม่

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

เมื่อถึงความพยายามที่ได้รับการสนับสนุนโครงการสามารถปรับปรุงเพื่อใช้คอนเทนเนอร์ IOC และผู้สร้างจะออกไปที่นั่นในนามธรรม



2
เพียงแค่ทราบ I consider it a challenge to decouple code and introduce an IOC container into a legacy applicationแน่นอนมัน มันมีชื่อว่าหนี้สินทางเทคนิค นี่คือเหตุผลที่ก่อนที่จะทำการปรับปรุงครั้งใหญ่ใด ๆ มันจะดีกว่า refactors ขนาดเล็กและต่อเนื่อง ลดข้อบกพร่องในการออกแบบที่สำคัญและการย้ายมาที่ IoC จะมีความท้าทายน้อยลง
Laiv

คำตอบ:


25

บทวิจารณ์เกี่ยวกับการฉีดของคนจนใน NerdDinner นั้นมีส่วนเกี่ยวข้องกับการที่คุณใช้ DI Container น้อยกว่าการตั้งค่าคลาสของคุณอย่างถูกต้องหรือไม่

ในบทความพวกเขาระบุว่า

public class SearchController : Controller {

    IDinnerRepository dinnerRepository;

    public SearchController() : this(new DinnerRepository()) { }

    public SearchController(IDinnerRepository repository) {
        dinnerRepository = repository;
    }
}

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

วิธีการรักษาที่ถูกต้องแน่นอนไม่ได้เป็นตามที่ Los Techies แนะนำให้เพิ่มภาชนะ DI แต่แทนที่จะลบตัวสร้างที่กระทำผิด

public class SearchController : Controller 
{
    IDinnerRepository dinnerRepository;

    public SearchController(IDinnerRepository repository) {
        dinnerRepository = repository;
    }
}

ชั้นที่เหลือตอนนี้มีการพึ่งพาของคว่ำอย่างถูกต้อง ตอนนี้คุณสามารถฉีดการพึ่งพาเหล่านั้นได้ตามที่คุณต้องการ


ขอบคุณสำหรับความคิดของคุณ! ฉันเข้าใจ "ผู้สร้างที่ละเมิด" และเราควรหลีกเลี่ยงได้อย่างไร ฉันเข้าใจว่าการมีการพึ่งพานี้ไม่ได้ลดค่าใช้จ่ายใด ๆ แต่มันอนุญาตสำหรับการทดสอบหน่วย ฉันกำลังอยู่ในช่วงเริ่มต้นของการแนะนำ DI และได้รับการทดสอบหน่วยในสถานที่โดยเร็วที่สุด ฉันพยายามหลีกเลี่ยงความซับซ้อนของ DI / IOC Container หรือโรงงานในช่วงต้นเกม ดังที่กล่าวไว้ในภายหลังเมื่อการสนับสนุน DI เพิ่มขึ้นเราสามารถใช้ Container และนำ "constructors ที่ละเมิด" ออก
Airn5475

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

2
@ Airn5475 ต้องระวังว่าคุณไม่ได้อยู่ในช่วงสรุปเกินไป การทดสอบเหล่านั้นควรทดสอบพฤติกรรมที่มีความหมาย - การทดสอบที่XServiceผ่านพารามิเตอร์ไปยังXRepositoryและผลตอบแทนสิ่งที่จะได้รับกลับไม่เป็นประโยชน์กับทุกคนมากเกินไปและไม่ได้ให้คุณได้มากในทางของการขยายอย่างใดอย่างหนึ่ง เขียนการทดสอบหน่วยของคุณเพื่อทดสอบพฤติกรรมที่มีความหมายและตรวจสอบให้แน่ใจว่าส่วนประกอบของคุณไม่แคบจนทำให้คุณเลื่อนตรรกะทั้งหมดของคุณไปยังรูทองค์ประกอบของคุณได้
Ant P

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

@Rob: มันไม่ได้ มันเป็นวิธีที่สะดวกสำหรับตัวสร้างเริ่มต้นในการตั้งค่าวัตถุที่ถูกต้อง
Robert Harvey

16

คุณตั้งสมมติฐานที่ผิดพลาดตรงนี้ว่า "คนจนคนจน" คืออะไร

การสร้างคลาสที่มีตัวสร้าง "ทางลัด" ที่ยังคงสร้างการมีเพศสัมพันธ์ไม่ใช่ DI ของคนจน

ไม่ใช้ภาชนะบรรจุและการสร้างการฉีดและการแมปด้วยตนเองทั้งหมดเป็น DI ของคนจน

คำว่า "DI คนจนของคนจน" ฟังดูเหมือนเป็นเรื่องไม่ดี ด้วยเหตุผลดังกล่าวคำว่า "pure DI" จึงได้รับการสนับสนุนในทุกวันนี้เนื่องจากฟังดูดีขึ้นและอธิบายกระบวนการได้อย่างแม่นยำมากขึ้น

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


8
"Poor man's" หรือ "Pure" DI แล้วแต่จำนวนใดที่คุณต้องการนอกจากนี้ยังช่วยลดปัญหามากมายเกี่ยวกับคอนเทนเนอร์ IoC ฉันเคยใช้คอนเทนเนอร์ IoC สำหรับทุกอย่าง แต่ยิ่งเวลาผ่านไปมากเท่าไรฉันก็ยิ่งหลีกเลี่ยงมันทั้งหมด
มด P

7
@AntP ฉันอยู่กับคุณ: ฉันบริสุทธิ์ 100% DI วันนี้และหลีกเลี่ยงภาชนะบรรจุอย่างแข็งขัน แต่ฉัน (เรา) มีคะแนนน้อยเท่าที่ฉันสามารถบอกได้
David Arno

2
ดูเหมือนเศร้ามาก - เมื่อฉันย้ายออกจากค่าย "เวทมนต์" ของภาชนะบรรจุ IoC ล้อเลียนห้องสมุดและอื่น ๆ และพบว่าตัวเองกำลังสวมกอด OOP การห่อหุ้มการทดสอบด้วยมือและการตรวจสอบสถานะดูเหมือนว่าแนวโน้มของเวทมนตร์ยังคงอยู่ใน ขึ้น +1 อยู่ดี
Ant P

3
@AntP & David: ดีใจที่ได้ยินว่าฉันไม่ได้อยู่คนเดียวในค่าย 'Pure DI' คอนเทนเนอร์ DI ถูกสร้างขึ้นเพื่อแก้ไขข้อบกพร่องในภาษาต่างๆ พวกเขาเพิ่มคุณค่าในแง่นั้น แต่ในใจของฉันคำตอบที่แท้จริงคือการแก้ไขภาษา (หรือย้ายไปที่ภาษาอื่น) และไม่สร้าง cruft ด้านบนของพวกเขา
JimmyJames

1

Paragidm การเปลี่ยนแปลงในทีมแบบดั้งเดิม / ฐานรหัสมีความเสี่ยงอย่างยิ่ง:

เมื่อใดก็ตามที่คุณแนะนำ"การปรับปรุง"ให้เป็นรหัสดั้งเดิมและมี โปรแกรมเมอร์"ดั้งเดิม"อยู่ในทีมคุณเพียงแค่บอกทุกคนว่า"พวกเขาทำผิด"และคุณจะกลายเป็นThe Enemyตลอดเวลาที่เหลือกับ บริษัท

การใช้ DI Framework เป็นค้อนทุบเล็บทั้งหมดจะทำให้รหัสดั้งเดิมแย่กว่าดีกว่าในทุกกรณี มันก็มีความเสี่ยงสูงเช่นกัน

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

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

การพึ่งพาการฉีดเป็นวิธีการแก้ปัญหาที่กำลังมองหาปัญหา

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

การพึ่งพาการฉีดมีประโยชน์ในปริมาณน้อยสำหรับช่วงที่แคบมาก:

  • สิ่งที่เปลี่ยนไปมากหรือมีการใช้งานทางเลือกมากมายที่ถูกผูกไว้แบบคงที่

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


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

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

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

4
@JarrodRoberson นั่นเป็นสภาพแวดล้อมที่เป็นพิษจริงๆ หนึ่งในสัญญาณสำคัญของนักพัฒนาที่ดีคือพวกเขามองย้อนกลับไปที่รหัสที่พวกเขาเขียนในอดีตและคิดว่า "อืมฉันจริง ๆ แล้วฉันเขียนมันเหรอ? นั่นเป็นเพราะพวกเขาเติบโตเป็นนักพัฒนาและเรียนรู้สิ่งใหม่ คนที่ดูรหัสพวกเขาเขียนเมื่อห้าปีที่แล้วและไม่เห็นสิ่งใดผิดกับมันได้เรียนรู้อะไรในห้าปีที่ผ่านมา ดังนั้นหากบอกว่าพวกเขาทำผิดในอดีตจะทำให้คุณกลายเป็นศัตรูจากนั้นให้รีบหนี บริษัท นั้นไปเพราะพวกเขาเป็นทีมที่มีจุดจบที่จะพาคุณกลับไปที่ระดับต่ำของพวกเขา
David Arno

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