
กรอกข้อมูลครบแล้ว กดส่ง ปุ่มเปลี่ยนเป็นวงกลมหมุน รอสักพักก็ยังเหมือนเดิม
กดอีกครั้งดีไหม? รีเฟรชแล้วข้อมูลจะหายหรือเปล่า? หรือรายการถูกส่งไปแล้ว แต่หน้านี้ยังไม่รู้?
คนใช้ไม่ควรต้องเดาคำตอบจากวงกลมที่หมุนอยู่ เรื่องเล็ก ๆ บนหน้าจอนี้พาเราไปถึงวิธีบันทึกข้อมูล การจัดการคำขอซ้ำ และโครงสร้างโค้ดที่ทีมจะดูแลต่อ
ลองใช้ระบบจองห้องประชุมเป็นตัวอย่างสมมติ ผู้ใช้ต้องการห้องหนึ่งห้องในช่วงเวลาหนึ่ง และควรรู้ว่าการจองครั้งนั้นได้ผลอย่างไร
ปุ่มหมุนอยู่ แต่ข้อมูลอาจถูกบันทึกแล้ว
สมมติว่าฝั่งเซิร์ฟเวอร์บันทึกการจองสำเร็จ แต่การเชื่อมต่อหลุดก่อนคำตอบกลับมาถึงหน้าจอ ผู้ใช้จึงเห็นเพียงข้อความว่าใช้เวลานานเกินไป
ถ้าหน้าจอบอกว่า “จองไม่สำเร็จ กรุณาส่งใหม่” ทันที คนใช้อาจสร้างคำขออีกครั้ง ทั้งที่รายการแรกมีอยู่แล้ว
การไม่ได้รับคำตอบจึงยังสรุปไม่ได้ว่างานไม่เกิดขึ้น ฝั่งหน้าจอควรบอกตามสิ่งที่ตรวจได้ เช่น “ยังตรวจสอบผลการจองไม่ได้” แล้วให้ทางไปตรวจรายการเดิม แนวคิดเรื่องผลข้างเคียงจากการลองใหม่อธิบายไว้ใน Amazon Builders’ Library
ข้อความบนปุ่มกับพฤติกรรมของระบบต้องตกลงกันตั้งแต่ต้น จะได้ไม่ผลักภาระการตัดสินใจไปให้คนใช้ในจังหวะที่ระบบมีปัญหา
แยกให้ชัดว่ากำลังส่ง สำเร็จ หรือยังไม่รู้ผล
ฟอร์มเดียวอาจต้องสื่อสารมากกว่าคำว่า “สำเร็จ” กับ “ผิดพลาด” ลองกำหนดข้อความจากเหตุการณ์ที่เกิดขึ้นจริง:
- กำลังส่งคำขอ — ระบบเริ่มส่งแล้ว เก็บข้อมูลที่กรอกไว้และป้องกันการกดติดกัน
- ยืนยันการจองแล้ว — ได้รับผลที่เชื่อถือได้ แสดงห้อง เวลา และเลขอ้างอิงให้ตรวจต่อ
- จองไม่ได้ — ระบบยืนยันเหตุผลแล้ว เช่น ช่วงเวลาถูกจองไปก่อน ผู้ใช้ควรรู้ว่าต้องเปลี่ยนอะไร
- ยังตรวจสอบผลไม่ได้ — คำตอบขาดหายหรือบริการตรวจสถานะไม่พร้อม ให้ตรวจรายการเดิมก่อนเริ่มคำขอใหม่
การกดส่งสำเร็จในทางเทคนิคก็อาจหมายถึงแค่ “รับคำขอแล้ว” หากยังต้องรอคนอนุมัติ หน้าจอควรแสดงว่ารออนุมัติ ไม่ข้ามไปบอกว่าจองเรียบร้อย
เลือกคำให้ตรงกับงาน แล้วใช้ความหมายเดียวกันทั้งหน้าฟอร์ม หน้าประวัติ และการแจ้งเตือน คนใช้จะตามเรื่องต่อได้โดยไม่ต้องตีความสถานะใหม่ทุกหน้า
ส่งซ้ำได้ ต้องจำได้ว่าเป็นคำขอเดิม
การปิดปุ่มระหว่างส่งช่วยลดการกดติดกัน แต่ยังมีการรีเฟรช เปิดหลายแท็บ และคำขอที่มาถึงพร้อมกัน ฝั่งเซิร์ฟเวอร์จึงต้องรับผิดชอบการป้องกันรายการซ้ำด้วย
แนวทางหนึ่งคือกำหนดรหัสให้การดำเนินการแต่ละครั้ง เมื่อส่งข้อมูลเดิมอีกครั้งเพราะยังไม่ได้คำตอบ ให้ใช้รหัสเดิม ระบบจึงแยกการลองซ้ำออกจากการจองครั้งใหม่ได้ หลักการนี้เรียกว่า idempotency: การลองทำรายการเดิมซ้ำไม่ควรสร้างผลเพิ่มตามจำนวนครั้งที่ส่ง
รหัสนี้ต้องมีขอบเขตของผู้ใช้และการดำเนินการที่ชัดเจน ตรวจสิทธิ์ตามปกติ และป้องกันคำขอพร้อมกันอย่างถูกต้อง การเช็กว่า “มีหรือยัง” แล้วค่อยบันทึกแยกกันอาจยังเกิดรายการซ้ำได้
สำหรับบริการภายนอก ต้องอ่านเงื่อนไขของบริการนั้นด้วย ตัวอย่างเช่น Stripe กำหนดการใช้ idempotency key ไว้เฉพาะ และตรวจว่าพารามิเตอร์ของคำขอซ้ำตรงกับครั้งแรกหรือไม่ รหัสเดิมไม่ได้ใช้แทนการตรวจสิทธิ์ และไม่ควรถูกนำไปผูกกับรายการใหม่ที่เปลี่ยนข้อมูลแล้ว
ต้องกำหนดด้วยว่าจะเก็บรหัสไว้นานแค่ไหน หลังหมดช่วงเวลานั้น ไม่ควรถือว่าระบบยังจำคำขอได้เสมอ หากผลยังไม่ชัด ควรตรวจรายการเดิมก่อนตัดสินใจส่งอีกครั้ง
ในระบบจองห้อง ยังต้องมีกติกาป้องกันคนละคำขอจองห้องและเวลาเดียวกันด้วย การจำคำขอเดิมกับการตรวจว่าห้องว่างเป็นคนละหน้าที่
Clean Code เริ่มจากชื่อที่บอกความหมายของงาน
ถ้าโค้ดใช้ตัวแปร success ตัวเดียวแทนทั้ง “ส่งถึงแล้ว” “บันทึกแล้ว” และ “อนุมัติแล้ว” คนแก้ต่อจะต้องไล่อ่านเงื่อนไขเพื่อหาว่าตอนนี้สำเร็จเรื่องไหน
ชื่ออย่าง requestAccepted, bookingConfirmed และ resultUnknown ช่วยให้การคุยเรื่องพฤติกรรมชัดขึ้น แต่ชื่อที่ดีต้องมาพร้อมเงื่อนไขที่แยกกันจริง ไม่ใช่เปลี่ยนชื่อแล้วปล่อยให้ทุกสถานะทำงานเหมือนเดิม
โครงสร้างโค้ดควรช่วยให้ตามงานได้ด้วย หน้าฟอร์มรับข้อมูลและแสดงผล ส่วนขั้นตอนจองตรวจสิทธิ์ ตรวจห้องว่าง และประสานการบันทึก รายละเอียดฐานข้อมูลหรือบริการภายนอกมีจุดเชื่อมที่ชัดเจน แนวทางนี้สอดคล้องกับ Clean Architecture ที่ให้กติกาของงานเป็นอิสระจากรายละเอียดเครื่องมือ
ระบบเล็กอาจจัดหน้าที่เหล่านี้อยู่ในแอปเดียวได้ ไม่จำเป็นต้องเพิ่มบริการหลายตัวเพื่อให้ดูเป็นงานองค์กร สิ่งที่ควรถามคือ เมื่อเปลี่ยนกติกาการจอง ทีมรู้ไหมว่าต้องแก้และทดสอบตรงไหน
ทดสอบวันที่อินเทอร์เน็ตไม่เป็นใจด้วย
ก่อนเปิดใช้ ลองเดินผ่านเหตุการณ์เหล่านี้กับทีม:
- กดส่งติดกันสองครั้ง — การดำเนินการเดิมต้องไม่เพิ่มเป็นสองรายการ
- บันทึกสำเร็จ แต่คำตอบกลับไม่ถึงหน้าจอ — ผู้ใช้ต้องตรวจพบรายการเดิม และข้อความต้องไม่รีบสรุปว่าล้มเหลว
- คนสองคนจองเวลาเดียวกันพร้อมกัน — ผลต้องเป็นไปตามกติกาที่ตกลงไว้ ไม่ใช่ขึ้นอยู่กับว่าใครเห็นหน้าจอก่อน
- แก้ห้องหรือเวลาแล้วส่งใหม่ — ระบบต้องแยกคำขอใหม่ออกจากการลองซ้ำของครั้งก่อน
- ไม่มีสิทธิ์จอง หรือบริการภายนอกไม่พร้อม — ปฏิเสธอย่างถูกต้อง เก็บข้อมูลที่ควรเก็บ และบอกขั้นตอนถัดไปโดยไม่เปิดเผยข้อมูลภายใน
ทดสอบทั้งกติกา การบันทึกจริง และหน้าจอที่คนใช้เห็น การทดสอบฟังก์ชันอย่างเดียวไม่ครอบคลุมปัญหาคำขอที่มาพร้อมกัน ส่วนการคลิกผ่านหน้าจออย่างเดียวก็อาจไม่เห็นรายการซ้ำในข้อมูล
เกณฑ์รับงานควรเขียนเป็นผลที่ตรวจได้ เช่น “ส่งคำขอเดิมพร้อมกันสองครั้งแล้วมีการจองเพียงรายการเดียว” ทีมจะมีจุดตรวจที่ชัดกว่าคำว่า “ระบบต้องไม่พัง”
เริ่มปรับจากแบบฟอร์มเดียว
เลือกแบบฟอร์มที่ทีมใช้บ่อย แล้วถามสามเรื่อง: กดส่งแล้วระบบบอกอะไร หากไม่ได้คำตอบจะตรวจต่อที่ไหน และส่งซ้ำแล้วเกิดอะไรขึ้น
ถ้ายังตอบข้อใดไม่ได้ ให้ปรับเรื่องนั้นก่อนเพิ่มลูกเล่นบนหน้าจอ คนใช้ควรได้ทั้งหน้าจอที่อ่านง่ายและคำตอบว่างานที่เพิ่งทำไปอยู่ตรงไหน
อ่านต่อเรื่อง ระบบที่คนอื่นรับไปดูแลได้ หรือใช้ Checklist เตรียมโปรเจกต์ จดขั้นตอนที่อยากปรับ ก่อน คุยกับทีม INTECH
