หลักการพื้นฐานในการเขียนโค้ดที่ดีในทุกภาษา

Published on

Authored by Pete. Pittawat Taveekitworachai.


แต่ละภาษาที่ใช้ในการเขียนโปรแกรมมักจะมี Best Practice หรือ Syntax ต่าง ๆ ที่เข้ามาช่วยเพื่อให้เราสวามารถเขียนโค้ดที่ดีขึ้น แน่นอนว่าการเขียนโค้ดให้ระบบของเราทำงานได้นั้นไม่ใช่เรื่องยากอะไร หากแต่การเขียนโค้ดที่ดีนั้น มีองค์ประกอบต่าง ๆ มากมาย โค้ดที่ดีไม่เพียงแค่ทำให้ระบบสามารถทำงานได้ตามวัตถุประสงค์ที่ตั้งไว้เท่านั้น หากแต่โค้ดที่ดียังทำให้นักพัฒนาทำงานกับระบบได้ง่ายขึ้นอีกด้วย ซึ่งโค้ดที่ดีนั้นไม่ได้มีเพียงแค่การตั้งชื่อให้สื่อความหมายเท่านั้น หากแต่ยังประกอบไปด้วยสิ่งอื่น ๆ อีกมากมาย รวมไปถึง Convention และข้อตกลงของแต่ละทีมด้วย ในบทความนี้ก็จะพาไปดูหลักการพื้นฐานต่าง ๆ ที่จะช่วยเราสามารถเขียนโค้ดได้ดียิ่งขึ้น ไม่ว่าจะเขียนภาษาใดก็ตาม


Naming

เรื่องแรกและเรื่องที่สำคัญที่สุด ย่อมหนีไม่พ้นเรื่องของการตั้งชื่อ การตั้งชื่อเป็นหนึ่งในสิ่งที่นักพัฒนาจะต้องเจออยู่ตลอดเวลาในการพัฒนาระบบ ไม่ว่าจะตั้งชื่อตัวแปร,​ ตั้งชื่อคลาส,​ ตั้งชื่อโฟลเดอร์,​ ตั้งชื่อไฟล์ ฯลฯ โดยส่วนตัวเชื่อในการตั้งชื่อว่าควรยึดถือหลัก 2C คือ Convention และ Convey meaning

Convention คือ การที่เราตั้งชื่อตามหลักการที่แนะนำของภาษานั้น ๆ เช่น Python อาจจะต้องตั้งเป็นแบบ Snake case หรือ Java อาจจะต้องเป็น Camel case แต่อย่างไรก็ตามหากมองในอีกมุมหนึ่ง Convention ก็อาจหมายถึงข้อตกลงภายในทีมได้เช่นกัน โดยส่วนตัวมองว่าควรยึด Convention ของทีมเป็นหลัก แต่หากเป็นไปได้ก็ควรสอดคล้องกับ Community เช่นกัน เพราะการพัฒนา Software ในปัจจุบัน เราพึ่งพา Third-party library ต่าง ๆ มากมาย

Convey meaning ก็ถือว่าตรงไปตรงมา คือ การตั้งชื่อให้สื่อความหมาย ปัจจุบันเวลาเราพัฒนาโปรแกรมเราใช้งาน Code editor หรือ IDE กันเป็นปกติอยู่แล้ว ดังนั้นการตั้งชื่อยาวก็ไม่ได้เป็นอุปสรรคที่เราต้องพิมพ์ให้ครบ เพราะโปรแกรมที่เราใช้จะช่วยเราในส่วนนี้อยู่แล้ว แต่อย่างไรก็ตาม Convey meaning ก็ควรจะต้องมอง Convention ร่วมด้วย เช่น การตั้งชื่อ Function ที่ปกติเรามักขึ้นต้นด้วย Verb แต่ในภาษาอังกฤษคำที่มีความหมายใกล้เคียงกันก็ค่อนข้างเยอะ จึงควรตกลงกันให้ดีว่าจะใช้คำอะไร เพื่อให้เป็นไปในทิศทางเดียวกัน และป้องกันความสับสนที่อาจจะเกิดขึ้น เช่น fetch, get, view, observe, download


DRY

Don’t Repeat Yourself - เป็นหลักการที่บอกว่า เมื่อไรก็ตามที่เราก็อปโค้ดแปะ หรือก็อปแปะแล้วแก้นิดหน่อย เราควรแยกโค้ดส่วนนั้นออกมาเป็นฟังก์ชัน อย่างไรก็ตามมันเป็นหลักการที่แนะนำเท่านั้น ในบางกรณีก็ไม่จำเป็นต้องทำ ควรพิจารณาเป็นครั้ง ๆ ไป แต่ก็เป็นหลักการหนึ่งที่ดี ที่จะช่วยให้เราฝึกนิสัยในการเขียนโค้ดที่ง่ายต่อการปรับเปลี่ยน เพิ่มเติมในอนาคต


SRP

Single-Responsibility Principle - หลักการที่ว่าด้วย ฟังก์ชัน หรือคลาสนั้น ๆ ควรมีความรับผิดชอบเพียงแค่เรื่องเดียว หากเกี่ยวข้องกับเรื่องอื่นควรแยกออกมาเป็นอีกหนึ่งฟังก์ชันหรือคลาส เช่น ฟังก์ชันที่ดึงข้อมูลจากเน็ตเวิร์คก็ควรมีหน้าที่เพียงแค่ดึงข้อมูลจากเน็ตเวิร์คเท่านั้น ไม่ควรไปทำอย่างอื่นด้วย เช่น ไปบันทึกข้อมูลที่รับมาลงฐานข้อมูลด้วย ซึ่งหลักการนี้นอกจากช่วยให้โค้ดเราเป็นระเบียบมากขึ้นแล้ว ยังลดโอกาสที่จะเกิดข้อผิดพลาด หรือหากเกิดข้อผิดพลาดก็จะแก้ไขได้ง่ายยิ่งขึ้น อย่างไรก็ตามนิยามของแต่ละคนว่า “หน้าที่” นั้นจะครอบคลุมถึงแค่ไหนก็ขึ้นอยู่กับดุลยพินิจของแต่ละคน ว่าควรแยกออกมาเมื่อไร


YAGNI

You Ain’t Gonna Need It - คุณอาจไม่ต้องการมันหรอก เป็นหลักการที่ว่าเราไม่ควรเขียนโค้ด “เผื่อ” เอาไว้ เพราะคิดว่าอาจจะต้องใช้มันในอนาคต การเขียนโค้ดเผื่อนั้นมีข้อเสียในแง่ที่เป็นการเพิ่มปริมาณงานที่ไม่ก่อให้เกิดประโยชน์กับเป้าหมายในปัจจุบัน ยิ่งไปกว่านั้นยังทำให้โค้ดอ่านยากขึ้นอีกด้วย เพราะมีส่วนที่ไม่เกี่ยวข้องกับปัจจุบันมากเกินไป เช่น เราเขียนฟังก์ชันเพื่อแปลงข้อมูลที่ได้รับมาจาก XML ให้เป็น Object แต่เราคิดเผื่อไปด้วยว่าในอนาคตเราอาจจะอยากเปลี่ยนไปใช้ JSON ดังนั้นเราจึงเขียนโลจิกเผื่อเอาไว้ ซึ่งเป็นการเพิ่มความซับซ้อนให้ฟังก์ชันนั้น และยังไม่เกิดคุณค่ากับเป้าหมายปัจจุบันอีกด้วย รวมไปถึงในอนาคตอาจจะไม่ได้ใช้ด้วยซ้ำหากเกิดการเปลี่ยนแปลงเป็น CSV แทนที่ XML ไม่ใช่ JSON

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


KISS

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


📚 Hope you enjoy reading! 📚