ฉันจะกำหนดและวัดความเรียบง่ายในโค้ดได้อย่างไร


13

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

ฉันจะกำหนดความเรียบง่ายในโค้ดได้อย่างไร มีซอฟต์แวร์การวัดและตัวชี้วัดใดบ้างที่ใช้ในการวัดความเรียบง่ายของโค้ด


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

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

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

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

คำตอบ:


16

ตัวชี้วัดส่วนใหญ่นิยมใช้สำหรับวัดความซับซ้อน (หรือความเรียบง่ายถ้าคุณใช้ความเรียบง่ายที่จะเป็นตรงข้ามของความซับซ้อน) เป็นของ McCabe Cyclomatic ซับซ้อนและสคีดตัวชี้วัดความซับซ้อน

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

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

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

Fan-in และ fan-out เป็นอีกสองตัวชี้วัดที่เกี่ยวข้องกับการไหลของข้อมูล ตามที่นิยามไว้ที่นี่ fan in คือผลรวมของโพรซีเดอร์ที่เรียกว่าพารามิเตอร์ที่อ่านและตัวแปรโกลบอลที่อ่านและรวมถึง fan out คือผลรวมของโพรซีเดอร์ที่เรียกใช้โพรซีเดอร์ที่กำหนดพารามิเตอร์ที่เขียนไป (เปิดเผยต่อผู้ใช้ภายนอก และตัวแปรทั่วโลกที่เขียนถึง อีกครั้ง fan-in และ fan-out ระดับสูงอาจบ่งบอกถึงโมดูลที่อาจเข้าใจยาก

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

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


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

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

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

7

แทนที่จะดูที่โหมดทางการของการนิยามความเรียบง่ายฉันอยากจะนิยามความเรียบง่ายเป็นคุณลักษณะของคุณภาพการเขียนโค้ด

ฉันไม่ได้วัดความเรียบง่าย แต่เมื่อใดที่คุณเรียกว่าอะไรที่เรียบง่ายหรือไม่

1.
การสำรวจเส้นทางโค้ด:การเลื่อนดูโค้ดทำได้ง่ายเพียงใด? มันง่ายที่จะระบุตำแหน่งที่ฟังก์ชั่น API ถูกเขียน? มันง่ายที่จะเข้าใจ flow call เช่นวิธีการใดที่เรียกผู้อื่น (และเพราะอะไร) - มีกลไกของรัฐที่ดีหรือใช้อัลกอริธึมที่ระบุอย่างหมดจดหรือไม่

เมื่อการสำรวจรหัสเป็นเรื่องง่ายรหัสนั้นง่ายต่อการติดตาม

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

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

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

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

คำถามง่าย ๆ ที่ฉันถามโดยทั่วไปมีดังนี้: ถ้าแทนที่จะเป็นโปรแกรมถ้าฉันขอให้มนุษย์ทำหน้าที่เดียวกันฉันจะกรอกข้อมูลนี้ในแบบฟอร์มกระดาษหรือไม่? ถ้าไม่ฉันไม่ง่ายพอที่นี่

ฉันจะไม่พูดว่ารายการนี้หมดจด แต่ฉันเดาว่าเกณฑ์เป็นวิธีที่ง่ายหรือยากในการใช้และแก้ไขซอฟต์แวร์ นั่นเป็นเรื่องง่าย


1
เขาขอการวัดและตัวชี้วัด สิ่งเหล่านี้เป็นอัตวิสัยดังนั้นฉันไม่คิดว่าพวกเขาตรงประเด็นมาก
psr

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

"ใช้ชื่อที่เป็นไปไม่ได้ที่จะเข้าใจผิด" - IMHO นี่คือการตั้งเป้าหมายสูงเกินไปไปสู่เป้าหมายที่ไม่สมจริงและเป็นไปไม่ได้ ฉันค่อนข้างจะไม่พยายามที่จะชัดเจนและเพียงแค่พูดว่า "ใช้ชื่อที่ชัดเจนและไม่น่าสงสัย"
PéterTörök

@ PéterTörökฉันเห็นด้วย ฉันคิดว่าโดยปกติแล้วในหลาย ๆ องค์กรกฎระเบียบที่กำหนดไว้อย่างชัดเจนมากสำหรับการตั้งชื่อการประชุมและยังคงมีความสับสนเกี่ยวกับความตั้งใจของตัวแปรเฉพาะที่มีอยู่ ดังนั้นการเน้นคือการบอกว่าความชัดเจนของจุดประสงค์นั้นมีความเรียบง่ายตรงข้ามกับกฎที่เป็นทางการ อาจเป็นฉันไปลงน้ำในวิธีที่ฉันอธิบาย ขอบคุณ
Dipan Mehta

@Dipan Cyclomatic ซับซ้อนนั้นเกี่ยวข้องกับความสามารถในการอ่านของรหัสผ่านหน่วยความจำที่ใช้งานได้ รหัสที่มีความซับซ้อนสูง (หรือแม้แต่ความลึกบล็อกสูง) นั้นยากที่จะเก็บไว้ในหน่วยความจำในการทำงานดังนั้นจึงยากที่จะอ่านตรงๆ
Thomas Owens

0

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

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

  • ความเรียบง่ายของโครงสร้างภายในโปรแกรม: คุณสามารถวัดจำนวนพารามิเตอร์ที่ฟังก์ชั่นจะยอมรับ หากคุณมี> n % ของฟังก์ชั่นทั้งหมดที่มีพารามิเตอร์> mคุณสามารถเลือกที่จะนับว่าไม่ง่ายขึ้นอยู่กับวิธีที่คุณกำหนดnและm (อาจจะ n = 3 และ m = 6?) ฉันคิดว่ามีเครื่องมือวิเคราะห์แบบคงที่ที่สามารถวัดสิ่งนี้ - ฉันคิดว่า JTest เพียงแค่วัดฟังก์ชันด้วยพารามิเตอร์> m

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

  • คุณสามารถลองวัด "refactorability" หากรหัสของคุณมีหลายชิ้นของรหัสที่สามารถ refactored แต่ไม่ได้อาจจะไม่ง่าย ฉันยังจำได้ตั้งแต่ตอนที่ฉันทำงานกับ JTest ว่ามันพยายามวัดเช่นกัน แต่ฉันจำได้ว่าฉันไม่เห็นด้วยกับมันในกรณีนี้บ่อยครั้งดังนั้น YMMV

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


2
ฉันเชื่อว่า # 3 เรียกว่าบล็อกลึก มันเกี่ยวข้องกับ Cyclomatic Complexity หากมีโครงสร้างการควบคุมที่เกี่ยวข้อง
โธมัสโอเวนส์

ไม่มีคำอธิบาย downvote?
FrustratedWithFormsDesigner

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

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

@ SK-logic: ฉันคิดว่าฉันควรจะเรียกมันว่า "ความฉลาด" อย่างใดอย่างหนึ่งมันใกล้เคียงกับที่ฉันหมายถึง ฉันแค่บอกว่าสิ่งต่าง ๆ เช่น?:เป็นปัญหาเมื่อพวกเขาซ้อนกัน 5 ลึก สำหรับเลเยอร์เลเยอร์ที่แยกจากกันอย่างสะอาดดีกว่าเลเยอร์ที่ซับซ้อนหนึ่งชั้น แต่ 7 ชั้นส่วนใหญ่ซ้ำซ้อนเมื่อเพียง 2 หรือ 3 มีความจำเป็นเป็นสิ่งที่ไม่ดี
FrustratedWithFormsDesigner
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.