หลายๆคนที่เริ่มพัฒนาซอฟต์แวร์ด้วยภาษาโก (Go) อาจเคยประสบเจอปัญหาตอนที่ต้องไปทำงานกับคนอื่นๆ แล้วไม่รู้ว่าควรจะเขียนโค้ดอย่างไรให้ถูกใจทุกคนในทีม เพราะหากเราพลาดขึ้นมา นอกจากจะต้องกลับไปแก้ไขเพิ่มเติมแล้ว ซ้ำร้ายหากปล่อยผ่านออกไป โปรแกรมของเราก็อาจจะเจอปัญหาใหญ่ได้เมื่อถึงเวลาใช้งานจริง
แน่นอนว่าภาษา Go นั้นมีคุณสมบัติเฉพาะตัวที่แตกต่างจากภาษาอื่น ทั้งความง่ายในการพัฒนา (Ease of Programming) และประสิทธิภาพในการทำงาน (Efficient Compilation/Efficient Execution) ดังนั้นแนวทางในการเขียนโค้ดของ Go จึงมีความแตกต่างจากภาษาอื่นเช่นเดียวกัน
ในบทความนี้ผมจะมาแนะนำแนวทางในการเขียนโค้ดคร่าวๆของภาษา Go ว่าควรมีหลักในการเขียนอย่างไรบ้าง เพื่อให้เราสามารถส่งโค้ดที่มีคุณภาพให้แก่ทีมเราได้โดยหลักการที่ผมจะกล่าวถึงมีดังนี้
- Simple
- Readable
- Consistent
- Productive
แต่ละอันหมายถึงอะไร เราไปไล่ดูกันครับ
Keep Codes Simple
คนที่เคยผ่าน Tutorial ของภาษา Go มาแล้ว จะเข้าใจว่า Go นั้นเป็นภาษาที่เข้าใจง่าย ตรงไปตรงมา และมี Syntax ที่ครอบคลุมการใช้งานเบื้องต้นหลากหลายรูปแบบ
อย่างไรก็ตาม ด้วยการที่ภาษา Go นั้นมีความหลากหลายในการเขียน ทำให้ในบางกรณีโค้ดที่มีผลลัพธ์ที่คล้ายกันอาจมีความซับซ้อนแตกต่างกันก็ได้
ขอยกตัวอย่างง่ายๆ เป็นฟังก์ชันในการหาค่ามากที่สุดจากค่าสองค่า
จากตัวอย่าง แม้ว่าฟังก์ชันนั้นจะให้ผลลัพธ์ที่ถูกต้อง แต่หากพิจารณาดีๆ แล้วจะเห็นว่าโค้ดชุดนี้ไม่จำเป็นต้องประกาศตัวแปร max
แต่อย่างใด ดังนั้นเราสามารถลดความซับซ้อนให้เหลือโค้ดประมาณนี้
การเขียนโค้ดให้ Simple ตามสไตล์ Go จะทำให้คนที่มาอ่านสามารถเข้าใจโค้ดของเราได้ง่ายขึ้น และเมื่อเกิดปัญหาขึ้นมาบนโปรแกรม เราก็จะสามารถแก้ไขปัญหาได้อย่างตรงจุด เพราะทุกคนเข้าใจว่าโค้ดแต่ละส่วนทำงานอย่างไร
Write Readable Codes
หลายๆครั้งที่นักพัฒนามักเจอปัญหาเวลาต้องแก้ไขโค้ดของคนอื่น หรือจำเป็นต้องนำโค้ดของคนอื่นมาใช้ต่อ แล้วพบว่า เราอ่านแล้วไม่เข้าใจโค้ดตัวนี้เลย
“Programs must be written for people to read, and only incidentally for machines to execute.”
― Harold Abelson, Structure and Interpretation of Computer Programs
ปกติแล้วเรามักจะเขียนโค้ดเพื่อให้โปรแกรมทำงานได้อย่างถูกต้อง และเราเข้าใจแค่คนเดียวก็เพียงพอแล้ว แต่เมื่อถึงเวลาที่เราต้องทำงานร่วมกับคนอื่น โค้ดของเราเพียงหนึ่งชุด อาจมีคนอ่านเป็นสิบๆหรือร้อยๆครั้งเลยก็ได้
ผมขอยกตัวอย่างฟังก์ชันการคำนวณค่ากึ่งกลางพิสัย 2 ฟังก์ชัน ฟังก์ชันบนเป็นแบบผมอ่านเองคนเดียว กับอีกฟังก์ชัน เป็นแบบเขียนให้คนอื่นอ่านด้วย
จะเห็นได้ว่าการเลือกเขียนแบบด้านล่าง func MidRange(n []float64) float64
คนที่อ่านสามารถเข้าใจการทำงานได้มากกว่า เพราะรู้ว่าแต่ละตัวแปรประกาศมาเพื่อใช้ทำอะไรบ้าง และผลลัพธ์ที่ได้คือค่าของอะไร (เห็นได้จากชื่อของฟังก์ชัน)
ในภาษา Go เราจะให้ค่าในการเขียนโค้ดให้สามารถอ่านได้ง่ายๆ ดีกว่าโค้ดที่สั้นแต่อ่านไม่ออก เพื่อช่วยลดภาระในการดูแล รวมถึงสร้างความเข้าใจในโปรแกรมของเราให้กับทุกคนในทีม
Be Consistent on Entire Project
สิ่งที่อาจหลงลืมไปเวลาที่นักพัฒนาทำงานร่วมกัน คือการวางโครงสร้างของระบบที่มั่นคง
ลองจินตนาการดูว่า หากเราให้แต่ละคนในทีมเขียนโค้ดได้ตามใจชอบ โดยไม่ได้กำหนดรูปแบบให้แน่ชัด ต่างคนก็มีสไตล์ในการเขียนโค้ดที่แตกต่างกัน บางคนอาจจะเขียนดี บางคนอาจจะเขียนแล้วขาดบางฟีเจอร์ บางคนอาจจะเขียนซับซ้อนจนยากเกินจะเข้าใจ สุดท้ายเมื่อนำโค้ดทั้งหมดมารวมกันเป็นหนึ่งโปรแกรม ผลลัพธ์ที่ได้ก็คือโปรแกรมที่ยากต่อการอ่าน (Unreadable) ยากต่อการดูแล (Low-Maintainability) และยากต่อการนำไปใช้ต่อ (Unusable) เหมือนกับสปาเก็ตตี (Spaghetti Code) ที่เส้นดูยุ่งเหยิง แยกไม่ออกว่าเส้นไหนเป็นเส้นไหน
ในทางกลับกัน หากทุกคนในทีมมีข้อตกลงที่แน่ชัด มีการวางโครงสร้าง (Project Structure) ที่มั่นคง มีการกำหนดรูปแบบการเขียนโค้ด (Style Guide) ให้ไปในทางเดียวกันเสมือนทั้งโปรแกรมมีคนเขียนเพียงคนเดียว สุดท้ายผลลัพธ์ที่ก็จะเป็นโปรแกรมที่ทุกคนในทีมสามารถเข้าใจตรงกัน และคนอื่นๆหรือคนที่มารับช่วงต่อจากโค้ดของเราก็สามารถทำความเข้าใจได้ในเวลาไม่นาน เพราะรูปแบบของโค้ดเหมือนกัน หากเข้าใจโครงสร้างของจุดหนึ่งแล้ว พอไปเจอโค้ดชุดอื่นก็สามารถทำความเข้าใจได้อย่างรวดเร็ว
อย่าลืมว่า สำหรับ Go แล้ว ยิ่ง Simple ยิ่งดี!
การฝึกทำโปรแกรมอย่างไรให้โค้ดมี Consistency นั้น อาจจะเป็นสิ่งที่เริ่มได้ยากสำหรับมือใหม่หลายๆคน คำแนะนำสำหรับผมคือ อยากให้ลองเขียนโค้ดตาม Senior Developer ในทีมเราก่อน ค่อยๆศึกษาถึงรูปแบบโค้ดที่ดี (และไม่ดี) แล้วจึงนำไปปรับใช้ในครั้งต่อไปถ้ามีโอกาส
หรือถ้าคนไหนยังไม่มีตัวอย่างที่ดี ไปศึกษากันได้ตามนี้เลย
Don’t Forget Productivity
โดยปกติแล้วเวลาที่เสียไปของนักพัฒนาในการสร้างซอฟต์แวร์ขึ้นมาหนึ่งชิ้นไม่ได้มาจากการเขียนโค้ดเพียงอย่างเดียว แต่ยังรวมไปถึงเวลาที่ใช้ในการอ่าน (Reading) แก้ไขปัญหา (Debugging) พัฒนาโค้ด (Refactoring) และดูแลโค้ด (Maintaining) อีกด้วย
สำหรับภาษา Go เอง การที่ตัวภาษาใช้เวลา Compile ไม่นาน เป็นอีกเหตุผลหนึ่งที่ทำให้นักพัฒนาภาษา Go สามารถโฟกัสไปที่การทำงานมากกว่าการที่ต้องมากังวลในการรอโค้ดแต่ละส่วน Compile จนเสร็จ
การเขียนโค้ดให้อ่านง่ายตามที่ผมได้กล่าวไว้ก่อนหน้านี้ ก็เป็นอีกหนึ่งช่องทางที่ช่วยเพิ่ม Productivity ให้กับงานเช่นกัน
นอกจากนี้ยังมีทางเลือกอื่นๆอีก อย่างเช่น
- การสร้าง Test (Unit Test, Integration Test)
- การทำ Code Review
- การทำ CI/CD
สิ่งเหล่านี้ล้วนแล้วแต่ช่วยลดเวลาในการดูแลโค้ดรวมถึงป้องกันการเกิดปัญหาที่อาจตามมาในภายหลัง
สรุปแล้ว ผมคิดว่า…
ภาษา Go เป็นภาษาที่เริ่มต้น สามารถเรียนรู้ได้ง่าย แต่สิ่งที่ยากกว่าคือเราจะมีหลักการและเทคนิคอย่างไรในการเขียนโค้ดของเรา เพราะสิ่งเหล่านี้ต้องอาศัยประสบการณ์ที่ซึมซับมาจากการทำงานจริง ยิ่งทำงานร่วมกับคนอื่นๆ หรือไปพบเจอ Use Case อื่นๆที่น่าสนใจ เราจะยิ่งได้เรียนรู้สิ่งใหม่ๆเพิ่มเข้ามา และท้ายที่สุดเราจะสามารถพัฒนาโค้ดให้กับทีมเราได้อย่างมีคุณภาพครับ
สุดท้ายนี้ ผมก็ขอให้ Gopher หน้าใหม่ทุกคน สนุกไปกับ Go นะครับ
Source:
แถม
สำหรับคนที่ยังสนใจในความหมายของ Simplicity ของภาษา Go สามารถไปศึกษาต่อได้จากวิดีโอนี้:
ส่วนอันนี้เป็นเรื่องของ Readability (ในวิดีโอนี้จะพูดถึงอีกคำหนึ่งที่เรียกว่า Clarity ซึ่งมีส่วนที่แตกต่างจาก Readability อยู่ ซึ่งแตกต่างกันอย่างไร วิดีโอนี้มีคำตอบให้ครับ 😉 )