วันนี้ทำการ review code ของ iOS app ที่พัฒนาด้วยภาษา Swift
พบว่ามีส่วนการ validate หรือตรวจสอบข้อมูลจำนวนมาก
และรูปแบบ code ที่เขียนบ่อย ๆ เป็นดังนี้
- ค่าต้องไม่ว่าง
- ข้อมูลต้องมีรูปแบบที่ถูกต้องเช่น email , ความยาวของข้อมูล, เป็นตัวเลข เป็นต้น
- ข้อมูลของ password ซึ่งต้องมีทั้งตัวเลข ตัวพิมพ์เล็กและพิมพ์ใหญ่
- และอื่น ๆ อีกมากมาย
คำถามก็คือ code ที่เขียนเป็นอย่างไร ? คำตอบก็คือ if-else-if-else ไปเรื่อย ๆ ไงล่ะ !!
คำถามต่อมาก็คือ
ถ้าต้องการให้ส่วนการแยกการ validate ข้อมูลแต่ละอย่างออกจากกัน เพื่อทำให้ง่ายต่อการเพิ่ม ลบ และเปลี่ยนแปลง แน่นอนว่า ต้องใช้งานง่ายอีกด้วย เราจะต้องทำอย่างไร ? ดังนั้นลองมาสร้างส่วนการ validate ข้อมูลใหม่กันหน่อย โดยละทิ้งแนวคิดแบบเดิม ๆ กันไปบ้างเริ่มต้นด้วยการกำหนดผลของการ validate ข้อมูล
ซึ่งมี 2 แบบคือ valid และ invalid สามารถเขียน code ได้ดังนี้ [gist id="a0c3e18ad68650afb3a6a2e6e190fc13" file="1.swift"]ในตัวอย่างทำการ validate ข้อมูลของ username
ซึ่งมีการตรวจสอบ 3 กรณีคือ- เป็นค่าว่าง
- สั้นเกินไป คือ ความยาวน้อยกว่า 5
- ยาวเกินไป คือ ความยาวมากกว่า 10
สิ่งที่ต้องการคือ ในการ validate แต่ละกรณีให้แยกออกจากกัน
เพื่อทำให้แต่ละส่วนทำงานอย่างใดอย่างหนึ่งไปเลย (Single Responsibility) ทำให้แต่ละส่วนทำงานมีขนาดที่เล็ก แต่ยังต้องการให้มีรูปแบบและโครงสร้างเดียวกัน จึงทำการสร้าง protocol ของ Validator ไว้ดังนี้ [gist id="a0c3e18ad68650afb3a6a2e6e190fc13" file="3.swift"] จากนั้นทำการสร้าง Validator สำหรับการ validate ข้อมูลในแต่ละกรณีไปกรณีที่ 1 ตรวจสอบค่าว่าง (Empty)
เป็น validator ที่ใช้สำหรับตรวจสอบค่าว่างของข้อมูล ตั้งชื่อไว้ว่า EmptyValidator เขียน code ได้ดังนี้ [gist id="a0c3e18ad68650afb3a6a2e6e190fc13" file="4.swift"]กรณีที่ 2 ตรวจความยาวของ username ว่าสั้นเกินไปหรือไม่
เป็น validator เฉพาะของ username เท่านั้น ตั้งชื่อไว้ว่า UsernameTooShortValidator เขียน code ได้ดังนี้ [gist id="a0c3e18ad68650afb3a6a2e6e190fc13" file="5.swift"]กรณีที่ 3 ตรวจความยาวของ username ว่ายาวเกินไปหรือไม่
เป็น validator เฉพาะของ username เท่านั้น ตั้งชื่อไว้ว่า UsernameTooLongValidator เขียน code ได้ดังนี้ [gist id="a0c3e18ad68650afb3a6a2e6e190fc13" file="6.swift"]เมื่อได้ validator ครบทุกตัวแล้ว ก็มีปัญหาตามมาคือ จะใช้งานอย่างไรดีล่ะ ?
เพื่อให้ได้ตามที่ต้องการคือ สามารถเพิ่ม ลบ และแก้ไขได้ง่าย ดังนั้นจึงทำการสร้าง struct/class สำหรับใช้จัดการกลุ่มของ validator ทำให้สามารถจัดการได้ง่ายขึ้น เขียน code ได้ดังนี้ [gist id="a0c3e18ad68650afb3a6a2e6e190fc13" file="7.swift"] จากนั้นทำการสร้างตัวรวม validator สำหรับ username ขึ้นมา และใช้งานดังนี้ [gist id="a0c3e18ad68650afb3a6a2e6e190fc13" file="8.swift"]พบว่าด้วยวิธีการนี้ ทำให้เราสามารถสร้างชุด validator ของข้อมูลได้ง่ายขึ้น
ทั้งการเพิ่ม ลบ และแก้ไข ที่สำคัญสามารถเขียนชุดการทดสอบได้ง่ายมาก ๆ อีกด้วย ถึงแม้จะแลกมาด้วยความซับซ้อนที่เพิ่มขึ้น (ควบคุมได้)Simple not easy !!