Screen Shot 2557-11-08 at 8.12.58 AM
ในการพัฒนา software นั้น ยิ่งนานไปก็ยิ่งมีความซับซ้อนเพิ่มขึ้นเรื่อยๆ
ซึ่งถ้าเราไม่สามารถจัดการความซับซ้อนเหล่านี้ได้
จะส่งผลให้ software ที่เราพัฒนาขึ้นมามันแย่ หรืออาจจะล้มไม่เป็นท่าก็ได้

ดังนั้น ถ้าเราสามารถรู้ได้ว่าใน software ที่เราสร้าง
มีอัตราความซับซ้อนเพิ่มขึ้นอย่างไร และ เท่าไร
ก็น่าจะทำให้เห็นว่าสิ่งที่เราพัฒนามีความเสี่ยงอย่างไร
และจะแก้ไขอย่างไร ใช่ไหม ?

แต่เราจะวัดค่าความซับซ้อน รวมทั้งค่าอื่นๆ ใน software ของเราอย่างไรดีล่ะ ?

กฎวิวัฒนาการของ software ในปัจจุบัน ประกอบไปด้วย

  • มีการเปลี่ยนแปลงอย่างต่อเนื่อง และ ตลอดเวลา
  • ความซับซ้อนจะเพิ่มขึ้นอย่างต่อเนื่อง
  • จำนวน feature จะสูงขึ้นเรื่อยๆ
  • คุณภาพมักจะลดลงไปเรื่อยๆ

จากกฏวิวัฒนาการของ software ในปัจจุบันนั้น มันบ่งบอกว่า
เราในฐานะ developer นั้น ล้มเหลวในการพัฒนาระบบงานอย่างมาก
เนื่องจากยิ่งพัฒนาไป ความซับซ้อนยิ่งเพิ่มขึ้น
รวมทั้งเรื่องคุณภาพก็ยิ่งแย่ลงไปเรื่อย
ผลที่ตามมาจากความล้มเหลวนี้คืออะไรล่ะ  … อันตรายอย่างยิ่ง
ลองจินตนาการดูกันเอง หรือ อาจจะพบเจอด้วยตัวเองมาก็ได้

ตัวอย่างของปัญหาที่น่าจะเคยพบเจอ เช่น

  • Software ที่สร้างมันยากต่อการทำความเข้าใจ
  • Software ที่สร้างมันยากต่อการแก้ไข หรือ เพิ่มความสามารถใหม่ๆ
  • ส่งผลต่อ productivity ของทีมให้ลดลง
  • Software ที่พัฒนาไร้ความน่าเชื่อถือจากลูกค้า และ ทีมที่เกี่ยวข้อง
  • ทีมพัฒนาไม่รู้ว่าจริงๆ แล้วต้องแก้ไขอย่างไร
  • จำนวน bug ที่สูงขึ้นอย่างต่อเนื่อง

เราจะป้องกันมันอย่างไรดีล่ะ ?

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

ว่าด้วยเรื่องของเอกสาร

เราควรสร้างเอกสารเพื่ออธิบาย software architecture และ user requirement
แต่ไม่ควรเขียนเอกสารเพื่ออธิบาย code
เนื่องจากมันไม่ได้ช่วยอะไรเลย ซึ่งอธิบายไว้ในเรื่อง comment code

ว่าด้วยแนวปฏิบัติของ Extreme Programming (XP)

มีแนวปฎิบัติที่เหมาะสมสำหรับการดูแลรักษา software
เพื่อให้พัฒนา และ ดูแลได้ง่ายขึ้น ประกอบไปด้วย

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

ต่อไปว่าด้วยเรื่องของ Code review

เป็นแนวปฏิบัติที่สำคัญมากๆ ในการพัฒนา software
และเป็นสิ่งที่ขอเน้นใน blog นี้เช่นกัน

Code review มันขึ้นกิจกรรมเพื่อทำการวิเคราะห์ code ที่พัฒนาขึ้นมา
เพื่อทำให้มั่นใจว่า code ที่พัฒนานั้น

  • ถูกต้องตามมาตรฐานที่ได้ตกลงกันไว้
  • ง่ายต่อการทำความเข้าใจ
  • ตรงตามความต้องการของผู้ใช้งาน

การทำ Code review มี 2 แนวทาง คือ

  1. Manual code review ทำด้วย developer คนอื่นๆ หรือ ตัวเราเอง
  2. Automatic code review ทำด้วยเครื่องมือวิเคราะห์

Manual code review

ส่วนใหญ่ที่พบเจอ มักจะโยนภาระหน้าที่นี้ไปให้ senior developer
ให้ทำการวิเคราะห์ code ทั้งหมดที่เกิดขึ้น

วิธีการนี้เป็นสิ่งที่ดีสำหรับการแบ่งปันความสามารถทางด้วยการ coding ภายในทีมพัฒนา
และเป็นการเพิ่มความรู้ความเข้าใจของทีมในการพัฒนา software นั้นๆ ด้วย

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

Automatic code review

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

โดยที่ การ review code แบบอัตโนมัติ นั้น
จำเป็นต้องสามารถสร้าง guildline ต่างๆ
จำเป็นต้องสามารถสร้าง หรือ มี ตัวชี้วัดในเรื่องต่างๆ
ของ code เช่น ขั้นตอนการทำงานต่างๆ และ ความซับซ้อน เป็นต้น
ซึ่งตัวชี้วัดเหล่านี้จะถูกเรียกว่า Code Metric

Code Metric

ถูกใช้เพื่อนำเสนอ code ต่างๆ ใน software ที่เราพัฒนาขึ้นมาในหลากหลายรูปแบบ เช่น

  • ขนาด
  • ความซับซ้อน
  • การผูกมัดของ code ทั้ง Cohesion และ Coupling

โดย code metric ตัวแรกที่เกิดขึ้นมาก็คือ Line of Code (LoC)
นำมาใช้สำหรับวัด productivity และ work effort ของทีมพัฒนา
ต่อจากนั้นจึงเกิด code metric ชื่อว่า cyclomatic complexity ขึ้นมา
เพื่อวัดความซับซ้อนของ code เนื่องจากในโลกนนี้มีภาษาโปรแกรมจำนวนมากมาย
ซึ่งค่า LoC นั้นไม่สามารถตอบโจทย์ และ ไม่มีประสิทธิภาพเพียงพอ
ต่อจากนั้นก็มี code metric อีกมากมายเกิดขึ้นมา เช่น CK metric และ MOOD

มาลงรายละเอียดของ Code metric บางตัวที่มักถูกใช้งานกันดีกว่า

1. Line of Code (LoC)
บรรทัดที่ถูกเรียกว่า Line of Code หรือ LoC นั้นไม่ใช่จำนวนบรรทัดของ code นะ
แต่มันมีเงื่อนไขอื่นๆ อีก สามารถอ่านเพิ่มเติมได้ที่นี่  Wikipedia :: Source Line of Code
แต่ขอแนะนำให้แต่ละ class, method เล็กที่สุดเท่าที่จะทำได้
เพื่อลดความซับซ้อน และ ลดหน้าที่การทำงานที่มากมายลงมา

2. Cyclomatic Complexity (CC)
ใช้สำหรับการวัดค่าความซับซ้อนของ class และ method
โดยพื้นฐานจะนับความซับซ้อนของ method จากเส้นทางทั้งหมดที่เป็นไปของการประมวลผล
ตัวอย่างเช่น

  • Method ที่ไม่มีเงื่อนไข และ loop จะมีค่าความซับซ้อนเท่ากับ 1
  • ถ้า method นั้นมี 1 เงื่อนไข จะมีความซับซ้อนเท่ากับ 2 เนื่องจากมีเส้นทางการทำงาน 2 ทาง

ขอแนะนำให้ค่า CC น้อยที่สุดเท่าที่จะทำได้
เพื่อลดความซับซ้อนของ code
ซึ่งค่ากลางของ CC อยู่ที่ 10-15
แต่ถ้าน้อยกว่านี้จะเป็นสิ่งที่ดีมากๆ
ค่า CC ถือเป็นตัวชี้วัดที่ท้าทายทีมพัฒนาอย่างมาก

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

3. Coupling
ใช้สำหรับวัดค่าความเกี่ยวข้องของ object ต่างๆ ภายใน code
ถ้าแต่ละ object มีความเกี่ยวข้องกันสูง แสดงว่ามันจะเป็นอิสระต่อกันต่ำ
ดังนั้น ถ้ามีการเปลี่ยนแปลงส่วนใดๆ แล้ว จะส่งผลกระทบสูง
ดังนั้น ถ้าค่าของ coupling สูง ก็ไม่น่าจะเป็นสิ่งที่ดีนะ

ซึ่งสามารถแยกออกเป็น 2 แบบ คือ

  1. Afferent coupling (Inbound) คือ การวัดจำนวน object อื่นๆ ที่มาใช้งาน object หนึ่ง เช่น A, B, C มาใช้งาน C แสดงว่าค่า Afferent coupling = 3
  2. Efferent coupling (Outbound) คือ การจัดจำนวน object อื่นๆ ที่ถูกใช้งานจาก object หนึ่ง เช่น A, B ถูกใช้งานจาก C แสดงว่าค่า Efferent coupling = 2

แนะนำให้ค่า coupling ต่ำที่สุดเท่าที่จะเป็นไปได้
ไม่เช่นนั้น code ของคุณมันจะยากต่อการ reuse และ การทดสอบ
แต่ไม่ใช่ว่าถ้าส่วนไหนที่มีค่า coupling สูงแล้วจะแย่เสมอไปนะ
เช่นค่า Afferent coupling มีค่าสูงมากๆ แสดงว่า object นั้นๆ ต้องมีความเสถียร
และมีการ reuse จำนวนมาก

4. Lack of Cohesion(LCOM)
ใช้สำหรับวัดค่าความสอดคล้องกันของ object นั้นๆ
นั่นคือใน object นั้นๆ จะต้องมีหน้าที่รับผิดชอบเดียวกัน
ทำให้เราสามารถแยก module ของ code ได้ง่าย

เช่นในโลกของ Object-Oriented นั้นในแต่ละ class ควรมี abstraction เดียวเท่านั้น
ถ้ามีมากกว่านั้น ต้องทำการ refactoring แล้วนะ

ค่าของ LCOM จะไม่มีติดลบ ค่าต่ำสุดที่เป็นไปได้คือ 0

แนะนำให้ค่า LCOM มีค่าที่สูงๆ จะดีมาก
แสดงว่า code ส่วนนั้น หรือ module นั้น สามารถทำงานได้ด้วยตัวเอง

เครื่องมือสำหรับการคำนวณค่าต่างๆ ของ Code Metric

ในปัจจุบันมีเครื่องมือจำนวนมาก ทั้ง ฟรีและไม่ฟรี
รวมทั้งยังสนับสนุนภาษาโปรแกรมมากมาย ประกอบไปด้วย

โดยสรุปแล้ว

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

ดังนั้นขอแนะนำให้เริ่มทำการ review code
ใช้ทั้งแบบ manual ร่วมกับอัตโนมัติ
เพื่อช่วยทำให้ code มันดีขึ้นอย่างต่อเนื่อง และ สม่ำเสมอ

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