หัวข้อ 27 อย่าขับเร็วจนเกินระยะไฟหน้า (Don't Outrun Your Headlights)

การทำนายเนี่ยเป็นเรื่องยาก โดยเฉพาะถ้าต้องทำนายอนาคต

Lawrence "Yogi" Berra, จากภาษิตเดนมาร์ก

มันเป็นคืนที่ดึก สงัด และฝนตกหนัก รถสปอร์ตสองที่นั่งซิ่งเลี้ยวลดไปตามโค้งแคบๆ ของถนนภูเขาที่คดเคี้ยว แทบจะทรงตัวไม่อยู่ในแต่ละโค้ง จนกระทั่งเจอโค้งหักศอกที่รถพลาดหลุดโค้งไป พุ่งชนราวกั้นกะโหลกกะลาแล้วตกลงไปในหุบเขาเบื้องล่างจนระเบิดลุกเป็นไฟ เมื่อตำรวจทางหลวงมาถึงที่เกิดเหตุ หัวหน้าตำรวจก็ส่ายหัวอย่างสลดใจ แล้วบอกว่า "สงสัยจะขับเร็วจนเกินระยะไฟหน้า (outrun their headlights) สินะ"

เจ้ารถสองที่นั่งคันนั้นวิ่งเร็วกว่าความเร็วแสงหรือเปล่า? เปล่าเลย ขีดจำกัดความเร็วเนี่ยมันตายตัวอยู่แล้ว สิ่งที่ตำรวจเขาหมายถึงก็คือความสามารถของคนขับที่จะหยุดหรือเลี้ยวได้ทันตามที่ไฟหน้าส่องสว่างขึ้นมาต่างหาก

ไฟหน้ามันมีระยะจำกัดของมันครับ ที่เรียกว่า throw distance ซึ่งถ้าพ้นจุดนั้นไป แสงมันจะกระจายจนใช้การไม่ได้ แถมไฟหน้ามันส่องเป็นเส้นตรงเท่านั้นด้วย มันจะไม่ส่องตามโค้ง ตามเนิน หรือหลุมบ่อในทางที่มันไม่ได้อยู่ในแนวแกนส่องสว่าง (off-axis) ข้อมูลจาก National Highway Traffic Safety Administration บอกว่า ระยะส่องสว่างเฉลี่ยของไฟหน้าแบบต่ำ (low-beam) อยู่ที่ประมาณ 160 ฟุต แต่ที่โชคร้ายคือระยะเบรกที่ความเร็ว 40mph มันคือ 189 ฟุต และถ้าที่ 70mph เนี่ย พุ่งไปถึง 464 ฟุตเลย [35] ดังนั้นจริงๆ แล้ว มันเป็นเรื่องที่เกิดขึ้นได้ง่ายมากครับที่จะขับเร็วจนเกินระยะไฟหน้า (outrun your headlights)

ในงานซอฟต์แวร์ "ไฟหน้า" ของเราก็มีข้อจำกัดเหมือนกันครับ เรามองอนาคตล่วงหน้าไม่ได้ไกลนัก และยิ่งคุณพยายามมองอะไรที่มันนอกเหนือจากแนวเส้นทาง (off-axis) มันก็ยิ่งมืดสลัวลงไปทุกที เพราะฉะนั้น Pragmatic Programmers เลยมีกฎเหล็กที่ยึดถือกันดังนี้ครับ:

Tip 42 ก้าวเดินทีละก้าวเสมอ (Take Small Steps—Always)

ให้ก้าวเดินทีละก้าวอย่างระมัดระวัง คอยเช็ค feedback และปรับปรุงเสมอก่อนจะไปต่อ ให้คิดว่าความเร็วของ feedback นี่แหละคือขีดจำกัดความเร็วของคุณ คุณไม่ควรจะรับงานหรือทำอะไรที่มัน "ใหญ่เกินไป"

ที่ว่า feedback คืออะไรกันแน่? มันก็คืออะไรก็ตามที่มายืนยันหรือหักล้างการกระทำของคุณอย่างอิสระนั่นแหละครับ ยกตัวอย่างเช่น:

  • ผลลัพธ์จาก REPL จะคอยให้ feedback เกี่ยวกับความเข้าใจของคุณใน API และ algorithm
  • Unit tests จะคอยบอกผลลัพธ์จากการแก้โค้ดล่าสุดของคุณ
  • การ demo ให้ user ดูและการได้คุยกันจะช่วยยืนยันเรื่องฟีเจอร์และ usability

แล้วไอ้งานที่มัน "ใหญ่เกินไป" มันคืออะไร? มันก็คืองานประเภทไหนก็ตามที่ต้องการ "การหยั่งรู้อนาคต" (fortune telling) นั่นเองครับ เหมือนกับไฟหน้ารถที่มีระยะ throw จำกัด เราเองก็มองเห็นอนาคตล่วงหน้าได้แค่หนึ่งหรือสองก้าวเท่านั้น อาจจะแค่สองสามชั่วโมงหรือสองสามวัน พ้นจากนั้นไป มันจะไม่ใช่แค่การคาดเดาแบบมีหลักการแล้ว แต่มันคือการมโนไปไกลแล้วครับ คุณอาจจะพบว่าตัวเองเริ่ม "หมอดู" (fortune telling) เมื่อต้อง:

  • ประเมินวันเสร็จงานล่วงหน้าเป็นเดือนๆ
  • วางแผนออกแบบเผื่อการ maintenance หรือ extendability ในอนาคต
  • เดาสิ่งที่ user จะต้องการในอนาคต
  • เดาเรื่องการรองรับของเทคโนโลยีในวันข้างหน้า

เดี๋ยวก่อนครับ คุณอาจจะแย้งขึ้นมาว่า "อ้าว แล้วเราไม่ควรออกแบบโค้ดเผื่อ maintenance ในอนาคตเหรอ?" คำตอบคือ "ควรครับ" แต่ต้องอยู่ในระดับที่คุณพอมองเห็นได้เท่านั้น ยิ่งคุณพยายามทำนายอนาคตมากเท่าไหร่ ความเสี่ยงที่จะผิดพลาดก็ยิ่งสูงขึ้น แทนที่จะไปเสียเวลาออกแบบเพื่ออนาคตที่ไม่แน่นอน ให้เปลี่ยนมาเป็นการออกแบบโค้ดให้ "ถูกเปลี่ยนใหม่ได้ง่าย" (replaceable) แทนดีกว่าครับ ทำให้การโละโค้ดเก่าทิ้งแล้วแทนที่ด้วยโค้ดใหม่ที่เหมาะกว่ากลายเป็นเรื่องง่าย ซึ่งการทำให้โค้ด replaceable เนี่ย มันจะช่วยเรื่อง cohesion, coupling, decoupling และ DRY ไปในตัวด้วย ทำให้ design โดยรวมมันออกมาดีขึ้นครับ

แม้ว่าคุณจะมั่นใจในอนาคตแค่ไหนก็ตาม แต่มันมีโอกาสเสมอที่ "หงส์ดำ" (black swan) จะโผล่มาให้เห็นที่หัวโค้งข้างหน้าครับ

Black Swans (หงส์ดำ)

ในหนังสือของเขาชื่อ The Black Swan: The Impact of the Highly Improbable [Tal10], Nassim Nicholas Taleb ได้กล่าวไว้ว่าเหตุการณ์สำคัญๆ ในประวัติศาสตร์ทั้งหมดเนี่ย ล้วนเกิดจากเหตุการณ์ที่ยากจะคาดเดาและเกิดขึ้นได้ยากมากชนิดที่อยู่นอกเหนือความคาดหมายปกติทั้งนั้นแหละครับ ซึ่งเจ้าพวก outliers เหล่านี้ ถึงแม้ว่าในทางสถิติมันจะหายาก แต่พอมันเกิดทีนี่ผลกระทบมหาศาลเลย (disproportionate effects) นอกจากนี้ cognitive biases ของเราเองก็มักจะทำให้เรามองไม่เห็นการเปลี่ยนแปลงเล็กๆ น้อยๆ ที่มันแฝงตัวเข้ามาทีละนิดในงานของเราด้วย (ดูหัวข้อที่ 4 เรื่อง ​_Stone Soup and Boiled Frogs_​)

ช่วงที่หนังสือ The Pragmatic Programmer พิมพ์ครั้งแรกเนี่ย ในนิตยสารคอมพิวเตอร์และฟอรั่มออนไลน์ต่างๆ มีการถกเถียงกันหน้าดำคร่ำเครียดเลยครับว่า "ใครจะเป็นผู้ชนะในสงคราม desktop GUI ระหว่าง Motif หรือ OpenLook?" [36] แต่จริงๆ แล้วมันคือการตั้งคำถามที่ผิดตั้งแต่แรกเลยครับ เชื่อสิว่าพวกคุณส่วนใหญ่คงไม่เคยได้ยินชื่อเทคโนโลยีพวกนี้หรอก เพราะไม่มีใคร "ชนะ" ทั้งนั้นแหละ เพราะ browser-centric web มันพุ่งทะยานเข้ามาครองโลกไปเสียก่อน

Tip 43 หลีกเลี่ยงการทำนายอนาคต (Avoid Fortune-Telling)

ส่วนใหญ่แล้ว พรุ่งนี้ก็คงไม่ต่างจากวันนี้เท่าไหร่หรอกครับ แต่ก็อย่าไปฝากความหวังไว้กับมันมากนักเลย

หัวข้อที่เกี่ยวข้องประกอบด้วย

  • หัวข้อ 12, ​_กระสุนส่องทาง_​ (Tracer Bullets)
  • หัวข้อ 13, ​_ต้นแบบและโพสต์-อิท_​ (Prototypes and Post-it Notes)
  • หัวข้อ 40, ​_การรีแฟกเตอร์_​ (Refactoring)
  • หัวข้อ 41, ​_การทดสอบเพื่อสร้างโค้ด_​ (Test to Code)
  • หัวข้อ 48, ​_แก่นแท้ของความคล่องตัว_​ (The Essence of Agility)
  • หัวข้อ 50, ​_ลูกมะพร้าวช่วยอะไรไม่ได้_​ (Coconuts Don't Cut It)

เชิงอรรถ

[30]

อ้างอิงบางส่วนจากผลงานก่อนหน้าของ Dijkstra, Floyd, Hoare, Wirth และคนอื่นๆ

[31]

ในภาษา C และ C++ มักจะถูกนำมาใช้ในรูปแบบของ macros ส่วนใน Java นั้น assertions จะถูกปิดไว้โดยค่าเริ่มต้น ให้รัน Java VM พร้อมกับแฟล็ก –enableassertions เพื่อเปิดใช้งาน และเปิดค้างไว้เสมอ

[32]

http://www.eps.mcgill.ca/jargon/jargon.html#heisenbug

[33]

สำหรับการอภิปรายเกี่ยวกับอันตรายของโค้ดที่มีความเกี่ยวพันกันสูง (coupled code) ดูหัวข้อที่ 28, ​_การแยกส่วนออกจากกัน_​ (Decoupling)

[34]

ดูคำแนะนำได้ที่นี่

[35]

อ้างอิงจาก NHTSA, ระยะหยุดรถ = ระยะตอบสนอง + ระยะเบรก โดยสมมติว่าเวลาตอบสนองเฉลี่ยอยู่ที่ 1.5 วินาที และความหน่วงอยู่ที่ 17.02 ฟุต/วินาที²

[36]

Motif และ OpenLook เป็นมาตรฐาน GUI สำหรับ Unix workstation ที่ทำงานบน X-Window

ลิขสิทธิ์ © 2020 Pearson Education, Inc.