- ระหว่างการรีวิวโค้ดเบสในช่วงหลัง ผู้เขียนพบว่าถึงแม้คุณภาพโค้ดจะดี แต่ก็ยังรู้สึกล้าทางความคิด
- ปัญหานี้เกี่ยวข้องกับ ความสามารถในการอ่าน มากกว่าความซับซ้อนของโค้ด
- จึงสรุปออกมาเป็น 8 รูปแบบ เพื่อช่วยเพิ่มความสามารถในการอ่านโค้ด
เมตริกความสามารถในการอ่านโค้ด และเมตริกความซับซ้อนทางเลือก
- ยังไม่มีเมตริกสากลที่ใช้กันอย่างแพร่หลายสำหรับวัดความสามารถในการอ่านโค้ด
- ที่มีอยู่ส่วนใหญ่เป็นเพียงงานวิชาการที่ไม่ถูกใช้จริง หรือเป็นความเห็นส่วนบุคคล
- แทนที่จะสร้างเมตริกใหม่ ผู้เขียนเลือกโฟกัสที่ รูปแบบทางสายตา ซึ่งทุกคนพูดคุยกันได้ง่าย
- เงื่อนไขสำคัญของเมตริกความซับซ้อน:
- ต้องใช้ได้กับ source code snippet หรือฟังก์ชันเดี่ยว ๆ
- โฟกัสที่วิธีการเขียนโค้ด แทนอัลกอริทึมคอมเพล็กซิตี
- ไม่เน้นองค์ประกอบด้านสไตล์ (เช่น ชื่อตัวแปร เว้นวรรค การย่อหน้า ฯลฯ)
Halstead complexity metric
- เมตริกความซับซ้อนของโค้ดที่ Maurice Halstead พัฒนาขึ้นในช่วง ทศวรรษ 1970
- สามารถทำให้วิธีการเขียนโค้ดเป็นตัวเลขได้ โดยไม่ขึ้นกับภาษาและแพลตฟอร์ม
- คำนวณความยาว ปริมาตร และความยากของโปรแกรมจากจำนวน operator และ operand
- ค่าที่วัดหลัก ๆ:
- จำนวน operator ที่ไม่ซ้ำ (
n1)
- จำนวน operand ที่ไม่ซ้ำ (
n2)
- จำนวน operator ทั้งหมด (
N1)
- จำนวน operand ทั้งหมด (
N2)
- ยิ่งมี operator และ operand มาก ความซับซ้อนของโค้ดยิ่งเพิ่มขึ้น
- เนื่องจากนิยามของ operator และ operand ไม่ได้ชัดเจนเหมือนกันในทุกภาษา จึงควรใช้เครื่องมืออย่างสม่ำเสมอ
ข้อสังเกตที่ได้จาก Halstead complexity
- ฟังก์ชันสั้นและมีตัวแปรน้อย จะอ่านง่ายกว่า
- ควรลดการใช้ operator เฉพาะภาษา หรือ syntactic sugar ให้น้อยที่สุด
- การใช้ chain แบบ functional programming (
map/reduce/filter เป็นต้น) หากยาวเกินไปจะทำให้อ่านยากขึ้น
Cognitive Complexity
- เมตริกความซับซ้อนที่พัฒนาโดย SonarSource
- เป็นความพยายามในการวัดความยากของการอ่านโค้ดให้แม่นยำขึ้น
- มี หลักการสำคัญ 3 ข้อ:
- shorthand constructs ช่วยลดความยากในการอ่าน
- การขัดจังหวะของ flow แบบไม่เป็นเส้นตรงเพิ่มความยาก
- control flow ที่ซ้อนกันเพิ่มความยาก
ข้อสังเกตที่ได้จาก Cognitive Complexity
- shorthand constructs แม้จะกระชับ แต่ก็มีความเสี่ยงต่อบั๊กแฝง
- เงื่อนไขและ logical operator หากใช้มากเกินไปจะทำให้อ่านยากขึ้น
- การจัดการ exception เป็นสาเหตุสำคัญที่ทำให้โค้ดซับซ้อนขึ้น
- โดยทั่วไปควรหลีกเลี่ยง
goto แต่ในบางสถานการณ์ก็อาจมีประโยชน์
- โครงสร้างควบคุมที่ซ้อนกัน ควรลดให้มากที่สุดเท่าที่ทำได้
รูปร่างของฟังก์ชัน รูปแบบ และตัวแปร
- "รูปร่าง" ทางสายตาของฟังก์ชันมีบทบาทสำคัญต่อความสามารถในการอ่านโค้ด
- 3 หลักการที่ช่วยเพิ่มความสามารถในการอ่าน:
- ใช้ ชื่อตัวแปรที่ชัดเจนและเฉพาะเจาะจง
- หลีกเลี่ยงการซ้ำชื่อในขอบเขตที่บดบังกัน (shadowing)
- ใช้ชื่อที่แยกกันได้ชัดเจนทางสายตา (หลีกเลี่ยงชื่อคล้ายกันอย่าง
i, j)
- ทำให้อายุการใช้งานของตัวแปร (liveness) สั้นลง
- ยิ่งขอบเขตการใช้งานของตัวแปรสั้นเท่าไรยิ่งดี
- ตัวแปรที่คงอยู่นานและข้ามขอบเขตของฟังก์ชันจะเพิ่มความซับซ้อน
- ใช้รูปแบบโค้ดที่คุ้นเคยซ้ำ
- การคงรูปแบบโค้ดให้สม่ำเสมอช่วยเพิ่มความสามารถในการอ่าน
- ควรเลือกใช้รูปแบบที่คุ้นเคยอยู่แล้วก่อนแนวทางใหม่ ๆ
8 รูปแบบที่ช่วยเพิ่มความสามารถในการอ่านโค้ด
- ลดจำนวนบรรทัด/operator/operand – ฟังก์ชันเล็กและตัวแปรน้อยช่วยให้อ่านง่ายขึ้น
- หลีกเลี่ยงแนวทางใหม่ – รักษารูปแบบที่คุ้นเคยภายในโค้ดเบส
- จัดกลุ่ม – แยก function chain ที่ยาว ตัววนซ้ำ หรือส่วนคล้ายกันออกเป็นฟังก์ชันช่วย
- ทำเงื่อนไขให้ง่าย – ทำให้เงื่อนไขสั้น และลดการผสม logical operator หลายแบบ
- ลดการใช้
goto – หากจำเป็นค่อยใช้แบบจำกัดเฉพาะใน error handling
- ลดการซ้อนกัน – ลด logic ที่ซ้อนกัน และหากจำเป็นให้แยกเป็นฟังก์ชัน
- ใช้ชื่อตัวแปรที่ชัดเจน – ใช้ชื่อตัวแปรที่เฉพาะเจาะจงและไม่ซ้ำกัน
- ทำให้อายุของตัวแปรสั้นลง – ใช้ให้อยู่ในฟังก์ชันช่วงสั้น ๆ และไม่ให้ข้ามขอบเขตฟังก์ชัน
บทสรุป
- ความสามารถในการอ่านโค้ดเป็นองค์ประกอบสำคัญของคุณภาพโค้ด
- Halstead และ Cognitive Complexity สามารถช่วยทำให้ปัญหาด้านการอ่านเป็นตัวเลข และชี้ทิศทางการปรับปรุงได้
- การเขียนโค้ดให้กระชับและชัดเจนช่วยให้บำรุงรักษาได้ง่ายขึ้น และลดโอกาสเกิดบั๊ก
- การเขียนโค้ดที่ดีที่สุดคือการให้ความสำคัญกับความเรียบง่าย ความสม่ำเสมอ และความชัดเจน
1 ความคิดเห็น
ความเห็นจาก Hacker News
การเชื่อมโครงสร้างการเขียนโปรแกรมเชิงฟังก์ชันอย่าง map, reduce, filter เข้าด้วยกันนั้นกระชับ แต่สายโซ่ที่ยาวมักทำให้ความสามารถในการอ่านลดลง
แง่มุมสำคัญของโค้ดที่ดีมีลักษณะเชิงคุณภาพและคล้ายงานวรรณกรรม
ปัญหาที่ทำให้เหนื่อยที่สุดเวลาอ่านโค้ดคือความเปลี่ยนแปลงได้ของสถานะ
ฟังก์ชันเล็กและตัวแปรน้อยโดยทั่วไปอ่านง่าย
TypeScript ทำให้โค้ดอ่านยากขึ้น
ฟังก์ชัน getOddness4 ทำให้เกิดความไม่สมมาตร
บทความน่าสนใจ แต่ยังไม่ค่อยน่าพอใจ
ความพยายามในการนิยามความอ่านง่ายเป็นสิ่งที่น่าชื่นชม
ความซับซ้อนของโค้ดแสดงออกได้ด้วยขนาดของ syntax tree
สายโซ่ฟังก์ชันยาว ๆ หรือ callback ควรถูกแบ่งเป็นกลุ่มเล็ก ๆ และใช้ตัวแปรที่ตั้งชื่อได้ดี