ทำไมความซับซ้อนของวงจรจึงมีความสำคัญสำหรับวิธีการเดียว?


10

ฉันกำลังใช้SonarLint สำหรับ Eclipseตั้งแต่เมื่อเร็ว ๆ นี้และมันช่วยฉันได้มาก อย่างไรก็ตามมันทำให้ฉันมีคำถามเกี่ยวกับความซับซ้อนของวัฏจักร

SonarLint ถือว่า CC ที่ยอมรับได้ของ 10 และมีบางกรณีที่ฉันเกินกว่านั้นประมาณ 5 หรือ 6 หน่วย ชิ้นส่วนเหล่านั้นเกี่ยวข้องกับตัวทำแผนที่ที่ค่าอาศัยตัวแปรที่แตกต่างกันตัวอย่างเช่น

  • ฟิลด์ A อาศัยสตริง sA;
  • ฟิลด์ B อาศัยสตริง sB;
  • ฟิลด์ C อาศัย String sC;
  • ฯลฯ ...

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


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

(ขออภัยในความผิดพลาดเล็กน้อยหากมี)


แก้ไข

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

อย่างไรก็ตามลิงค์ที่สอง ( เกี่ยวกับ anti-pattern ) นั้นมีประโยชน์อย่างมาก




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

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

1
สำหรับกรณีของคุณโดยเฉพาะฉันจะทำบางอย่างในวิธีการหลักของคุณเช่น "A = extractAFrom (sA);" สำหรับแต่ละฟิลด์ คุณอาจจะได้ชื่อที่ดีกว่าเพราะคุณรู้ว่าเขตข้อมูลจริงและการใช้งาน
Tin Man

คำตอบ:


32

สิ่งสำคัญที่นี่: "ความจุสมอง"

คุณจะเห็นหนึ่งในหลักของการทำงานของรหัสคือ ... ที่จะอ่าน และรหัสสามารถอ่านและเข้าใจได้ง่าย หรือยาก

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

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

และเมื่อคุณมีวิธีการขนาดเล็ก (มีชื่อที่ดี) ที่ประกอบด้วยเพียงไม่กี่บรรทัดและ CC ที่ต่ำมาก; จากนั้นสมองของคุณสามารถยอมรับ "บล็อก" นี้ได้อย่างง่ายดาย คุณอ่านมันคุณเข้าใจมัน; DONE

ในทางตรงกันข้ามถ้ารหัสของคุณมี CC สูงสมองของคุณจะใช้ "วงจร" จำนวนมากขึ้นเพื่อหักสิ่งที่เกิดขึ้น

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


9
ดังนั้นโดยทั่วไปจะไม่เกี่ยวกับทางด้านเทคนิคปัญหา แต่เกี่ยวกับมนุษย์ ? ฟังดูฉลาดจริงๆฉันไม่รู้ว่าฉันไม่เคยคิดมาก่อน ขอบคุณมาก!
Yassine Badache

4
ถ้าเป็นเช่นนั้นฉันขอแนะนำให้คุณซื้อ "Clean Code" โดย Robert Martin (คุณอาจพบไฟล์ PDF ฟรีบนอวน) คุณจะเห็นว่าการสร้างโค้ดที่อ่านได้เป็นหนึ่งในสิ่งที่สำคัญที่สุด แต่บ่อยครั้งที่ไม่สนใจโปรแกรมเมอร์ที่ดี
GhostCat แสดงความยินดี Monica C.

@YassineBadache CC ทำให้ยากต่อการทดสอบทุกซอกและซอกเล็กซอกน้อย
Tulains Córdova

นี่เป็นจุดเริ่มต้นของกระดาษ goto ของ Dijkstraด้วย
เซทแบตทิน

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

6

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

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


2
หาก "FieldA อาศัย String sA" เป็นสถานะ OP ฉันไม่เชื่อว่าการย้ายไปไว้ใน CalculateFieldA (String sA) ทำให้รหัสที่ซับซ้อนยิ่งขึ้น
Taemyr

2

ในระยะสั้น: มันคือทั้งหมดที่เกี่ยวกับการอ่านและการบำรุงรักษารหัสของคุณ

หากคุณมีวิธีการที่ยาวและซับซ้อนซึ่งมีจำนวนมาก (ซ้อนกัน) ifมันก็ยากที่จะบอกว่ามันทำอะไร หากคุณแยกวิธีการส่วนตัวและตั้งชื่ออย่างมีความหมายจะง่ายกว่ามาก


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

2

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

นอกเหนือจากนั้นผมเห็นด้วยกับคำตอบอื่น ๆ สำหรับการพิจารณาอื่น ๆ - กำลังจิตของนักพัฒนาหรือตัวบ่งชี้ของปัญหาที่อาจเกิดหรือ refactoringหรือตัวชี้วัดของการอ่านและการบำรุงรักษาของรหัส


0

CC เป็นเพียงฮิวริสติกและคะแนนที่ไม่ดีนั้นขึ้นอยู่กับหลาย ๆ สิ่ง

ที่กล่าวว่าคุณควรดู CC สูงเป็นสิ่งที่เน้นรหัสที่สามารถ / ควรจะ refactored คุณบอกว่าการย้ายifคำสั่งไปยังวิธีอื่นกำลังซ่อนปัญหา แต่มีรูปแบบที่คุณสามารถทำให้เป็นนามธรรมแทนที่จะคัดลอกการวาง n ครั้งได้หรือไม่ ถ้ามันเป็นif-elseสายยาวคุณสามารถเปลี่ยนมันให้เป็นคำสั่งสลับหรืออาจจะใช้ความหลากหลายหรืออะไรอย่างอื่น? หากมีการทำรังลึกประโยคคำสั่งบางส่วนของคุณสามารถเข้าร่วมหรือไม่หรือมันบ่งบอกถึงความรับผิดชอบแยกต่างหากที่ควรแบ่งออกเป็นชั้นเรียนที่แตกต่างกัน?


0

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

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

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

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


0

มันลงมาถึงเวลาที่ใช้ในการมอง (รอบสมอง) ที่โค้ดและทำความเข้าใจกับสิ่งที่โค้ดกำลังทำอยู่

  • พิจารณาวิธี 10 บรรทัด - อาจใช้เวลาสักครู่เพื่อทำความเข้าใจกับสิ่งที่กำลังทำ
  • พิจารณาวิธี 100 line - อาจใช้เวลาหนึ่งชั่วโมงหรือมากกว่านั้นเพื่อเข้าใจสิ่งที่กำลังทำอยู่
  • พิจารณาวิธี 1,000 line - อาจใช้เวลาหนึ่งวันหรือมากกว่านั้นในการทำความเข้าใจสิ่งที่กำลังทำ

วิธีการที่ใหญ่กว่านั้นยากที่จะทดสอบและยากที่จะทำนายว่าพฤติกรรมแบบไหนที่จะเกิดขึ้นได้

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

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

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


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