- กรณีศึกษาระหว่างการพัฒนาแอปพลิเคชันสร้างรายงานที่เพิ่มตัวเลือก –dry-run เพื่อให้สามารถจำลองผลลัพธ์การทำงานได้
- ตัวเลือกนี้จะแสดงว่างานใดจะถูกดำเนินการบ้างโดยไม่มีการเปลี่ยนแปลงจริง ทำให้สามารถ ทดสอบได้อย่างปลอดภัยและรับฟีดแบ็กได้รวดเร็ว
- นักพัฒนาสามารถใช้สิ่งนี้เพื่อตรวจสอบการตั้งค่า การเข้าถึง และสถานะของระบบได้ทันที และนำไปใช้เป็น เครื่องมือตรวจสอบประจำวัน
- ข้อเสียที่กล่าวถึงคือ ความซับซ้อนที่เพิ่มขึ้นเล็กน้อย จากการต้องตรวจสอบแฟล็ก dryRun ภายในโค้ด
- ในแอปพลิเคชันแบบสั่งงาน ฟังก์ชัน –dry-run มีประโยชน์มาก และยิ่งนำมาใช้ตั้งแต่ช่วงต้นของโปรเจ็กต์ ก็ยิ่งช่วยเพิ่มประสิทธิภาพการพัฒนา
ภูมิหลัง
- แอปพลิเคชันสร้างรายงานที่กำลังพัฒนาใหม่ มีโครงสร้างการทำงานคือสร้างรายงานทุกวันในวันทำการ จากนั้นบีบอัดและอัปโหลดไปยังเซิร์ฟเวอร์ sftp ตรวจสอบการตอบกลับข้อผิดพลาด และส่งอีเมลแจ้งเตือน
- ไฟล์ที่สร้างขึ้นและไฟล์ฟีดแบ็กในแต่ละขั้นตอนจะถูกย้ายไปยังไดเรกทอรีที่ต่างกันตามลำดับขั้น
- ในช่วงเริ่มต้นการพัฒนา จึงนึกถึงตัวเลือก –dry-run ของ Subversion และคำสั่ง ลินุกซ์หลายตัว แล้วเพิ่มความสามารถแบบเดียวกันเข้าไป
- ตัวเลือกนี้จะแสดงว่าเมื่อรันแล้วจะเกิดอะไรขึ้น โดยไม่มีการเปลี่ยนแปลงจริง
- เมื่อรันด้วย –dry-run ระบบจะแสดงเป็นลำดับขั้นว่ารายงานใดจะถูกสร้าง รายงานใดจะถูกยกเว้น ไฟล์ใดจะถูกบีบอัดและย้าย และไฟล์ใดจะถูกอัปโหลดหรือดาวน์โหลดผ่าน sftp
การใช้งานและข้อดี
- เป็นฟังก์ชันที่มีประโยชน์มากจนถูก ใช้งานทุกวันระหว่างการพัฒนาและทดสอบ
- เมื่อนำมาใช้เพื่อตรวจสอบสถานะก่อนรัน จะสามารถยืนยันการตั้งค่า การเข้าถึง และสถานะของระบบได้ทันที
- เนื่องจากไม่มีการเปลี่ยนแปลงจริง จึงสามารถรันได้อย่างปลอดภัย
- หลังจากเปลี่ยนวันที่ในไฟล์สถานะของรายงาน ก็สามารถ ตรวจสอบได้ทันที ว่ารายงานนั้นจะถูกสร้างหรือไม่
- การสร้างรายงานจริงใช้เวลา แต่ dry-run ให้ฟีดแบ็กได้อย่างรวดเร็ว
- แม้ในการทดสอบระบบทั้งหมด ก็ยังช่วยให้มี วงจรการตรวจสอบที่รวดเร็ว
ข้อเสีย
- เนื่องจากต้อง ตรวจสอบแฟล็ก dryRun ซ้ำๆ ภายในโค้ด จึงเกิดความรกของโค้ดขึ้นเล็กน้อย
- ในแต่ละขั้นตอนหลักจะต้องตรวจสอบแฟล็กเพื่อแสดงเพียงล็อกแทนการทำงานจริง
- อย่างไรก็ตาม การตรวจสอบนี้ไม่ได้ลึกมาก และไม่จำเป็นต้องมีการจัดการเพิ่มเติมภายในลอจิกการสร้างรายงาน
- ตรวจสอบเฉพาะในขั้นตอนระดับบนที่ใช้ตัดสินใจว่าจะรันจริงหรือไม่
บทสรุป
- แอปพลิเคชันที่ทำงานแบบสั่งการและสร้างผลลัพธ์ขึ้นมานั้น เหมาะกับตัวเลือก –dry-run มาก
- ในทางกลับกัน แอปพลิเคชันเชิง reactive ที่รอข้อความเข้ามาไม่เหมาะกับแนวทางนี้
- การเพิ่มฟังก์ชันนี้ตั้งแต่ช่วงต้นของโปรเจ็กต์ ช่วยเพิ่มประสิทธิภาพการพัฒนาได้มาก
- แม้จะไม่ใช่ฟังก์ชันที่จำเป็นในทุกสถานการณ์ แต่ก็ถือเป็น เครื่องมือที่มีประโยชน์มากเมื่อใช้ถูกกรณี
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
เมื่อโต้ตอบกับระบบที่มีสถานะ
--dry-runก็อาจเกิด race condition ได้เครื่องมือจะแสดงว่า “จะทำอะไร” ตามสถานะปัจจุบัน แต่เมื่อถึงเวลารันจริง สถานการณ์อาจเปลี่ยนไปแล้ว
เพราะแบบนี้ฉันจึงชอบแนวทาง โหมด “plan” ของ Terraform มากกว่า โหมดนี้จะสร้างแผนที่นำไปใช้รันได้จริง และถ้าสมมติฐานตอนวางแผนเปลี่ยนไป ก็สามารถหยุดหรือ rollback ได้
อีกทั้งยังไม่ต้องใส่
if dry_run:กระจายไปทั่วโค้ด และสามารถแยกการวางแผนกับการรันออกจากกันให้เรียบง่ายเป็นรูปแบบexecute(plan())เกิดปัญหาเรื่องจังหวะเวลาระหว่าง DNS Planner กับ Enactor จนแผนเก่าไปเขียนทับแผนใหม่ล่าสุด
มีการพูดถึงเรื่องนี้ใน เธรด HN ก่อนหน้า ด้วย
เพราะการทำโหมด plan ต้องมีภาษาเฉพาะโดเมนหรือโครงสร้างข้อมูลรองรับ
(1) จับสถานะของระบบไฟล์แล้วบันทึกแผน → (2) ตรวจว่าสถานะยังไม่เปลี่ยนก่อนรันและบันทึกล็อก → (3) เปรียบเทียบกับสถานะก่อนหน้าเพื่อตรวจสอบว่ามีการสูญหายของข้อมูลหรือไม่
ตอนนี้แยกสามขั้นตอนนี้เป็นสคริปต์หรือแฟล็กคนละตัว
rmได้อย่างไรถ้าเครื่องมือไหนไม่มี
--dry-runบางครั้งก็ทำขึ้นมาใช้เองตัวอย่างเช่น ก่อนรันคำสั่ง
sedที่ซับซ้อน จะใช้diffเปรียบเทียบการเปลี่ยนแปลงล่วงหน้าสามารถดูความต่างได้ด้วยคำสั่งอย่าง
diff -u <(echo "hello") <(echo "hello" | sed "s/hello/hi/g")ฉันรวบรวมเรื่องนี้ไว้ใน บล็อกของฉัน
ฉันชอบแพตเทิร์น
--dry-runแต่ โค้ดในเส้นทาง dry ต้องทำงานเหมือนกับเส้นทางจริงถ้าแค่พิมพ์ว่า “จะทำอะไร” แล้วข้าม logic จริงไป ก็อาจพลาดบั๊กตอนรันจริงได้
ควรให้ทำงานเหมือนกันทั้งหมดจนถึงก่อนการเขียนฐานข้อมูลหรือการเรียก API
dry run มีไว้เพื่อแสดงว่า “จะเกิดอะไรขึ้น” ส่วนการทดสอบจริงเป็นอีกเรื่องหนึ่ง
ในทางกลับกัน ฉันชอบใช้แฟล็ก
--commitหรือ--executeแล้วให้การรันปกติเป็นแบบ อ่านอย่างเดียว (dry) มากกว่าแบบนี้จะลดโอกาสที่เผลอทำการเปลี่ยนแปลงจริงโดยไม่ตั้งใจ
--commitอย่างชัดเจนถึงจะมีการเปลี่ยนแปลงตรงกันข้าม เคยมีหลายครั้งที่ลืมใส่
--dry-runแล้วเกิดปัญหาค่าเริ่มต้นจะเปรียบเทียบอย่างเดียว และต้องใส่
--executeถึงจะเปลี่ยนเป็น hard link จริงขั้นตอนยืนยันแบบนี้ช่วยลดความผิดพลาดได้มาก
--wet-runด้วย บางสถานการณ์แฟล็กที่มีความหมายตรงข้ามกลับเข้าใจง่ายกว่าDELETE-ACCOUNTเองจนถึงตอนนี้ยังไม่เคยลบบัญชีผิดพลาดเลยสักครั้ง
ถ้าอยากหลีกเลี่ยงการทำให้โค้ดปนเปื้อน ควรแยก persistence ออกมาเป็นกลยุทธ์ที่ inject ได้
การใส่
if dry_run:กระจายไปทั่วไม่ใช่แนวทางที่ดีอันที่จริง การบังคับให้รัน production แบบชัดเจนด้วย
--wet-runอาจปลอดภัยกว่าแบบนี้จะตัดสินเรื่อง dry run ได้จากจุดเดียว — เป็นสไตล์ “functional core, imperative shell”
rm --wet-run tempfile.tmpทุกครั้งก็ค่อนข้างน่ารำคาญอาจดีกว่าถ้าให้ค่าเริ่มต้นเป็นรันจริง แล้วมีตัวเลือก
--undoไว้ย้อนงานล่าสุด--wet-runเท่าไร แต่ก็เคยใช้วิธีตั้งค่าเริ่มต้นเป็นdry-runแล้วต้องระบุ--no-dry-runถึงจะมีการเปลี่ยนแปลงจริงถ้าเป็นบริการ ระบบควรเลือก safe mode ให้อัตโนมัติตามสภาพแวดล้อมที่รันอยู่ เช่น dev/prod
ในบทความมีประโยคว่า “เพิ่ม
--dry-runไว้ตั้งแต่แรก แล้วพบว่ามีประโยชน์เกินคาด”จริง ๆ แล้วแฟล็กแบบนี้มักเป็นสิ่งที่ AI coding agent (เช่น Claude) เสนอให้อัตโนมัติบ่อยมาก
ทุกวันนี้ที่เครื่องมือ CLI หลายตัวมีแพตเทิร์นคล้ายกัน อาจเป็นผลจาก การลู่เข้าของโค้ดที่ขับเคลื่อนโดยเอเจนต์ ก็ได้
--dry-runของ Subversion ดังนั้นก็ถือว่าเป็นเหตุผลที่น่าเชื่อถือมากพอฉันมักเพิ่มแฟล็ก
--reallyให้กับยูทิลิตี CLI และตั้งค่าเริ่มต้นเป็นอ่านอย่างเดียวจุดประสงค์คือให้มี ขั้นตอนยืนยันโดยเจตนา เพื่อป้องกันความผิดพลาด
--i-meant-thatมาก่อนด้วยมันเป็นคำสั่งลบเครื่องระยะไกล โดยค่าเริ่มต้นจะรอ 10 วินาทีเพื่อเปิดโอกาสให้ยกเลิก
โชคดีที่ไม่เคยมีใครใช้แฟล็กนี้ผิดเลย
ข้อดีอย่างหนึ่งของ PowerShell คือแค่เพิ่ม
[CmdletBinding(SupportsShouldProcess)]เพียงบรรทัดเดียวก็จะได้ฟีเจอร์ dry run ผ่าน
-WhatIfโดยอัตโนมัติ เป็น ความสามารถที่สะดวกมาก-Confirmก็จะถูกเปิดใช้งานด้วย และสามารถโต้ตอบกับ เกณฑ์การยืนยันของผู้ใช้ ผ่านฟังก์ชันShouldProcessได้ด้วย เป็นการออกแบบที่ยอดเยี่ยมมากใน CLI ภายในที่ฉันดูแล ฉันจะใส่
if not dry_run:ไว้ ภายในส่วนเรียก REST APIแบบนี้แทนที่จะยิงคำขอจริง ก็จะเก็บ ล็อกคำสั่ง CURL ไว้ให้ดูว่า request ไหนจะถูกส่งออกไป
แต่ถ้าการเชื่อมต่อกันระหว่าง API ซับซ้อนขึ้น การจำลองก็จะยากขึ้นและซับซ้อนกว่า
if not dry_run:ธรรมดามากฉันดูแล CLI สำหรับ automation pipeline อยู่หลายตัว และใช้แพตเทิร์นนี้กับแทบทุกเครื่องมือ
สิ่งสำคัญคือควรทำเครื่องมือโลคัลให้ดีตั้งแต่แรก
ถ้าแฟล็ก
--dry-runกระจายอยู่ทั่วทั้งโค้ดเบส ควรใช้ แพตเทิร์น state machine เพื่อแยกแต่ละขั้นตอนให้ชัดเจน