By Arnon Puitrakul - 22 เมษายน 2021
มีปัญหามากมายเกิดขึ้นเมื่อเราเริ่มเอามือวางไว้บน Keyboard และจะเขียน Code จนกลายเป็น Quote ประมาณว่า ถ้าการ Debug คือการเอาบัคออก การเขียน Code ก็คงเป็นการเอาบัคใส่เข้าไปแหละ ใช่แล้ว ฮ่า ๆ เพื่อให้การ Debug ทำได้ง่ายขึ้น สิ่งนึงที่เราทำได้คือ การเขียน Code ให้ดูเรียบร้อย โดยที่ปัญหาที่วันนี้เราจะมาโฟกัสเป็นปัญหาที่คนเขียน Code มือใหม่มักจะเจอ และอาจจะยังไม่รู้ตัวว่ามันทำให้เกิดความชิบหายตอนเราจะ Debug หรือแก้ไขได้ขนาดไหน นั่นคือการใช้ Conditional ซ้อนกันเยอะ ๆ นั่นเอง
if condition_1 :
if condition_2 :
if condition_3:
do_sth_1()
else:
do_sth_2()
else:
do_sth_3()
else:
do_end_case()
จาก Code ด้านบนเป็นปัญหาที่เรามักจะพบได้บ่อยมาก ๆ ในโปรแกรมหลาย ๆ ตัวที่ไม่ได้ผ่านการทำ Refactor มาก่อน ซึ่งส่วนใหญ่แล้ว จะเกิดจากมือใหม่นี่แหละที่อาจจะยังมีวิธีการวาง Logic ที่ยังไม่มีประสิทธิภาพมากนัก ปัญหาคือ เมื่อเราต้องทำงานกับมัน อาจจะเป็นการ Debug หรือมานั่งแก้ เราจะพบว่า มันน่าปวดหัวมาก ๆ เอ๊ะ Condition Block นี้มันอยู่ตรงไหนนะ อันนี้ของใครอะไรยังไง ทำให้เสี่ยงต่อการเกิดข้อผิดพลาดได้สูงขึ้นเป็นเงาตามตัวนั่นเอง
หลาย ๆ ครั้งที่เราเจอ Code แบบนี้ เราจะไปถามคนที่เขียนว่า เขาคิดอะไรอยู่ ทำไมถึงเขียน Code แบบนี้ออกมา หลาย ๆ ครั้งเราได้คำตอบว่า ก็เขาคิดออกมาเป็นแบบนี้ เขาก็เลยเขียนมาเป็นแบบนี้ตรง ๆ เลย อะไรแบบนั้น แต่อาจจะยังไม่ได้คิดถึงผลลัพธ์ที่จะตามมานั่นเอง
if condition_1 :
return do_sth_3()
if condition_2:
return do_sth_2()
if condition_3:
return do_sth_1()
return do_end_case()
จากเดิมที่เราใช้ Indent กว้างสุดลูกหูลูกตา ยาวจนจอ Ultra Super Wide ไม่พอ เราก็ปรับมันให้มาอยู่ในรูปแบบที่อ่านง่ายขึ้นอย่าง Guard Causes ง่าย ๆ ก็คือ เราแยก Condition จากกันไปเลย แทนที่เราจะเขียนซ้อน ๆ กัน ทำให้มันอ่านง่ายขึ้น ก็ทำให้ดูแลง่ายขึ้นด้วยเช่นกัน
วิธีการที่เราจะ Extract ออกมาเป็น Guard Causes คือ เราจะต้องแรก Logic การทำงานออกมาก่อน จากเดิม เราติดทุกอย่างไว้ใน Conditional Block เดียวกันเลย เราต้องแยกออกมาตามเงื่อนไขการทำงาน ค่อย ๆ ไล่ลงไปทีละเคส เราก็จะได้ Conditional Block ของแต่ละเคสออกมา และเราก็เอามาจัดเรียงเพื่อให้มันได้เงื่อนไขตรงกับ Nested-Conditional ของเราก่อนหน้าก็เรียบร้อยแล้ว เพื่อความชัวร์ บางทีมึนก็เขียน Test Case ไว้ก็ทำให้เราจัดการกับเรื่องพวกนี้ได้ง่ายขึ้น ลดความกังวลว่าจะเขียน Logic ผิดอีกต่อไปเลย
Guard Causes เป็นวิธีการ Refactoring ง่าย ๆ ที่ใคร ๆ ก็ทำได้ แถมยังทำให้ Code ของเรามันดูดีขึ้น ดูแลง่ายขึ้นมาก เมื่อก่อน ตอนเราเขียนโปรแกรมใหม่ ๆ เราก็ไม่เข้าใจนะว่า ทำไมต้องทำ Refactoring ด้วย Code เราก็รันได้นิอะไรแบบนั้น แต่พอเอาเข้าจริงทำงานจริง ๆ มันเป็นของที่ต้องทำ เพราะโปรแกรมเราเขียนวันนี้ก็เหมือนคบแฟน คบมันก็ดูแลกันไปนาน ๆ โปรแกรมก็เช่นกัน ฮิ้ววววว
เวลาเราทำงานกับข้อมูลอย่าง Pandas DataFrame หนึ่งในงานที่เราเขียนลงไปให้มันทำคือ การ Apply Function เข้าไป ถ้าข้อมูลมีขนาดเล็ก มันไม่มีปัญหาเท่าไหร่ แต่ถ้าข้อมูลของเราใหญ่ มันอีกเรื่องเลย ถ้าเราจะเขียนให้เร็วที่สุด เราจะทำได้โดยวิธีใดบ้าง วันนี้เรามาดูกัน...
Python เป็นภาษาที่เราใช้งานกันเยอะมาก ๆ เพราะความยืดหยุ่นของมัน แต่ปัญหาของมันก็เกิดจากข้อดีของมันนี่แหละ ทำให้เมื่อเราต้องการ Performance แต่ถ้าเราจะบอกว่า เราสามารถทำได้ดีทั้งคู่เลยละ จะเป็นยังไง เราขอแนะนำ Numba ที่ใช้งาน JIT บอกเลยว่า เร็วขึ้นแบบ 700 เท่าตอนที่ทดลองกันเลย...
หลายวันก่อน เราทำงานแล้วเราต้องการทำงานกับตัวเลขเพื่อให้มันอ่านได้ง่ายขึ้น จะมานั่งเขียนเองก็เสียเวลา เลยไปนั่งหา Library มาใช้ จนไปเจอ Humanize วันนี้เลยจะเอามาเล่าให้อ่านกันว่า มันทำอะไรได้ แล้วมันล่นเวลาการทำงานของเราได้ยังไง...
การทำงานกับตัวเลขทศนิยมบนคอมพิวเตอร์มันมีความลับซ่อนอยู่ เราอาจจะเคยเจอเคสที่ เอา 0.3 + 0.6 แล้วมันได้ 0.899 ซ้ำไปเรื่อย ๆ ไม่ได้ 0.9 เพราะคอมพิวเตอร์ไม่ได้มองระบบทศนิยมเหมือนกับคนนั่นเอง บางตัวมันไม่สามารถเก็บได้ เลยจำเป็นจะต้องประมาณเอา เราเลยเรียกว่า Floating Point Approximation...