เมื่อใดที่จะไม่ใช้หลักการผกผันของการพึ่งพาอาศัย


43

ฉันกำลังพยายามหา SOLID อยู่ ดังนั้นหลักการการพึ่งพาการพึ่งพาจึงหมายความว่าสองคลาสใด ๆ ควรสื่อสารผ่านอินเทอร์เฟซไม่ใช่โดยตรง ตัวอย่าง: หากclass Aมีวิธีที่คาดว่าตัวชี้ไปยังวัตถุของการพิมพ์แล้ววิธีนี้ควรจริงคาดว่าวัตถุของการพิมพ์class B abstract base class of Bสิ่งนี้จะช่วยในการเปิด / ปิดเช่นกัน

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

เหตุผลที่ฉันสงสัยก็เพราะเราจ่ายราคาบางอย่างสำหรับการทำตามหลักการนี้ บอกว่าฉันต้องใช้คุณสมบัติZนี้ หลังจากการวิเคราะห์ผมสรุปได้ว่าคุณลักษณะที่Zประกอบด้วยฟังก์ชั่นA, และB Cฉันจะสร้างซุ้มระดับZที่ผ่านอินเตอร์เฟซที่ใช้เรียนA, และB Cฉันเริ่มต้นการเข้ารหัสและการดำเนินการในบางจุดที่ผมทราบดีว่างานที่Zจริงประกอบด้วยฟังก์ชั่นA, และB Dตอนนี้ฉันต้องทำให้เสียCอินเตอร์เฟส, Cคลาสต้นแบบและเขียนDอินเตอร์เฟสและคลาสแยกกัน หากไม่มีอินเทอร์เฟซจะต้องเปลี่ยนคลาสเท่านั้น

กล่าวอีกนัยหนึ่งคือการเปลี่ยนแปลงบางสิ่งฉันต้องเปลี่ยน 1. ผู้โทร 2. ส่วนต่อประสาน 3. การประกาศ 4. การดำเนินการ ในไพ ธ อนการใช้งานร่วมกันโดยตรงฉันจะต้องเปลี่ยนเฉพาะการใช้งานเท่านั้น


13
การผกผันของการพึ่งพาเป็นเพียงเทคนิคดังนั้นจึงควรใช้เมื่อจำเป็นเท่านั้น ... ไม่ จำกัด ระดับที่สามารถนำไปใช้ได้ดังนั้นหากคุณนำไปใช้ทุกที่คุณจะพบกับขยะ: เช่นเดียวกับสถานการณ์อื่น ๆ - เทคนิคเฉพาะ
Frank Hileman

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

@rwong อินเทอร์เฟซจับภาพ invariants ตามสัญญาเฉพาะเมื่อคุณใช้ภาษาที่สนับสนุน invariants ตามสัญญา ในภาษาทั่วไป (Java, C #), อินเตอร์เฟสเป็นเพียงชุดของลายเซ็น API การเพิ่มส่วนต่อประสานที่ไม่จำเป็นเพียงลดระดับการออกแบบ
Frank Hileman

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

คำตอบ:


87

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

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

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

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


19
การแนะนำครั้งแรกของฉันเกี่ยวกับ SOLID คือประมาณ 15 ปีที่แล้วในระบบใหม่ที่เรากำลังสร้าง เราทุกคนดื่มคนช่วย kool หากใครพูดถึงสิ่งที่ฟังดูเหมือน YAGNI เราก็เหมือน "Pfffft ... plebeian" ฉันได้รับเกียรติ (สยองขวัญ?) จากการดูระบบที่พัฒนาขึ้นในช่วงทศวรรษหน้า มันกลายเป็นความยุ่งเหยิงที่ไม่เคยมีใครเข้าใจแม้แต่เราก็เป็นผู้ก่อตั้ง สถาปนิกชอบ SOLID คนที่หาเลี้ยงชีพด้วยรักแท้ YAGNI ไม่สมบูรณ์ แต่ YAGNI ใกล้จะสมบูรณ์แบบและควรเป็นค่าเริ่มต้นหากคุณไม่รู้ว่าคุณกำลังทำอะไรอยู่ :-)
Calphool

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

22
ความรู้สึกต่อต้านต่อต้าน SOLID มากมายที่นี่ SOLID และ YAGNI ไม่ได้เป็นปลายทั้งสองของสเปกตรัม พวกมันเหมือนกับพิกัด X และ Y บนแผนภูมิ ระบบที่ดีมีรหัสฟุ่มเฟือยน้อยมาก (YAGNI) และเป็นไปตามหลักการที่เป็นของแข็ง
สตีเฟ่น

31
Meh, (a) ฉันไม่เห็นด้วยที่ SOLID = enterprisey และ (b) ประเด็นทั้งหมดของ SOLID คือเรามักจะเป็นนักพยากรณ์ที่แย่มากในสิ่งที่จำเป็น ฉันต้องเห็นด้วยกับ @Stephen ที่นี่ YAGNI กล่าวว่าเราไม่ควรพยายามคาดการณ์ข้อกำหนดในอนาคตที่ไม่ชัดเจนในวันนี้ SOLID กล่าวว่าเราควรคาดหวังว่าการออกแบบจะพัฒนาไปตามกาลเวลาและใช้เทคนิคง่ายๆเพื่ออำนวยความสะดวก พวกเขาไม่ได้เป็นพิเศษร่วมกัน ทั้งสองเป็นเทคนิคสำหรับการปรับให้เข้ากับความต้องการที่เปลี่ยนแปลง ปัญหาที่แท้จริงเกิดขึ้นเมื่อคุณพยายามออกแบบให้มีข้อกำหนดที่ไม่ชัดเจนหรือห่างไกลมาก
Aaronaught

8
"คุณสามารถสลับการอ่านจากไฟล์สำหรับเน็ตเวิร์ก aa ได้อย่างง่ายดาย" - นี่เป็นตัวอย่างที่ดีที่คำอธิบาย DI ที่ง่ายเกินไปทำให้ผู้คนหลงทาง บางครั้งผู้คนคิดว่า (มีผลบังคับใช้) "วิธีนี้จะใช้ a Fileดังนั้นจะใช้IFileงานแทน" แล้วพวกเขาก็ไม่สามารถได้อย่างง่ายดายทดแทนกระแสเครือข่ายเพราะพวกเขามากกว่าที่เรียกร้องอินเตอร์เฟซและมีการดำเนินงานในวิธีการที่ไม่ได้ใช้งานที่ไม่ได้นำไปใช้กับซ็อกเก็ตเพื่อให้ซ็อกเก็ตไม่สามารถดำเนินการIFile IFileหนึ่งในสิ่งที่ DI ไม่ได้เป็น bullet เงินสำหรับเป็นที่ประดิษฐ์แนวคิดขวา (อินเตอร์เฟซ) :-)
สตีฟเจสซอพ

11

ในคำพูดของคนธรรมดา:

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

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

ในทางกลับกันการเขียนโปรแกรมด้วยอินเทอร์เฟซและ OOD สามารถนำความสุขกลับไปสู่การเขียนโปรแกรมค้างในบางครั้ง

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


5
ฉันไม่รู้ว่า OP หรือภาษาใดที่ IDE ใช้อยู่ แต่ใน VS 2013 มันเป็นเรื่องง่ายมากที่จะทำงานกับส่วนต่อประสานแยกส่วนต่อประสานและนำไปใช้งานและสำคัญหากใช้ TDD ไม่มีค่าใช้จ่ายในการพัฒนาเพิ่มเติมสำหรับการพัฒนาโดยใช้หลักการเหล่านี้
stephenbayer

ทำไมคำตอบนี้ถึงพูดถึง DI หากคำถามเกี่ยวกับกรมทรัพย์สินทางปัญญา? กรมทรัพย์สินทางปัญญาเป็นแนวคิดจากปี 1990 ในขณะที่ DI มาจากปี 2004 พวกเขาแตกต่างกันมาก
Rogério

1
(ความคิดเห็นก่อนหน้าของฉันมีไว้สำหรับคำตอบอื่นไม่สนใจเลย) "การเขียนโปรแกรมไปยังส่วนต่อประสาน" นั้นเป็นเรื่องทั่วไปมากกว่า DIP แต่มันไม่ได้เกี่ยวกับการทำให้ทุกคลาสใช้อินเทอร์เฟซแยกกัน และจะทำให้ "การทดสอบ / การเยาะเย้ย" ทำได้ง่ายขึ้นหากเครื่องมือการทดสอบ / การเยาะเย้ยนั้นประสบกับข้อ จำกัด ที่ร้ายแรง
Rogério

@ Rogérioโดยปกติเมื่อใช้ DI ไม่ทุกคลาสใช้อินเทอร์เฟซแยกต่างหาก อินเทอร์เฟซเดียวที่นำมาใช้โดยหลายคลาสเป็นเรื่องปกติ
Tulains Córdova

@ Rogérioฉันแก้ไขคำตอบของฉันทุกครั้งที่ฉันพูดถึง DI ฉันหมายถึงกรมทรัพย์สินทางปัญญา
Tulains Córdova

9

ใช้การผกผันของการพึ่งพาที่เหมาะสม

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

หากคุณมีกลุ่มของวัตถุที่ใช้ภายในโมดูลที่ไม่ได้สัมผัสกับโมดูลอื่นหรือนำกลับมาใช้ที่ใดก็ได้ก็อาจไม่คุ้มค่ากับความพยายามในการใช้ DI

มีสองที่ที่ DI ควรใช้โดยอัตโนมัติในความคิดของฉัน:

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

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

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

DI เป็นเครื่องมือที่ยอดเยี่ยม แต่เช่นเดียวกับเครื่องมือ * ใด ๆ มันสามารถใช้มากเกินไปหรือใช้ผิดวัตถุประสงค์

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


3
เกิดอะไรขึ้นถ้า "ปัญหาของคุณ" เป็นรูในกำแพง? เลื่อยจะไม่ลบมัน มันจะทำให้แย่ลง ;)
Mason Wheeler

3
@MasonWheeler ที่มีประสิทธิภาพและสนุกกับการใช้งาน "หลุมในผนัง" สามารถกลายเป็น "ประตู" ซึ่งเป็นสินทรัพย์ที่มีประโยชน์ :-)

1
คุณไม่สามารถใช้เลื่อยเพื่อทำปะสำหรับรูได้หรือไม่?
JeffO

ในขณะที่มีข้อได้เปรียบบางประการในการมีชนิดที่ไม่สามารถขยายได้โดยผู้ใช้Stringแต่ก็มีหลายกรณีที่การรับรองทางเลือกจะเป็นประโยชน์หากประเภทนั้นมีชุดปฏิบัติการเสมือนจริงที่ดี (เช่นคัดลอกสตริงย่อยไปยังส่วนที่ระบุของshort[]a สตริงย่อยทำหรืออาจมีเพียง ASCII เท่านั้นลองคัดลอกสตริงย่อยที่เชื่อว่ามีเฉพาะ ASCII ไปยังส่วนที่ระบุของbyte[]ฯลฯ ) มันแย่มากเฟรมเวิร์กไม่มีประเภทสตริงที่ใช้อินเทอร์เฟซที่เกี่ยวข้องกับสตริง
supercat

1
ทำไมคำตอบนี้ถึงพูดถึง DI หากคำถามเกี่ยวกับกรมทรัพย์สินทางปัญญา? กรมทรัพย์สินทางปัญญาเป็นแนวคิดจากปี 1990 ในขณะที่ DI มาจากปี 2004 พวกเขาแตกต่างกันมาก
Rogério

5

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

เหตุผลที่ฉันสงสัยก็เพราะเราจ่ายค่าใช้จ่ายสำหรับการทำตามหลักการนี้ บอกว่าฉันต้องใช้งานฟีเจอร์ Z หลังจากการวิเคราะห์ฉันสรุปว่าฟีเจอร์ Z ประกอบด้วยฟังก์ชั่น A, B และ C ฉันสร้างคลาสฟาสซิสต์ Z ที่ผ่านอินเตอร์เฟสใช้คลาส A, B และ C ฉันเริ่มเขียนโค้ด การใช้งานและในบางจุดฉันรู้ว่างาน Z จริง ๆ แล้วประกอบด้วยการทำงาน A, B และ D ตอนนี้ฉันต้องการที่จะแยกส่วน C interface, C class prototype และเขียน D interface แยกต่างหากและ class หากไม่มีส่วนต่อประสานคลาสจะต้องเปลี่ยนคลื่นเท่านั้น

เพื่อใช้ประโยชน์จากกรมทรัพย์สินทางปัญญาอย่างแท้จริงคุณจะต้องสร้างคลาส Z ก่อนและเรียกมันว่าการทำงานของคลาส A, B และ C (ซึ่งยังไม่พัฒนา) สิ่งนี้จะให้ API สำหรับคลาส A, B และ C จากนั้นคุณไปและสร้างคลาส A, B และ C และกรอกรายละเอียด คุณควรสร้าง abstractions ที่คุณต้องการอย่างมีประสิทธิภาพในขณะที่คุณกำลังสร้างคลาส Z ขึ้นอยู่กับสิ่งที่คลาส Z ต้องการทั้งหมด คุณสามารถเขียนแบบทดสอบรอบคลาส Z ก่อนที่จะเขียนคลาส A, B หรือ C

โปรดจำไว้ว่ากรมทรัพย์สินทางปัญญากล่าวว่า "โมดูลระดับสูงไม่ควรขึ้นอยู่กับโมดูลระดับต่ำทั้งสองควรขึ้นอยู่กับบทคัดย่อ"

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

จะไม่มีคลาส D เพราะคุณได้ผลว่า Z ต้องการ A, B และ C ก่อนที่จะเขียน การเปลี่ยนแปลงข้อกำหนดเป็นเรื่องที่ต่างออกไปโดยสิ้นเชิง


5

คำตอบสั้น ๆ คือ "แทบจะไม่เคย" แต่จริงๆแล้วมีบางแห่งที่กรมทรัพย์สินทางปัญญาไม่สมเหตุสมผล:

  1. โรงงานหรือผู้สร้างซึ่งมีหน้าที่สร้างวัตถุ นี่คือ "leaf nodes" ในระบบที่รวบรวม IoC อย่างสมบูรณ์ ณ จุดหนึ่งบางสิ่งบางอย่างจะต้องสร้างวัตถุของคุณจริงและไม่สามารถพึ่งพาสิ่งอื่นใดที่จะทำ ในหลายภาษาคอนเทนเนอร์ IoC สามารถทำเพื่อคุณได้ แต่บางครั้งคุณจำเป็นต้องทำด้วยวิธีที่ล้าสมัย

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

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

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

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

อาจมีมากกว่านั้น เหล่านี้เป็นคนที่ฉันเห็นในค่อนข้างพื้นฐานบ่อย


"เมื่อใดก็ตามที่คุณทำงานในภาษาแบบไดนามิก"
เควิน

ไม่มี? ฉันทำงาน JavaScript มากมายและมันก็ใช้ได้ดีเหมือนกัน ถึงแม้ว่า "O" และ "I" ใน SOLID อาจจะพร่ามัวเล็กน้อย
Aaronaught

อืม ... ฉันพบว่าประเภทชั้นหนึ่งของไพ ธ อนรวมกับการพิมพ์เป็ดทำให้มันค่อนข้างจำเป็นน้อยลง
เควิน

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

1
@Kevin python เป็นภาษาแรกแทบจะไม่มีการพิมพ์แบบไดนามิกหรือ mocks หลวม นอกจากนี้ยังไม่เกี่ยวข้องอย่างสมบูรณ์ คำถามไม่ใช่ประเภทของวัตถุ แต่เป็นวิธีการ / สร้างวัตถุนั้น เมื่อวัตถุสร้างการขึ้นต่อกันของตัวเองคุณจะถูกบังคับให้ทำการทดสอบหน่วยว่าควรจะมีรายละเอียดการใช้งานอย่างไรโดยการทำสิ่งที่น่ากลัวเช่นการทำลายตัวสร้างคลาสที่ API สาธารณะไม่ได้กล่าวถึง และการลืมเกี่ยวกับการทดสอบพฤติกรรมการผสมและการสร้างวัตถุนั้นนำไปสู่การแต่งงานกันอย่างแน่นหนา การพิมพ์เป็ดไม่สามารถแก้ปัญหาเหล่านั้นได้
Aaronaught

2

สัญญาณบางอย่างที่คุณอาจใช้กรมทรัพย์สินทางปัญญาในระดับเล็กเกินไปซึ่งมันไม่ได้ให้คุณค่า:

  • คุณมีคู่ C / CImpl หรือ IC / C ด้วยการใช้งานอินเทอร์เฟซนั้นเพียงครั้งเดียว
  • ลายเซ็นในอินเทอร์เฟซและการใช้งานของคุณตรงกับแบบหนึ่งต่อหนึ่ง (ละเมิดหลักการ DRY)
  • คุณเปลี่ยน C และ CImpl บ่อยครั้งในเวลาเดียวกัน
  • C เป็นโครงการภายในของคุณและไม่ได้แชร์ภายนอกโครงการของคุณเป็นห้องสมุด
  • คุณผิดหวังจาก F3 ใน Eclipse / F12 ใน Visual Studio ที่นำคุณไปยังส่วนต่อประสานแทนที่จะเป็นคลาสจริง

หากนี่คือสิ่งที่คุณเห็นคุณอาจจะดีกว่าเพียงแค่ให้ Z โทร C โดยตรงและข้ามอินเทอร์เฟซ

นอกจากนี้ฉันไม่คิดว่าการตกแต่งวิธีการโดยการพึ่งพาเฟรมเวิร์กการฉีด / ไดนามิกพร็อกซี (Spring, Java EE) เหมือนกับวิธีที่เป็นจริงของ SOLID - นี่เป็นรายละเอียดเพิ่มเติมเกี่ยวกับวิธีการตกแต่งวิธีการทำงานในกองเทคโนโลยี ชุมชน Java EE พิจารณาว่าเป็นการปรับปรุงที่คุณไม่ต้องการคู่ Foo / FooImpl เหมือนที่คุณเคยใช้ ( อ้างอิง ) ในทางตรงกันข้าม Python รองรับการตกแต่งฟังก์ชั่นเป็นคุณสมบัติภาษาชั้นหนึ่ง

ดูโพสต์บล็อกนี้ด้วย


0

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

จุดผกผันของการพึ่งพาคือคุณเลือกคว่ำการพึ่งพาที่ทำให้สิ่งต่าง ๆ ยุ่งเหยิง คนที่ควรไปจาก A ถึง B ถึง C ยังคงทำมันคนที่ไปจาก C ถึง A ที่ตอนนี้ไปจาก A ถึง C

ผลลัพธ์ควรเป็นกราฟการพึ่งพาที่ไม่มีรอบ - DAG มีเครื่องมือต่าง ๆ ที่จะตรวจสอบคุณสมบัตินี้และวาดกราฟ

สำหรับคำอธิบายฟูลเลอร์ดูบทความนี้ :

สาระสำคัญของการใช้หลักการการพึ่งพาการพึ่งพาอย่างถูกต้องคือ:

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

การดำเนินการยังคงอยู่ที่มันอยู่ แต่อินเทอร์เฟซมีฟังก์ชั่นที่แตกต่างกันในขณะนี้ (และใช้ศัพท์แสง / ภาษาที่แตกต่างกัน) โดยอธิบายสิ่งที่การใช้โค้ดสามารถทำได้ ย้ายไปที่แพ็คเกจนั้น โดยการไม่วางอินเทอร์เฟซและการนำไปใช้ในแพ็คเกจเดียวกันการพึ่งพา (ทิศทางของ) จะถูกคว่ำจากผู้ใช้→การนำไปใช้กับการนำไปใช้งาน→ผู้ใช้

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