มีอะไรผิดปกติกับการอ้างอิงแบบวงกลม?


160

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

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

แก้ไข:ฉันไม่ได้ถามเกี่ยวกับการอ้างอิงแบบวงกลมที่เป็นเนื้อเดียวกันเช่นที่อยู่ในรายการที่ลิงก์สองเท่าหรือตัวชี้ไปยังผู้ปกครอง คำถามนี้ถามเกี่ยวกับการอ้างอิงแบบวงกลม "ขอบเขตที่กว้างขึ้น" เช่น libA การโทร libB ซึ่งโทรกลับไปที่ libA แทน 'โมดูล' สำหรับ 'lib' หากคุณต้องการ ขอบคุณสำหรับคำตอบทั้งหมด!


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

1
@ Luv2code มันจะโง่ถ้าคุณตัดและวางรหัสระหว่างโครงการหรืออาจเป็นไปได้เมื่อทั้งสองโครงการรวบรวมและเชื่อมโยงในรหัสเดียวกัน หากพวกเขาแบ่งปันทรัพยากรเช่นนี้ให้นำไปไว้ในห้องสมุด
dash-tom-bang

คำตอบ:


220

มีหลายสิ่งที่ผิดปกติในการอ้างอิงแบบวงกลม:

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

  • การอ้างอิงชุดประกอบแบบวงกลมป้องกันการเชื่อมโยงแบบคงที่เนื่องจาก B ขึ้นอยู่กับ A แต่ A ไม่สามารถประกอบได้จนกว่า B จะเสร็จสมบูรณ์

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

  • การอ้างอิงวัตถุแบบวงกลมยังทำให้ไม่สามารถพึ่งพาการฉีดได้ทำให้ลดความสามารถในการทดสอบระบบของคุณได้อย่างมาก

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

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

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

โปรดคิดถึงเด็ก ๆ หลีกเลี่ยงการอ้างอิงแบบวงกลมทุกครั้งที่คุณทำได้


32
ฉันรู้สึกซาบซึ้งเป็นพิเศษในท้ายที่สุด "การรับรู้ทางปัญญา" เป็นสิ่งที่ฉันรู้ตัวมาก แต่ไม่เคยมีคำศัพท์สั้นกระชับเลย
dash-tom-bang

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

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

3
@ BlueRaja-DannyPflughoeft: ฉันคิดว่ารูปแบบการต่อต้านเช่นเดียวกับผู้ปฏิบัติงานอื่น ๆ ของ DI เพราะ (ก) มันไม่ชัดเจนว่าทรัพย์สินเป็นที่พึ่งและ (b) วัตถุที่ถูก "ฉีด" ไม่สามารถทำได้อย่างง่ายดาย ติดตามค่าคงที่ของมันเอง ยิ่งไปกว่านั้นเฟรมเวิร์กที่มีความซับซ้อน / เป็นที่นิยมมากที่สุดอย่าง Castle Windsor ไม่สามารถให้ข้อความแสดงข้อผิดพลาดที่เป็นประโยชน์หากไม่สามารถแก้ไขการพึ่งพาได้ คุณจบลงด้วยการอ้างอิงโมฆะที่น่ารำคาญแทนคำอธิบายรายละเอียดของการพึ่งพาซึ่งในตัวสร้างซึ่งไม่สามารถแก้ไขได้ เพียงเพราะคุณสามารถไม่ได้หมายความว่าคุณควร
Aaronaught

3
ฉันไม่ได้อ้างว่าเป็นการฝึกฝนที่ดีฉันแค่ชี้ให้เห็นว่ามันเป็นไปไม่ได้อย่างที่อ้างไว้ในคำตอบ
BlueRaja - Danny Pflughoeft

22

การอ้างอิงแบบวงกลมคือการคัปปลิ้งสองเท่าของการอ้างอิงแบบไม่เป็นวงกลม

หาก Foo รู้จัก Bar และ Bar รู้เกี่ยวกับ Foo คุณมีสองสิ่งที่ต้องเปลี่ยน (เมื่อความต้องการมาถึง Foos และ Bars จะต้องไม่รู้จักซึ่งกันและกัน) หาก Foo รู้จัก Bar แต่ Bar ไม่รู้เกี่ยวกับ Foo คุณสามารถเปลี่ยน Foo ได้โดยไม่ต้องแตะ Bar

การอ้างอิงตามวัฏจักรอาจทำให้เกิดปัญหา bootstrapping อย่างน้อยก็ในสภาพแวดล้อมที่มีอายุการใช้งานนาน (บริการที่ปรับใช้สภาพแวดล้อมการพัฒนาบนพื้นฐานของรูปภาพ) ซึ่ง Foo ขึ้นอยู่กับ Bar ที่ทำงานเพื่อโหลด แต่ Bar ก็ขึ้นอยู่กับ Foo ที่ทำงานด้วย ภาระ


17

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

ผู้คนมักจะดูความซับซ้อนของคลาส (/ function / file / etc.) และลืมว่าคุณควรพิจารณาถึงความซับซ้อนของหน่วยที่เล็กที่สุดที่แยกได้ (encapsulatable) การมีการพึ่งพาแบบวนเพิ่มขนาดของหน่วยนั้นอาจจะมองไม่เห็น (จนกว่าคุณจะเริ่มพยายามเปลี่ยนไฟล์ 1 และตระหนักว่าต้องมีการเปลี่ยนแปลงในไฟล์ 2-127)


14

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


10

อืม ... นั่นขึ้นอยู่กับความหมายของการพึ่งพาแบบวงกลมเพราะจริงๆแล้วมันมีการพึ่งพาแบบวงกลมซึ่งฉันคิดว่ามีประโยชน์มาก

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


1
จะไม่เป็นต้นไม้เหรอ?
Conrad Frix

@ คอนราด: ฉันคิดว่ามันอาจจะคิดว่าเป็นต้นไม้ใช่ ทำไม?
Billy ONeal

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

5
การอ้างอิงแบบวงกลมคือถ้าหนึ่งในชายด์ของโหนดวนกลับไปที่บรรพบุรุษ
Matt Olenik

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

9

เป็นเหมือนไก่หรือไข่ปัญหา

มีหลายกรณีที่การอ้างอิงแบบวงกลมหลีกเลี่ยงไม่ได้และมีประโยชน์ แต่ตัวอย่างเช่นในกรณีต่อไปนี้มันไม่ทำงาน:

โครงการ A ขึ้นอยู่กับโครงการ B และ B ขึ้นอยู่กับ A. A จะต้องรวบรวมเพื่อใช้ใน B ซึ่งต้องรวบรวม B ก่อนหน้า A ซึ่งต้องใช้ B เพื่อรวบรวมก่อน A ...


6

ในขณะที่ฉันเห็นด้วยกับความคิดเห็นส่วนใหญ่ที่นี่ฉันขอร้องเป็นกรณีพิเศษสำหรับการอ้างอิงแบบวงกลม "หลัก" / "เด็ก"

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

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

อีกทางเลือกหนึ่งคือการส่งผ่านข้อมูลทั้งหมดที่เด็กอาจต้องการในตัวสร้างซึ่งจบลงด้วยการเป็นเพียงน่ากลัวธรรมดา


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

5

ในแง่ของฐานข้อมูลการอ้างอิงแบบวงกลมที่มีความสัมพันธ์แบบ PK / FK ที่เหมาะสมทำให้ไม่สามารถแทรกหรือลบข้อมูลได้ หากคุณไม่สามารถลบออกจากตาราง a เว้นแต่ว่าข้อมูลจะหายไปจากตาราง b และคุณไม่สามารถลบออกจากตาราง b ได้เว้นแต่ว่าข้อมูลนั้นจะหายไปจากตาราง A คุณจะไม่สามารถลบได้ เช่นเดียวกันกับเม็ดมีด นี่คือสาเหตุที่ฐานข้อมูลจำนวนมากไม่อนุญาตให้คุณตั้งค่าการปรับปรุงเรียงซ้อนหรือลบหากมีการอ้างอิงแบบวงกลมเพราะในบางจุดอาจเป็นไปไม่ได้ ใช่คุณสามารถตั้งค่าความสัมพันธ์ประเภทนี้โดยที่ PK / Fk ได้รับการประกาศอย่างเป็นทางการ แต่จากนั้นคุณจะ (100% ของเวลาในประสบการณ์ของฉัน) มีปัญหาเรื่องความถูกต้องของข้อมูล นั่นเป็นเพียงการออกแบบที่ไม่ดี


4

ฉันจะใช้คำถามนี้จากการสร้างแบบจำลองมุมมอง

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

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

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

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

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

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

(หมายเหตุ: นี่คือเอนเอียงเล็กน้อยกับการออกแบบฐานข้อมูล แต่ฉันจะพนันได้ว่ามันใช้ได้กับพื้นที่อื่นเช่นกัน)


2

ฉันจะตอบคำถามนั้นด้วยคำถามอื่น:

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

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


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

1

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


1

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

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

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

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


1

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

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


11
อืม .. ตัวเก็บขยะใด ๆ เพิ่มขึ้นเป็นอย่างนี้ไม่ใช่ตัวเก็บขยะที่แท้จริง
Billy ONeal

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

4
ดูsct.ethz.ch/teaching/ws2005/semspecver/slides/takano.pdfซึ่งอธิบายข้อเสียของตัวรวบรวมขยะประเภทต่าง ๆ - ถ้าทำเครื่องหมายและกวาดและเริ่มปรับให้เหมาะสมเพื่อลดเวลาหยุดที่ยาวนาน (เช่นการสร้างรุ่น) คุณเริ่มมีปัญหากับโครงสร้างแบบวงกลม (เมื่อวัตถุทรงกลมมีรุ่นต่างกัน) หากคุณนับจำนวนการอ้างอิงและเริ่มแก้ไขปัญหาการอ้างอิงแบบวนรอบคุณจะพบว่าเวลาหยุดที่ยาวนานนั้นเป็นลักษณะของเครื่องหมายและการกวาด
Ken Bloom

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

1
ในวัตถุประสงค์ -c การอ้างอิงแบบวนรอบทำให้นับจำนวนการอ้างอิงไม่ถึงศูนย์เมื่อคุณปล่อยซึ่งจะไปเก็บขยะ
DexterW

-2

ในความคิดของฉันมีการอ้างอิงที่ไม่ จำกัด ทำให้การออกแบบโปรแกรมง่ายขึ้น แต่เราทุกคนรู้ว่าภาษาการเขียนโปรแกรมบางภาษาขาดการสนับสนุนในบริบทบางอย่าง

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

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

ฉันจะบอกว่านั่นเป็นปัญหากับเครื่องมือไม่ใช่ปัญหากับหลักการ


การเพิ่มความเห็นหนึ่งประโยคไม่ได้ช่วยสนับสนุนการโพสต์หรืออธิบายคำตอบ คุณช่วยอธิบายเรื่องนี้ได้ไหม?

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

ฉันพบว่ามันทำให้การเรียกใช้และการใช้งานของคุณง่ายขึ้น แต่โดยทั่วไปแล้วการพูดในท้ายที่สุดจะทำให้การบำรุงรักษาซอฟต์แวร์ทำได้ยากขึ้นเนื่องจากคุณพบว่าการเปลี่ยนแปลงเล็กน้อยมีผลกระทบแบบซ้อน A ทำให้การโทรเป็น B ซึ่งทำให้การโทรกลับไปที่ A ซึ่งทำให้การโทรกลับไปที่ B ... ฉันพบว่ามันยากที่จะเข้าใจผลกระทบของการเปลี่ยนแปลงของลักษณะนี้โดยเฉพาะอย่างยิ่งเมื่อ A และ B เป็น polymorphic
dash-tom-bang
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.