Tutorial

จัดการกับ Nested Condition ด้วย Guard Causes

By Arnon Puitrakul - 22 เมษายน 2021 - 1 min read min(s)

จัดการกับ Nested Condition ด้วย Guard Causes

มีปัญหามากมายเกิดขึ้นเมื่อเราเริ่มเอามือวางไว้บน 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 แบบนี้ออกมา หลาย ๆ ครั้งเราได้คำตอบว่า ก็เขาคิดออกมาเป็นแบบนี้ เขาก็เลยเขียนมาเป็นแบบนี้ตรง ๆ เลย อะไรแบบนั้น แต่อาจจะยังไม่ได้คิดถึงผลลัพธ์ที่จะตามมานั่นเอง

Guard Causes คือตัวช่วยที่ดี

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 ผิดอีกต่อไปเลย

สรุป: ทดลองดูแล้ว Code จะดูสวยขึ้นเยอะ

Guard Causes เป็นวิธีการ Refactoring ง่าย ๆ ที่ใคร ๆ ก็ทำได้ แถมยังทำให้ Code ของเรามันดูดีขึ้น ดูแลง่ายขึ้นมาก เมื่อก่อน ตอนเราเขียนโปรแกรมใหม่ ๆ เราก็ไม่เข้าใจนะว่า ทำไมต้องทำ Refactoring ด้วย Code เราก็รันได้นิอะไรแบบนั้น แต่พอเอาเข้าจริงทำงานจริง ๆ มันเป็นของที่ต้องทำ เพราะโปรแกรมเราเขียนวันนี้ก็เหมือนคบแฟน คบมันก็ดูแลกันไปนาน ๆ โปรแกรมก็เช่นกัน ฮิ้ววววว