หอสมุดรัฐสภาใน Washington, DC ตอนนี้มีข้อมูลดิจิทัลออนไลน์อยู่ประมาณ 75 terabytes. เร็ว! ต้องใช้เวลานานแค่ไหนในการส่งข้อมูลทั้งหมดนั่นผ่าน network 1Gbps? ต้องใช้ storage เท่าไหร่สำหรับชื่อและที่อยู่ล้านรายการ? การบีบอัด text ขนาด 100Mb ใช้เวลาเท่าไหร่? แล้วกี่เดือนล่ะถึงจะส่งมอบโปรเจกต์ของคุณได้?
ถ้ามองเผินๆ คำถามพวกนี้มันก็แทบจะไร้ความหมาย เพราะมันขาดข้อมูลไปตั้งหลายอย่าง. แต่ถึงอย่างนั้น เราก็ยังตอบได้ ถ้าคุณคุ้นเคยกับการทำ estimating. และในระหว่างขั้นตอนการประเมินนี่แหละ คุณจะเริ่มเข้าใจบริบทของสิ่งที่โปรแกรมของคุณต้องเจอมากขึ้นด้วย.
พอคุณฝึกทำ estimate และพัฒนารักษานี้จนมันกลายเป็นเซนส์ที่ทำให้คุณเห็นภาพรวมของขนาดและความสำคัญได้ คุณจะดูเหมือนมีพลังพิเศษในการระบุความเป็นไปได้ (feasibility) ของอะไรสักอย่างได้ในทันที. พอมีใครพูดว่า "เราจะส่ง backup ข้าม network connection ไปที่ S3," คุณจะรู้ได้เองเลยว่ามันเป็นไปได้ไหมในทางปฏิบัติ. และเวลาที่คุณเขียน code คุณจะรู้ได้ทันทีว่าส่วนไหนควรต้องทำ optimizing และส่วนไหนที่ปล่อยไว้เฉยๆ ก็ได้.
| Tip 23 | Estimate to Avoid Surprises |
|---|
และเป็นโบนัสเลยครับ เดี๋ยวตอนจบส่วนนี้ เราจะเฉลยคำตอบที่ถูกต้องเพียงหนึ่งเดียวที่คุณควรใช้เวลาที่มีใครมาขอให้คุณช่วยทำ estimate.
How Accurate Is Accurate Enough?
ถ้ามองกันจริงๆ ทุกคำตอบมันก็คือ estimate ทั้งนั้นแหละ. มันแค่ว่าบางอันแม่นกว่าบางอันแค่นั้นเอง. ดังนั้นคำถามแรกที่คุณต้องถามตัวเองเมื่อมีคนมาขอให้ทำ estimate คือ บริบทที่คนคนนั้นจะเอาคำตอบไปใช้คืออะไร? เขาต้องการความแม่นยำสูง หรือแค่ต้องการตัวเลขคร่าวๆ (ballpark figure)?
สิ่งที่น่าสนใจอย่างหนึ่งเกี่ยวกับการทำ estimating คือ หน่วยที่คุณใช้นั้นมีผลต่อการตีความผลลัพธ์. ถ้าคุณบอกว่างานนี้จะใช้เวลาประมาณ 130 วันทำการ (working days) คนจะเริ่มคาดหวังว่ามันควรจะเสร็จในเวลาใกล้เคียงกับเลขนั้นมาก. แต่ถ้าคุณบอกว่า "อ๋อ ประมาณหกเดือน," พวกเขาจะเข้าใจทันทีว่ามันอาจจะอยู่ในช่วงระหว่างห้าถึงเจ็ดเดือนจากนี้. ทั้งสองตัวเลขบอกระยะเวลาที่ใกล้เคียงกัน แต่นิยามของ "130 วัน" มันแฝงไปด้วยความรู้สึกที่ว่าคุณแม่นยำกว่าที่คุณรู้สึกจริงๆ. เราแนะนำให้คุณเลือกสเกลของ time estimate ดังนี้:
| Duration | Quote estimate in | |
|---|---|---|
| 1–15 days | Days | |
| 3–6 weeks | Weeks | |
| 8–20 weeks | Months | |
| 20+ weeks | Think hard before giving an estimate |
ดังนั้น ถ้าหลังจากที่คุณทำทุกอย่างเรียบร้อยแล้ว และคุณสรุปได้ว่าโปรเจกต์น่าจะใช้เวลา 125 วันทำการ (25 สัปดาห์), คุณอาจจะเลือกส่ง estimate ว่า "ประมาณหกเดือน" แทน.
หลักการเดียวกันนี้สามารถนำไปใช้กับ estimate ในปริมาณอะไรก็ได้: เลือกหน่วยของคำตอบให้สะท้อนถึงระดับความแม่นยำที่คุณต้องการจะสื่อสาร.
Where Do Estimates Come From?
ทุกๆ estimate นั้นตั้งอยู่บนพื้นฐานของ models ของปัญหาที่เจอ. แต่ก่อนที่จะลงลึกไปเรื่องเทคนิคการสร้าง model เราต้องบอกทริคพื้นฐานอย่างหนึ่งที่ให้คำตอบดีเสมอ: ลองไปถามคนที่เคยทำมาแล้วดูสิ. ก่อนที่คุณจะทุ่มเทเวลาไปกับการสร้าง model ลองมองหาคนที่เคยผ่านสถานการณ์คล้ายๆ กันมาในอดีตดูก่อน. ลองดูว่าเขาแก้ปัญหายังไง. ถึงแม้คุณอาจจะเจออะไรที่ไม่ตรงกับคุณเป๊ะๆ 100% แต่น่าจะแปลกใจว่าประสบการณ์ของคนอื่นนั้นมีประโยชน์กว่าที่คิด.
Understand What's Being Asked
ขั้นตอนแรกของงาน estimation คือการทำความเข้าใจว่าจริงๆ แล้วเขากำลังถามหาอะไรกันแน่. นอกเหนือจากเรื่องความแม่นยำที่เราคุยกันไปแล้ว คุณยังต้องเข้าใจขอบเขต (scope) ของ domain นั้นด้วย. หลายครั้ง scope มันก็ซ่อนอยู่ในคำถามอยู่แล้วนั่นแหละ แต่คุณต้องทำให้มันเป็นนิสัยที่จะต้องคิดถึง scope ก่อนที่จะเริ่มเดาตัวเลข. บ่อยครั้งที่ scope ที่คุณเลือกจะกลายเป็นส่วนหนึ่งของคำตอบที่คุณจะให้: "ถ้าสมมติว่ารถไม่ติดและน้ำมันรถไม่หมด ผมน่าจะไปถึงที่นั่นภายใน 20 นาทีครับ."
Build a Model of the System
นี่คือส่วนที่สนุกที่สุดของ estimating เลย. จากความเข้าใจในคำถามของคุณ ลองสร้าง model ง่ายๆ ในหัวดู. ถ้าคุณกำลัง estimate เรื่อง response times, model ของคุณอาจจะประกอบด้วย server และปริมาณ traffic ที่เข้ามา. แต่ถ้าเป็นเรื่องโปรเจกต์, model ก็อาจจะเป็นลำดับขั้นตอนที่ทีมของคุณใช้ในการพัฒนา พร้อมกับภาพคร่าวๆ ว่าระบบจะถูก implement ขึ้นมายังไง.
การสร้าง model นั้นทั้งสร้างสรรค์และมีประโยชน์ในระยะยาว บ่อยครั้งที่ขั้นตอนการสร้าง model จะนำไปสู่การค้นพบรูปแบบ (patterns) และกระบวนการบางอย่างที่ซ่อนอยู่ซึ่งเรามองไม่เห็นในตอนแรก คุณอาจจะถึงขั้นอยากกลับไปพิจารณาคำถามเดิมใหม่เลยก็ได้: "คุณขอให้ทำ estimate สำหรับงาน X แต่พอดูแล้ว งาน Y ซึ่งเป็นรูปแบบหนึ่งของ X ดูเหมือนจะใช้เวลาทำแค่ครึ่งเดียว โดยแลกกับการตัดออกไปแค่ฟีเจอร์เดียวเท่านั้น"
การสร้าง model จะทำให้เกิดความไม่แม่นยำเข้ามาในขั้นตอนการทำ estimate ซึ่งเรื่องนี้เป็นสิ่งที่เลี่ยงไม่ได้และยังมีข้อดีในตัวของมันเองด้วย เพราะคุณกำลังแลกความเรียบง่ายของ model กับความแม่นยำ การทุ่มเทแรงกายแรงใจในการสร้าง model เพิ่มขึ้นเป็นสองเท่าอาจจะช่วยเพิ่มความแม่นยำให้คุณได้เพียงเล็กน้อยเท่านั้น ประสบการณ์จะเป็นตัวบอกคุณเองว่าเมื่อไหร่ที่ควรหยุดปรับแต่งมันได้แล้ว
Break the Model into Components
เมื่อคุณได้ model แล้ว คุณสามารถแยกมันออกมาเป็นส่วนประกอบย่อยๆ ได้ คุณจะต้องค้นหากฎทางคณิตศาสตร์ที่อธิบายว่าส่วนประกอบเหล่านี้มีปฏิสัมพันธ์กันอย่างไร บางครั้งส่วนประกอบหนึ่งอาจให้ค่าเพียงค่าเดียวที่นำไปบวกเพิ่มในผลลัพธ์ บางส่วนประกอบอาจให้ตัวคูณ ในขณะที่บางส่วนอาจซับซ้อนกว่านั้น (เช่น ส่วนที่จำลองการเข้ามาของ traffic ในโหนดหนึ่ง)
คุณจะพบว่าแต่ละส่วนประกอบมักจะมีพารามิเตอร์ (parameters) ที่ส่งผลต่อการทำงานร่วมกันใน model โดยรวม ในขั้นตอนนี้ ให้ระบุพารามิเตอร์แต่ละตัวออกมาให้ได้ก่อน
Give Each Parameter a Value
เมื่อคุณแยกพารามิเตอร์ออกมาได้แล้ว คุณสามารถเริ่มกำหนดค่าให้กับมันทีละตัว ในขั้นตอนนี้คุณอาจจะคาดเดาความผิดพลาดได้บ้าง ทริคคือต้องดูว่าพารามิเตอร์ตัวไหนที่มีผลต่อผลลัพธ์มากที่สุด และพยายามกำหนดค่านั้นให้ใกล้เคียงความเป็นจริงมากที่สุด โดยปกติ พารามิเตอร์ที่นำค่าไปบวกเพิ่มในผลลัพธ์มักจะมีนัยสำคัญน้อยกว่าตัวที่นำไปคูณหรือหาร การเพิ่มความเร็วของสายสัญญาณ (line speed) เป็นสองเท่าอาจส่งผลให้ปริมาณข้อมูลที่ได้รับในหนึ่งชั่วโมงเพิ่มขึ้นเป็นสองเท่า ในขณะที่การเพิ่ม transit delay เข้าไป 5ms อาจไม่เห็นผลที่ชัดเจนเลยด้วยซ้ำ
คุณควรจะมีวิธีการคำนวณพารามิเตอร์ที่สำคัญเหล่านี้อย่างมีเหตุผล สำหรับตัวอย่างเรื่องการรอคิว (queuing) คุณอาจจะต้องการวัดอัตราการเข้าของทรานแซกชัน (transaction arrival rate) ในระบบที่มีอยู่จริง หรือหาระบบที่คล้ายกันมาวัดดู ในทำนองเดียวกัน คุณสามารถวัดเวลาที่ใช้ในการตอบสนองต่อหนึ่งคำขอ (serve a request) หรือทำ estimate โดยใช้เทคนิคที่อธิบายไว้ในหัวข้อนี้ ในความเป็นจริง คุณมักจะพบว่าตัวคุณเองกำลังทำ estimate บนพื้นฐานของ subestimate อื่นๆ และนี่แหละคือจุดที่ความผิดพลาดก้อนใหญ่ที่สุดจะเข้ามาแทรกซึมได้
Calculate the Answers
มีเพียงในกรณีที่เรียบง่ายที่สุดเท่านั้นที่ estimate จะให้คำตอบเพียงอย่างเดียว คุณอาจจะพอใจที่จะบอกว่า "ผมสามารถเดินห้าบล็อกข้ามเมืองได้ใน 15 นาที" อย่างไรก็ตาม เมื่อระบบซับซ้อนขึ้น คุณจะต้องการให้คำตอบแบบแบ่งรับแบ่งสู้ (hedge) ลองคำนวณหลายๆ ครั้งโดยเปลี่ยนค่าพารามิเตอร์ที่สำคัญไปเรื่อยๆ จนกว่าจะรู้ว่าตัวไหนที่ส่งผลกระทบต่อ model จริงๆ การใช้ spreadsheet จะช่วยได้มาก จากนั้นให้สรุปคำตอบโดยอิงตามพารามิเตอร์เหล่านั้น: "response time จะอยู่ที่ประมาณสามในสี่วินาทีหากระบบใช้ SSD และมี memory 32GB และจะเป็นหนึ่งวินาทีถ้ามี memory 16GB" (สังเกตไหมว่า "สามในสี่วินาที" ให้ความรู้สึกถึงระดับความแม่นยำที่ต่างจาก 750ms)
ในระหว่างขั้นตอนการคำนวณ หากคุณได้คำตอบที่ดูแปลกๆ อย่าเพิ่งรีบปัดมันทิ้งไป ถ้าการคำนวณเลขของคุณถูกต้องแล้วละก็ นั่นแสดงว่าความเข้าใจในปัญหาหรือ model ของคุณอาจจะผิด ซึ่งนั่นแหละคือข้อมูลที่มีค่ามาก
Keep Track of Your Estimating Prowess
เราคิดว่าเป็นไอเดียที่ยอดเยี่ยมที่จะบันทึก estimate ของคุณเอาไว้เพื่อดูว่ามันใกล้เคียงแค่ไหน ถ้าการทำ estimate โดยรวมมีการคำนวณ subestimate ด้วย ก็ให้บันทึกพวกนั้นเอาไว้ด้วยเช่นกัน บ่อยครั้งคุณจะพบว่าการทำ estimate ของคุณค่อนข้างแม่นเลยทีเดียว—อันที่จริง หลังจากที่ทำไปได้สักพัก คุณจะเริ่มคุ้นเคยกับความแม่นยำนี้
เมื่อการทำ estimate ออกมาผิด อย่าแค่ยักไหล่แล้วปล่อยผ่าน—จงหาคำตอบว่าทำไม บางทีพารามิเตอร์ที่คุณเลือกอาจจะไม่ตรงกับความเป็นจริงของปัญหา หรือบางที model ของคุณอาจจะผิด ไม่ว่าจะด้วยเหตุผลอะไรก็ตาม ให้ใช้เวลาค้นหาว่าเกิดอะไรขึ้น และนั่นจะทำให้การทำ estimate ครั้งต่อไปของคุณดีขึ้น
Estimating Project Schedules
ปกติแล้วคุณจะถูกขอให้ทำ estimate ว่างานแต่ละชิ้นจะใช้เวลานานเท่าไหร่ ถ้า "งานนั้น" ซับซ้อน การทำ estimate ก็จะทำได้ยากมาก ในส่วนนี้เราจะดูเทคนิคสองอย่างที่จะช่วยลดความไม่แน่นอนนั้น
Painting the Missile
"ต้องใช้เวลานานแค่ไหนในการทาสีบ้าน?"
"ก็ ถ้าทุกอย่างเป็นไปด้วยดี และสีทาได้พื้นที่ตามที่โฆษณาไว้ มันอาจจะใช้เวลาแค่ 10 ชั่วโมง แต่ก็น่าจะเป็นไปได้ยากครับ ผมเดาว่าตัวเลขที่สมจริงกว่าน่าจะอยู่ที่ประมาณ 18 ชั่วโมง และแน่นอนว่าถ้าอากาศแย่ลง มันอาจจะลากยาวไปถึง 30 ชั่วโมงหรือมากกว่านั้นก็ได้"
นั่นแหละคือวิธีที่คนในโลกความจริงทำ estimate กัน ไม่ได้ใช้แค่ตัวเลขเดียว (เว้นแต่คุณจะบังคับให้เขาบอกตัวเลขมา) แต่เป็นการบอกตามช่วงของสถานการณ์ที่ต่างกันออกไป
เมื่อกองทัพเรือสหรัฐฯ ต้องการวางแผนโปรเจกต์เรือดำน้ำ Polaris พวกเขาใช้วิธีการทำ estimate แบบนี้ด้วยระเบียบวิธีที่เรียกว่า Program Evaluation Review Technique หรือ PERT
ทุกงานใน PERT จะมีค่า estimate แบบมองในแง่ดี (optimistic), แบบที่เป็นไปได้มากที่สุด (most likely) และแบบมองในแง่ร้าย (pessimistic) งานต่างๆ จะถูกจัดเรียงเป็นเครือข่ายความสัมพันธ์ (dependency network) จากนั้นคุณจะใช้สถิติพื้นฐานเพื่อระบุเวลาที่ดีที่สุดและแย่ที่สุดที่เป็นไปได้สำหรับโปรเจกต์โดยรวม
การใช้ช่วงของค่าแบบนี้เป็นวิธีที่ดีมากในการเลี่ยงสาเหตุที่พบบ่อยที่สุดของความผิดพลาดในการทำ estimate นั่นคือการ "เผื่อ" (padding) ตัวเลขไว้เพราะคุณไม่แน่ใจ แต่สถิติที่อยู่เบื้องหลัง PERT จะช่วยกระจายความไม่แน่นอนนั้นออกไปให้คุณ และทำให้คุณได้ค่า estimate ของโปรเจกต์โดยรวมที่ดีขึ้น
แต่อย่างไรก็ตาม เราก็ไม่ได้ชอบวิธีนี้มากนัก เพราะคนมักจะสร้างแผนภูมิขนาดเท่าฝาบ้านของงานทั้งหมดในโปรเจกต์ขึ้นมา แล้วก็เชื่อไปเองว่าพอมีสูตรคำนวณแล้ว ค่า estimate ที่ได้จะแม่นยำ ซึ่งความเป็นจริงแล้วมักจะไม่เป็นอย่างนั้น เพราะพวกเขาไม่เคยทำแบบนี้มาก่อนเลยต่างหาก
Eating the Elephant
เราพบว่าบ่อยครั้งวิธีเดียวที่จะกำหนดตารางเวลา (timetable) ของโปรเจกต์ได้ คือการเก็บเกี่ยวประสบการณ์จากโปรเจกต์เดิมนั้นเอง ซึ่งมันจะไม่ใช่ความย้อนแย้งเลยหากคุณฝึกการพัฒนาแบบทีละส่วน (incremental development) และทำซ้ำขั้นตอนต่อไปนี้ด้วยฟังก์ชันที่แบ่งย่อยออกมาเป็นส่วนเล็กๆ:
- ตรวจสอบความต้องการ (Check requirements)
- วิเคราะห์ความเสี่ยง (และจัดลำดับความสำคัญของสิ่งที่เสี่ยงที่สุดก่อน)
- ออกแบบ พัฒนา (implement) และรวมระบบ (integrate)
- ตรวจสอบความถูกต้องกับผู้ใช้งาน
ในช่วงแรก คุณอาจจะมีเพียงภาพลางๆ ว่าต้องทำกี่รอบ (iterations) หรือแต่ละรอบจะใช้เวลานานแค่ไหน บางระเบียบวิธีอาจจะกำหนดให้คุณต้องฟันธงเรื่องนี้ตั้งแต่วางแผนเริ่มต้น แต่อย่างไรก็ตาม สำหรับโปรเจกต์ทั่วไป (ที่ไม่ใช่งานง่ายๆ สบายๆ) การทำแบบนั้นถือเป็นความผิดพลาด เว้นแต่ว่าคุณกำลังทำแอปพลิเคชันที่คล้ายกับที่เคยทำมาก่อน โดยใช้ทีมงานเดิมและเทคโนโลยีเดิม ไม่เช่นนั้นมันก็เป็นแค่การเดาเท่านั้นเอง
ดังนั้น เมื่อคุณเขียน code และทดสอบฟังก์ชันเริ่มต้นเสร็จแล้ว ให้ทำเครื่องหมายว่านั่นคือจุดจบของรอบแรก จากประสบการณ์นั้น คุณจะสามารถปรับปรุงการเดาในตอนแรกเกี่ยวกับจำนวนรอบและสิ่งที่จะรวมอยู่ในแต่ละรอบได้ การปรับปรุงจะดีขึ้นเรื่อยๆ ในแต่ละครั้ง และความมั่นใจในตารางเวลาจะเพิ่มขึ้นตามไปด้วย การทำ estimate แบบนี้มักจะทำกันในช่วงรีวิวของทีมเมื่อสิ้นสุดแต่ละรอบของการทำงาน
นั่นแหละคือที่มาของมุกตลกเก่าๆ ที่ว่าเราจะกินช้างทั้งตัวได้ยังไง: ก็กินทีละคำยังไงล่ะ
| Tip 24 | Iterate the Schedule with the Code |
|---|
เรื่องนี้อาจจะไม่ถูกใจบรรดาผู้บริหารสักเท่าไหร่ เพราะพวกเขามักจะต้องการตัวเลขที่แน่นอนและรวดเร็วก่อนที่โปรเจกต์จะเริ่มเสียอีก คุณต้องช่วยให้เขาเข้าใจว่าทีมงาน ประสิทธิภาพการทำงาน และสภาพแวดล้อมต่างหากที่เป็นตัวกำหนดตารางเวลา การทำให้เรื่องนี้เป็นทางการและปรับปรุงตารางเวลาให้เป็นส่วนหนึ่งในทุกๆ รอบการทำงาน จะทำให้คุณสามารถให้ค่า estimate ของตารางเวลาที่แม่นยำที่สุดเท่าที่จะเป็นไปได้
What to Say When Asked for an Estimate
คุณบอกไปว่า "เดี๋ยวผมกลับมาบอกครับ"
คุณมักจะได้ผลลัพธ์ที่ดีกว่าเสมอถ้าคุณชะลอขั้นตอนลงและใช้เวลาสักนิดเพื่อทำตามขั้นตอนที่เราอธิบายไว้ในหัวข้อนี้ การทำ estimate ตรงเครื่องทำกาแฟ (เหมือนกับกาแฟนั่นแหละ) สุดท้ายมันจะกลับมาหลอกหลอนคุณเอง
Related Sections Include
- Topic 7, _Communicate!_
- Topic 39, _Algorithm Speed_
Challenges
- เริ่มจดบันทึกการทำ estimate ของคุณเอาไว้ แล้วติดตามดูว่าแต่ละอันมันแม่นยำแค่ไหน ถ้าความผิดพลาดของคุณเกิน 50% ให้พยายามค้นหาว่ามันผิดพลาดตรงจุดไหน
Exercises
Exercise 9 (possible answer)
คุณถูกถามว่า "อันไหนมี bandwidth สูงกว่ากัน: ระหว่างการเชื่อมต่อ network 1Gbps กับคนคนหนึ่งที่เดินระหว่างคอมพิวเตอร์สองเครื่องพร้อมกับอุปกรณ์เก็บข้อมูล 1TB ที่เต็มเปี่ยมอยู่ในกระเป๋า?" คุณจะตั้งข้อกำหนด (constraints) อะไรบ้างเพื่อให้แน่ใจว่าขอบเขตของคำตอบของคุณถูกต้อง? (ตัวอย่างเช่น คุณอาจจะบอกว่าไม่นับรวมเวลาที่ใช้ในการเข้าถึงอุปกรณ์เก็บข้อมูล)
Exercise 10 (possible answer)
สรุปแล้ว อันไหนมี bandwidth สูงกว่ากัน?
Footnotes
ถอดความมาจากเพลงเก่าของ Arlen/Mercer…
หรือบางที เพื่อรักษาความมีสติของคุณไว้ ก็ทำทุกๆ 10 ครั้งแทน…
https://github.com/OAI/OpenAPI-Specification
ในความเป็นจริง วิธีคิดแบบนี้มันดูอ่อนหัดไปหน่อย นอกจากคุณจะโชคดีมากๆ การเปลี่ยนแปลง requirements ส่วนใหญ่ในโลกความจริงมักจะส่งผลกระทบต่อฟังก์ชันจำนวนมากในระบบ อย่างไรก็ตาม ถ้าคุณวิเคราะห์การเปลี่ยนแปลงในระดับของฟังก์ชัน การเปลี่ยนแปลงแต่ละฟังก์ชันก็ยังควรจะส่งผลกระทบต่อเพียงโมดูลเดียวในอุดมคติ
อันที่จริง หนังสือเล่มนี้เขียนขึ้นด้วย Markdown และถูกจัดหน้าโดยตรงจาก source ที่เป็น Markdown นี่แหละ
ลองเอาตัวอย่างระบบที่ไม่เป็นเส้นตรง (nonlinear) หรือระบบที่ยุ่งเหยิง (chaotic) แล้วลองเปลี่ยนข้อมูลที่ใส่เข้าไปเพียงเล็กน้อยสิ คุณอาจจะได้ผลลัพธ์ที่ยิ่งใหญ่และคาดเดาไม่ได้เลยทีเดียว มุกเดิมๆ ที่ว่าผีเสื้อขยับปีกในโตเกียวอาจจะเป็นจุดเริ่มต้นของเหตุการณ์ที่นำไปสู่พายุทอร์นาโดในเท็กซัส ฟังดูเหมือนโปรเจกต์ไหนที่คุณรู้จักบ้างไหม?
Copyright © 2020 Pearson Education, Inc.