การพึ่งพาการฉีด: ฉันควรสร้างคลาสรถยนต์เพื่อเก็บชิ้นส่วนทั้งหมดหรือไม่


10

ฉันมีรถยนต์มากมายในแอปพลิเคชัน C ++ ของฉันซึ่งบรรจุอยู่ภายใน RaceTrack

รถแต่ละคันประกอบด้วยชิ้นส่วนหลายร้อยชิ้น แต่ละส่วนขึ้นอยู่กับส่วนอื่น ๆ หรือสอง

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

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

แก้ไข:

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

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

คำตอบ:


24

ชิ้นส่วนรถยนต์ที่ดีอะไรที่กำลังนั่งอยู่บนสนามแข่งที่ทำทุกคน?

หากคลาสรถของคุณทั้งหมดถือชิ้นส่วนรถยนต์มันจะมีประโยชน์เหมือนกระเป๋าเปียกของชิ้นส่วน

การใช้

ในฐานะคนขับสิ่งที่ฉันต้องการคือสิ่งที่ฉันสามารถควบคุมได้ ที่ตอบสนองเมื่อฉันขอความเร็ว ที่จัดการเหมือนอยู่บนราง ที่สามารถหยุดในค่าเล็กน้อย

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

ฉีดพึ่งพา

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

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

DI เป็นจริงเกี่ยวกับการปฏิบัติตามหลักการ: แยกการใช้งานจากการก่อสร้าง

รถที่สามารถติดตั้งยางใหม่ที่ 90 ไมล์ต่อชั่วโมงอาจฟังดูดี แต่ฉันไม่คิดว่ามันจะชนะการแข่งขันใด ๆ ที่มีการติดตั้งยางในรถ

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

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

การก่อสร้าง

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

มันเป็นรูปแบบที่เรียบง่าย ในหลักสร้างกราฟวัตถุแล้วเรียกวิธีการพฤติกรรมหนึ่งอย่างบนวัตถุหนึ่งในกราฟวัตถุ แค่นั้นแหละ. นี่คือการสร้างสถานที่เท่านั้นและพฤติกรรมจะต้องอยู่ด้วยกัน

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

การทำเช่นนี้ในภาษาและไม่ใช้กรอบ DI บางส่วนหรือ IoC ภาชนะที่เรียกว่าDI บริสุทธิ์ มันใช้งานได้ดีมาก มีมาเป็นเวลานาน เราใช้เพียงแค่เรียกมันอ้างอิงผ่าน

เครื่องมือ DI

สิ่งที่เครื่องมือ DI ซื้อให้คุณคือรายละเอียดการก่อสร้างที่ย้ายไปอยู่ในภาษาอื่น (xml, json หรืออะไรก็ตาม) ที่บังคับแยกระหว่างการก่อสร้างและพฤติกรรม หากคุณไม่ไว้วางใจโปรแกรมเมอร์เพื่อนของคุณที่จะไม่ใช้newเมื่อพวกเขาไม่ควรสนใจ

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

หลักการออกแบบ

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

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

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

หลีกเลี่ยงการทำที่เรียกว่าต่อไปนี้หลักการพึ่งพาผกผัน โมดูลระดับสูง (เช่นคลาสรถยนต์) ไม่ควรขึ้นอยู่กับโมดูลระดับต่ำโดยตรง (เช่นคลาส GoodyearTire) ควรขึ้นอยู่กับสิ่งที่เป็นนามธรรม (เช่นอินเทอร์เฟซยาง)

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

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

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

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


มันจะเจ๋งถ้าคุณไม่ได้ใช้อุปมาอุปไมยในรถยนต์และลูกเรือเพื่อหาคำถามที่ใช้มันเพื่อเป็นตัวแทนของรหัส แต่ก็ยังเป็นคำตอบที่ดี
S. TarıkÇetin

6
และฉันคิดเสมอว่า Inversion of Control เกิดขึ้นเมื่อคุณเลี้ยวซ้าย แต่รถเลี้ยวขวา ...
mkrieger1

CandiedOrange ดังนั้นจึงไม่มีคลาสรถยนต์หากไม่มีส่วนต่อประสานที่มีความหมายและความรับผิดชอบที่ชัดเจน? และไม่มี Car.h ในโครงการของฉัน และเพื่อนร่วมงานมองดูรหัสของฉันและสงสัยว่ามันเป็นแอพพลิเคชั่นการจัดการชิ้นส่วนรถยนต์หรืออู่ซ่อมรถหรือไม่? :)
Anton Petrov

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

15

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

เลขที่

จุดฉีดของการพึ่งพานั้นไม่ได้เป็นการขัดขวางการพึ่งพา ค่อนข้างตรงกันข้าม

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

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

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


1
ในที่สุดคำอธิบายอย่างมีเหตุผลของdependency injectionแนวคิด
Anatoly techtonik

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

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

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

0

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

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

ใช่รถยนต์เป็นภาชนะบรรจุชิ้นส่วน แต่มันเป็นบรรจุภัณฑ์และความร่วมมือของชิ้นส่วนที่ประกอบขึ้นเป็นสิ่งที่ใหญ่กว่า: รถยนต์

ดังนั้นจริงๆไม่ รถยนต์ไม่ได้เป็นเพียงถุงโลหะและพลาสติกแบบสุ่ม มันเป็นเครื่องจักร

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


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