คำติชมและข้อเสียของการฉีดพึ่งพา


118

การฉีดพึ่งพา (DI) เป็นรูปแบบที่รู้จักกันดีและทันสมัย วิศวกรส่วนใหญ่ทราบถึงข้อดีของมันเช่น:

  • ทำให้การแยกในการทดสอบหน่วยเป็นไปได้ / ง่าย
  • การกำหนดการขึ้นต่อกันของคลาสอย่างชัดเจน
  • ยกตัวอย่างเช่นการออกแบบที่ดี ( หลักการความรับผิดชอบเดี่ยว (SRP))
  • เปิดใช้งานการสลับการใช้งานอย่างรวดเร็ว ( DbLoggerแทนที่จะConsoleLoggerเป็นตัวอย่าง)

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

  • เพิ่มจำนวนคลาส
  • สร้างอินเตอร์เฟสที่ไม่จำเป็น

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

สิ่งที่ฉันต้องการถามคือ:

  • เราควรใช้การฉีดพึ่งพาเมื่อเรามีเพียงหนึ่งการดำเนินการ?
  • เราควรห้ามการสร้างวัตถุใหม่ยกเว้นภาษา / กรอบงานหรือไม่?
  • การฉีดความคิดที่ไม่ดีในการนำไปใช้งานเพียงครั้งเดียว (สมมติว่าเรามีการนำไปใช้เพียงครั้งเดียวดังนั้นเราจึงไม่ต้องการสร้างอินเทอร์เฟซ "ว่างเปล่า") ถ้าเราไม่ได้วางแผนทดสอบหน่วยเฉพาะชั้นเรียนหรือไม่

33
คุณถามเกี่ยวกับการฉีดตามความเป็นจริงหรือคุณถามเกี่ยวกับการใช้ DI Frameworks หรือไม่? สิ่งเหล่านี้เป็นสิ่งที่แตกต่างกันอย่างแท้จริงคุณควรอธิบายให้ชัดเจนว่าคุณสนใจส่วนใดของปัญหาหรือถามทั้งสองอย่าง
Frax

10
@Frax เกี่ยวกับรูปแบบไม่ใช่กรอบ
Landeeyo

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

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

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

คำตอบ:


160

ก่อนอื่นฉันต้องการแยกวิธีการออกแบบออกจากแนวคิดของกรอบงาน การฉีดพึ่งพาในระดับที่ง่ายที่สุดและพื้นฐานที่สุดคือ:

วัตถุแม่ให้การอ้างอิงทั้งหมดที่จำเป็นสำหรับวัตถุลูก

แค่นั้นแหละ. โปรดทราบว่าไม่มีสิ่งใดในนั้นที่ต้องใช้อินเทอร์เฟซเฟรมเวิร์กรูปแบบการฉีด ฯลฯ เพื่อความเป็นธรรมฉันได้เรียนรู้เกี่ยวกับรูปแบบนี้เป็นครั้งแรกเมื่อ 20 ปีก่อน มันไม่ใช่เรื่องใหม่

เนื่องจากมีมากกว่า 2 คนที่มีความสับสนเกี่ยวกับคำว่าผู้ปกครองและเด็กในบริบทของการฉีดพึ่งพา:

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

ฉีดพึ่งพาเป็นรูปแบบสำหรับวัตถุองค์ประกอบ

ทำไมอินเตอร์เฟส

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

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

ทำไมกรอบ

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

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

พวกเขายังมีข้อเสียดังต่อไปนี้:

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

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

แล้ว [บทความแบบสุ่มบนอินเทอร์เน็ต] ล่ะ?

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

กล่าวโดยย่อให้คิดด้วยตัวเองและลองทำดู

การทำงานกับ "หัวเก่า"

เรียนรู้ให้มากที่สุด สิ่งที่คุณจะพบกับนักพัฒนาจำนวนมากที่ทำงานในยุค 70 ของพวกเขาคือพวกเขาได้เรียนรู้ที่จะไม่ดื้อรั้นเกี่ยวกับสิ่งต่างๆมากมาย พวกเขามีวิธีการที่พวกเขาได้ทำงานร่วมกันมานานหลายทศวรรษเพื่อให้ได้ผลลัพธ์ที่ถูกต้อง

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


6
@CarlLeth ฉันได้ทำงานกับเฟรมเวิร์กจำนวนมากตั้งแต่ Spring ถึง. net variants ฤดูใบไม้ผลิจะช่วยให้คุณฉีดการใช้งานลงในช่องส่วนตัวโดยใช้เวทมนตร์ดำสะท้อน / classloader วิธีเดียวในการทดสอบส่วนประกอบที่สร้างขึ้นเช่นนั้นคือการใช้คอนเทนเนอร์ ฤดูใบไม้ผลิมีนักวิ่ง JUnit เพื่อกำหนดค่าสภาพแวดล้อมการทดสอบ แต่มันซับซ้อนกว่าการตั้งค่าด้วยตัวคุณเอง ใช่ฉันแค่ยกตัวอย่างการปฏิบัติ
Berin Loritsch

17
มีข้อเสียอีกข้อหนึ่งที่ฉันพบว่าเป็นอุปสรรคกับ DI ผ่านกรอบงานเมื่อฉันสวมหมวกแก้ไขปัญหา / ผู้ดูแล: การกระทำที่น่ากลัวในระยะที่พวกเขาให้ทำให้การดีบักออฟไลน์ยากขึ้น ในกรณีที่เลวร้ายที่สุดฉันต้องเรียกใช้รหัสเพื่อดูว่าการอ้างอิงเริ่มต้นและส่งต่ออย่างไรคุณพูดถึงสิ่งนี้ในบริบทของ "การทดสอบ" แต่จริงๆแล้วมันแย่กว่านั้นมากถ้าคุณเพิ่งเริ่มมองหาที่มา โปรดพยายามทำให้มันทำงาน (ซึ่งอาจเกี่ยวข้องกับการตั้งค่าจำนวนมาก) ขัดขวางความสามารถของฉันในการบอกว่าโค้ดทำอะไรโดยเพียงแค่เหลือบมองไปที่มันเป็นสิ่งที่ไม่ดี
Jeroen Mostert

1
ส่วนต่อประสานไม่ใช่สัญญา แต่เป็นเพียง API สัญญาหมายถึงความหมาย คำตอบนี้ใช้คำศัพท์เฉพาะทางภาษาและอนุสัญญาเฉพาะ Java / C #
Frank Hileman

2
@BerinLoritsch ประเด็นหลักของคำตอบของคุณคือหลักการ DI! = กรอบ DI ใด ๆ ความจริงที่ว่าสปริงสามารถทำสิ่งที่น่ากลัวและไม่สามารถให้อภัยได้นั้นเป็นข้อเสียของสปริงไม่ใช่กรอบ DI โดยทั่วไป กรอบ DI ที่ดีจะช่วยให้คุณทำตามหลักการ DI โดยไม่ต้องใช้เทคนิคที่น่ารังเกียจ
Carl Leth

1
@Carleth: เฟรมเวิร์ก DI ทั้งหมดได้รับการออกแบบมาเพื่อลบหรือทำให้บางสิ่งที่โปรแกรมเมอร์ไม่ต้องการสะกดออกมาโดยอัตโนมัติ เพื่อความรู้ของฉันที่ดีที่สุดพวกเขาทั้งหมดลบความสามารถในการรู้วิธี (หรือถ้า ) คลาส A และ B มีปฏิสัมพันธ์โดยเพียงแค่ดูที่ A และ B - อย่างน้อยที่สุดคุณต้องดู DI setup / configuration / การประชุม ไม่ใช่ปัญหาสำหรับโปรแกรมเมอร์ (เป็นสิ่งที่พวกเขาต้องการจริง ๆ แล้ว) แต่เป็นปัญหาที่อาจเกิดขึ้นสำหรับผู้ดูแล / ดีบักเกอร์ (อาจเป็นโปรแกรมเมอร์คนเดียวกันภายหลัง) นี่เป็นการแลกเปลี่ยนที่คุณทำแม้ว่ากรอบ DI ของคุณจะ "สมบูรณ์แบบ"
Jeroen Mostert

88

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

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

พิจารณาโมดูลที่ดาวน์โหลดข้อมูลบางอย่างจากบริการภายนอกแยกวิเคราะห์และทำการวิเคราะห์ที่ซับซ้อนและเขียนผลลัพธ์ลงในไฟล์

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

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

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

ในทางตรงกันข้ามมีบางกรณีที่ DI มีประโยชน์จริงๆ ตัวอย่างเช่นบริการทั่วโลกที่มีผลข้างเคียงเช่นคนตัดไม้

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

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


15
ฉันไม่เห็นด้วยเพิ่มอีก! นอกจากนี้โปรดทราบว่าการเยาะเย้ยสิ่งต่าง ๆ เพื่อประโยชน์ของมันหมายความว่าเราไม่ได้ทดสอบการใช้งานจริง หากAใช้Bในการผลิต แต่ได้รับการทดสอบแล้วเท่านั้นการทดสอบMockBของเราจะไม่บอกเราว่าจะใช้งานได้จริงหรือไม่ เมื่อองค์ประกอบบริสุทธิ์ (ไม่มีผลข้างเคียง) ของแบบจำลองโดเมนถูกแทรกและเยาะเย้ยกันผลที่ได้คือเสียเวลามากของทุกคนฐานข้อมูลที่ป่องและเปราะบางและความมั่นใจต่ำในระบบผลลัพธ์ จำลองที่ขอบเขตของระบบไม่ใช่ระหว่างส่วนใดส่วนหนึ่งของระบบเดียวกัน
Warbo

17
@Carleth ทำไมคุณถึงคิดว่า DI ทำให้โค้ด "ทดสอบได้และบำรุงรักษาได้" และรหัสโดยไม่ทำให้น้อยลง? JacquesB ถูกต้องว่าผลข้างเคียงเป็นสิ่งที่เป็นอันตรายต่อการทดสอบ / การบำรุงรักษา หากรหัสไม่มีผลข้างเคียงเราจะไม่สนใจสิ่งที่ / ที่ไหน / เมื่อใด / อย่างไรที่เรียกว่ารหัสอื่น เราสามารถทำให้มันเรียบง่ายและตรงไปตรงมา หากรหัสมีผลข้างเคียงเราต้องดูแล DI สามารถดึงผลข้างเคียงออกจากฟังก์ชั่นและวางไว้ในพารามิเตอร์ทำให้ฟังก์ชั่นเหล่านั้นทดสอบได้มากขึ้น แต่โปรแกรมซับซ้อนขึ้น บางครั้งก็หลีกเลี่ยงไม่ได้ (เช่นการเข้าถึงฐานข้อมูล) หากโค้ดไม่มีผลข้างเคียง DI จะเป็นเพียงความซับซ้อนที่ไร้ประโยชน์
Warbo

13
@CarlLeth: DI เป็นวิธีการหนึ่งในการแก้ปัญหาของการทดสอบรหัสในการแยกหากมีการอ้างอิงที่ห้ามมัน แต่มันไม่ได้ลดความซับซ้อนโดยรวมหรือทำให้โค้ดอ่านง่ายขึ้นซึ่งหมายความว่ามันไม่จำเป็นต้องเพิ่มความสามารถในการบำรุงรักษา อย่างไรก็ตามหากการอ้างอิงทั้งหมดเหล่านั้นสามารถกำจัดได้โดยการแยกข้อกังวลออกมาได้ดีกว่านี้สิ่งนี้จะทำให้ประโยชน์ของ DI เป็นโมฆะเพราะมันไม่จำเป็นต้อง DI นี่เป็นวิธีที่ดีกว่าในการสร้างรหัสทดสอบและบำรุงรักษาได้ในเวลาเดียวกัน
Doc Brown

5
@Warbo นี่เป็นต้นฉบับและยังคงใช้การล้อเลียนที่ถูกต้องเท่านั้น แม้จะอยู่ในขอบเขตของระบบก็ยังไม่ค่อยจำเป็น ผู้คนเสียเวลามากในการสร้างและอัปเดตการทดสอบเกือบไร้ค่า
Frank Hileman

6
@CarlLeth: โอเคตอนนี้ฉันเห็นว่าความเข้าใจผิดมาจากไหน คุณกำลังพูดถึงการพึ่งพาการผกผัน แต่คำถามคำตอบนี้และแสดงความคิดเห็นของฉันเกี่ยวกับ DI = depency ฉีด
Doc Brown

36

จากประสบการณ์ของผมมีข้อเสียหลายประการสำหรับการฉีดแบบพึ่งพา

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

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

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


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

7
หากคุณต้องการทดสอบชั้นเรียนด้วยการใช้งานจริง (ไม่ใช่จำลอง) คุณสามารถเขียนแบบทดสอบการใช้งานได้ - แบบทดสอบที่คล้ายกับแบบทดสอบหน่วย แต่ไม่ใช้แบบจำลอง
BЈовић

2
ฉันคิดว่าย่อหน้าที่สองของคุณจะต้องมีความเหมาะสมยิ่งขึ้น: DI ในตัวมันเองไม่ได้ทำให้ยากที่จะสำรวจโค้ด ที่ง่ายที่สุด DI นั้นเป็นผลมาจากการติดตาม SOLID สิ่งที่เพิ่มความซับซ้อนคือการใช้ความร้ายที่ไม่จำเป็นและกรอบ DI นอกเหนือจากนั้นคำตอบนี้กระทบเล็บบนหัว
Konrad Rudolph

4
การฉีดการพึ่งพานอกกรณีที่จำเป็นจริงๆก็เป็นสัญญาณเตือนว่ารหัสฟุ่มเฟือยอื่น ๆ อาจมีอยู่มากมาย ผู้บริหารระดับสูงมักจะประหลาดใจที่รู้ว่านักพัฒนาเพิ่มความซับซ้อนเพื่อความซับซ้อน
Frank Hileman

1
+1 นี่คือคำตอบที่แท้จริงสำหรับคำถามที่ถูกถามและควรเป็นคำตอบที่ยอมรับได้
Mason Wheeler

13

ฉันทำตามคำแนะนำของ Mark Seemann จาก "การพึ่งพาการฉีดใน. NET" เพื่อคาดการณ์

ควรใช้ DI เมื่อคุณมี 'การพึ่งพาที่ผันผวน' เช่นมีโอกาสที่เหมาะสมที่อาจเปลี่ยนแปลงได้

ดังนั้นหากคุณคิดว่าคุณอาจมีการใช้งานมากกว่าหนึ่งครั้งในอนาคตหรือการใช้งานอาจเปลี่ยนแปลงได้ให้ใช้ DI ไม่งั้นnewก็ดี


5
โปรดทราบว่าเขายังให้คำแนะนำที่แตกต่างกันสำหรับ OO และภาษาที่ใช้งานได้blog.ploeh.dk/2017/01/27/ …
jk

1
นั่นเป็นประเด็นที่ดี ถ้าเราสร้างส่วนต่อประสานสำหรับทุกการพึ่งพาโดยค่าเริ่มต้นมันก็เทียบกับ YAGNI
Landeeyo

4
คุณสามารถให้การอ้างอิงถึง"การพึ่งพาการฉีดใน. NET" ?
Peter Mortensen

1
หากคุณกำลังทดสอบหน่วยก็มีโอกาสสูงที่การพึ่งพาของคุณจะผันผวน
Jaquez

11
สิ่งที่ดีคือนักพัฒนาสามารถคาดการณ์อนาคตได้อย่างแม่นยำ
Frank Hileman

5

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

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

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

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


3

การเปิดใช้งานการสลับการใช้งานอย่างรวดเร็ว (เช่น DbLogger แทน ConsoleLogger)

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

เพิ่มจำนวนคลาส

นี่เป็นข้อเสียของกรอบงาน DI ที่กำหนดหรือกรอบการเยาะเย้ยไม่ใช่ตัว DI ในสถานที่ส่วนใหญ่ชั้นเรียนของฉันขึ้นอยู่กับชั้นเรียนที่เป็นรูปธรรมซึ่งหมายความว่าไม่มีความจำเป็นต้องใช้หม้อไอน้ำ Guice (กรอบงาน Java DI) ผูกคลาสกับตัวเองเป็นค่าเริ่มต้นและฉันต้องการแทนที่การเชื่อมโยงในการทดสอบ (หรือวางสายด้วยตนเองแทน)

สร้างอินเตอร์เฟสที่ไม่จำเป็น

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

เราควรใช้การฉีดพึ่งพาเมื่อเรามีเพียงหนึ่งการดำเนินการ?

ใช่ แต่หลีกเลี่ยงสำเร็จรูปเพิ่มใด

เราควรห้ามการสร้างวัตถุใหม่ยกเว้นภาษา / กรอบงานหรือไม่?

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

สำหรับพวกเขาคุณอาจต้องฉีดโรงงานแทน แต่ส่วนใหญ่แล้วมันก็ไม่สมเหตุสมผล (ลองนึกภาพเช่น, @Value class NamedUrl {private final String name; private final URL url;}; คุณไม่จำเป็นต้องมีโรงงานที่นี่และไม่มีอะไรจะฉีด)

การฉีดความคิดที่ไม่ดีในการนำไปใช้งานเพียงครั้งเดียว (สมมติว่าเรามีการนำไปใช้เพียงครั้งเดียวดังนั้นเราจึงไม่ต้องการสร้างอินเทอร์เฟซ "ว่างเปล่า") ถ้าเราไม่ได้วางแผนทดสอบหน่วยเฉพาะชั้นเรียนหรือไม่

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

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


ข้อเสียของเฟรมเวิร์ก DI ส่วนใหญ่ก็คือโอเวอร์เฮดแบบรันไทม์ สิ่งนี้สามารถเคลื่อนย้ายเพื่อรวบรวมเวลา (สำหรับ Java มีDaggerไม่มีความคิดเกี่ยวกับภาษาอื่น)

ข้อเสียอีกอย่างหนึ่งก็คือความมหัศจรรย์ที่เกิดขึ้นทุกที่ซึ่งสามารถปรับได้ (เช่นฉันปิดใช้งานการสร้างพรอกซีเมื่อใช้ Guice)


-4

ฉันต้องบอกว่าในความเห็นของฉันความคิดทั้งหมดของการพึ่งพาการฉีดนั้นเกินจริง

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

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

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

ในรหัสแนวคิดนี้มีลักษณะเช่นนี้ ...

class ClassUnderTest {

   protected final ADependency;
   protected final AnotherDependency;

   // Call from a factory or use an initializer 
   public void initializeDependencies() {
      aDependency = new ADependency();
      anotherDependency = new AnotherDependency();
   }
}

class TestClassUnderTest extends ClassUnderTest {

    @Override
    public void initializeDependencies() {
      aDependency = new MockitoObject();
      anotherDependency = new MockitoObject();
    }

    // Unit tests go here...
    // Unit tests call base class methods
}

ผลลัพธ์นั้นเทียบเท่ากับการใช้ DI - นั่นคือ ClassUnderTest ได้รับการกำหนดค่าสำหรับการทดสอบ

ความแตกต่างเพียงอย่างเดียวคือรหัสนี้รัดกุมอย่างสมบูรณ์ห่อหุ้มง่ายกว่าโค้ดเข้าใจง่ายขึ้นเร็วขึ้นใช้หน่วยความจำน้อยไม่ต้องการการกำหนดค่าสำรองไม่ต้องการกรอบใด ๆ จะไม่เป็นสาเหตุของหน้า 4 (WTF!) การติดตามสแต็กที่มีคลาส ZERO (0) ที่คุณเขียนและเห็นได้ชัดว่าใครก็ตามที่มีความรู้เกี่ยวกับ OO น้อยที่สุดตั้งแต่เริ่มต้นจนถึง Guru (คุณคิดว่า แต่จะเข้าใจผิด)

แน่นอนว่าเราไม่สามารถใช้งานได้ - มันชัดเจนเกินไปและไม่ทันสมัยพอ

ในตอนท้ายของวันแม้ว่าความกังวลที่ใหญ่ที่สุดของฉันกับ DI คือโครงการที่ฉันเห็นล้มเหลวอย่างน่าสังเวชพวกเขาทั้งหมดเป็นฐานรหัสขนาดใหญ่ที่ DI เป็นกาวที่ยึดทุกอย่างไว้ด้วยกัน DI ไม่ใช่สถาปัตยกรรม - มันเกี่ยวข้องเฉพาะในสถานการณ์จำนวนมากซึ่งส่วนใหญ่ถูกบังคับให้คุณใช้ไลบรารีอื่น (JPA, Spring Data ฯลฯ ) ส่วนใหญ่ในฐานรหัสที่ออกแบบมาอย่างดีการใช้ DI ส่วนใหญ่จะเกิดขึ้นในระดับที่ต่ำกว่าที่กิจกรรมการพัฒนาประจำวันของคุณเกิดขึ้น


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

1
มันเรียบร้อยเมื่อคุณมีการสืบทอดคลาสเพียงหนึ่งระดับและการพึ่งพาในระดับหนึ่ง มันจะกลายเป็นนรกบนโลกอย่างแน่นอนหรือไม่?
Ewan

4
ถ้าคุณใช้อินเทอร์เฟซและย้าย initializeDependencies () ลงใน Constructor มันก็เหมือนกัน ขั้นตอนต่อไปการเพิ่มพารามิเตอร์การก่อสร้างหมายความว่าคุณสามารถทำได้ TestClasses ทั้งหมดของคุณ
Ewan

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

3
การเพิ่มใน @ Mr.Mindor: มีรูปแบบการต่อต้านแบบต่อเนื่องทั่วไป "การเชื่อมต่อแบบต่อเนื่อง" ซึ่งไม่ได้ใช้กับการเริ่มต้นเท่านั้น หากวิธีการของวัตถุ (หรือโดยทั่วไปการเรียกใช้ API) จะต้องทำงานตามลำดับเฉพาะเช่นbarสามารถเรียกได้หลังจากfooเท่านั้นนั่นคือ API ที่ไม่ดี มันอ้างว่ามีฟังก์ชั่นการใช้งาน ( bar) แต่เราไม่สามารถใช้งานได้จริง (เนื่องจากfooอาจไม่มีการเรียก) หากคุณต้องการที่จะยึดติดกับinitializeDependenciesรูปแบบ (ต่อต้าน?) อย่างน้อยคุณควรทำให้เป็นส่วนตัว / มีการป้องกันและเรียกมันโดยอัตโนมัติจากนวกรรมิกดังนั้น API มีความจริงใจ
Warbo

-6

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

99% ของคลาสอื่นที่คุณต้องการฉีดจะเป็น mocks ที่เปิดใช้งานการทดสอบหน่วย

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

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

เป็นการยากที่จะจินตนาการถึงข้อเสียที่เลวร้ายจนข้อได้เปรียบของการทดสอบหน่วยมีมาก


13
ฉันไม่เห็นด้วยกับการยืนยันของคุณว่า DI นั้นเกี่ยวกับการทดสอบหน่วย การทดสอบหน่วยอำนวยความสะดวกเป็นเพียงหนึ่งในประโยชน์ของ DI และไม่ใช่เนื้อหาที่สำคัญที่สุด
Robert Harvey

5
ฉันไม่เห็นด้วยกับหลักฐานของคุณว่าการทดสอบหน่วยและ DI ใกล้เคียงกันมาก โดยการใช้จำลอง / ต้นขั้วเราทำให้ชุดทดสอบอยู่กับเราอีกเล็กน้อย: ระบบภายใต้การทดสอบจะได้รับเพิ่มเติมจากระบบจริง นั่นเป็นวัตถุที่ไม่ดี บางครั้งที่มีน้ำหนักเกินโดยหัวกลับหัว: การโทร FS ที่เยาะเย้ยไม่ต้องการการล้าง คำร้องขอ HTTP ที่ถูกเยาะเย้ยนั้นรวดเร็วกำหนดและทำงานแบบออฟไลน์ ในทางกลับกันทุกครั้งที่เราใช้ฮาร์ดโค้ดnewในวิธีการที่เรารู้ว่ารหัสเดียวกันที่ทำงานในการผลิตกำลังทำงานในระหว่างการทดสอบ
Warbo

8
ไม่มันไม่ใช่“ การทดสอบหน่วยไม่ดีใช่หรือไม่” มันคือ“ การเยาะเย้ย (a) จำเป็นจริงๆและ (b) มีค่าเพิ่มขึ้นในความซับซ้อนที่เกิดขึ้นหรือไม่” นั่นเป็นคำถามที่แตกต่างกันมาก การทดสอบหน่วยไม่เลว (จริงๆแล้วไม่มีใครโต้แย้งเรื่องนี้) และแน่นอนว่ามันคุ้มค่าโดยทั่วไป แต่ไม่ใช่การทดสอบหน่วยทั้งหมดที่ต้องมีการเยาะเย้ยและการเยาะเย้ยจะมีค่าใช้จ่ายมากดังนั้นอย่างน้อยควรใช้อย่างรอบคอบ
Konrad Rudolph

6
@Ewan หลังจากความคิดเห็นล่าสุดของคุณฉันไม่คิดว่าเราเห็นด้วย ฉันกำลังบอกว่าการทดสอบหน่วยส่วนใหญ่ไม่ต้องการ DI [frameworks]เนื่องจากการทดสอบหน่วยส่วนใหญ่ไม่จำเป็นต้องเยาะเย้ย ที่จริงแล้วฉันยังใช้สิ่งนี้เป็นวิธีแก้ปัญหาสำหรับคุณภาพของรหัส: ถ้ารหัสส่วนใหญ่ของคุณไม่สามารถทดสอบหน่วยโดยไม่มีวัตถุ DI / จำลองแล้วคุณได้เขียนรหัสที่ไม่ถูกต้องซึ่งเป็นคู่ที่ถูกต้องเกินไป รหัสส่วนใหญ่ควร decoupled สูงความรับผิดชอบเดียวและวัตถุประสงค์ทั่วไปและสามารถทดสอบได้เล็กน้อยในการแยก
Konrad Rudolph

5
@Ewan ลิงก์ของคุณให้คำจำกัดความที่ดีของการทดสอบหน่วย โดยคำจำกัดความOrderตัวอย่างของฉันคือการทดสอบหน่วย: มันกำลังทดสอบวิธี ( totalวิธีการOrder) คุณกำลังบ่นว่ามันเรียกรหัสจาก 2 การเรียนการตอบสนองของฉันคือดังนั้นสิ่งที่ ? เราไม่ได้ทดสอบ "2 คลาสพร้อมกัน" เรากำลังทดสอบtotalวิธีการ เราไม่ควรสนใจว่าวิธีการทำงานของวิธีการเหล่านี้คือรายละเอียดการใช้งาน การทดสอบทำให้เกิดความเปราะบางการมีเพศสัมพันธ์อย่างแน่นหนา ฯลฯ เราใส่ใจเฉพาะพฤติกรรมของวิธีการ (ค่าส่งคืนและผลข้างเคียง) ไม่ใช่คลาส / โมดูล / CPU รีจิสเตอร์ / etc มันใช้ในกระบวนการ
Warbo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.