สายตากี่คู่ที่จะจัดการความซับซ้อนได้

การสังเกตในภาพรวม ว่ารูปแบบตลาดสดช่วยเร่งอัตราการแก้บั๊กและการวิวัฒนาการของโค้ด ก็เป็นส่วนหนึ่ง แต่ในอีกส่วนหนึ่ง เราก็ต้องเข้าใจด้วย ว่ามันทำงานอย่างไรและด้วยเหตุผลใดในระดับย่อยของพฤติกรรมประจำวันของนักพัฒนาและนักทดสอบ ในหัวข้อนี้ (ซึ่งเขียนขึ้นหลังจากบทความฉบับแรกสามปี โดยใช้ข้อมูลเชิงลึกจากนักพัฒนาที่ได้อ่านบทความและสำรวจพฤติกรรมของตน) เราจะพิจารณาโดยละเอียดเกี่ยวกับกลไกที่เกิดขึ้นจริง ผู้อ่านที่ไม่มีพื้นฐานทางเทคนิคอาจข้ามหัวข้อนี้ไปได้

ประเด็นสำคัญที่จะเข้าใจเรื่องนี้ คือการตระหนัก ว่าทำไมรายงานบั๊กจากผู้ใช้ที่ไม่สนใจซอร์สมักจะไม่ค่อยมีประโยชน์นัก ผู้ใช้ที่ไม่สนใจซอร์สมักจะรายงานแค่อาการผิวเผิน โดยถือว่าสภาพแวดล้อมของเขาปกติ ดังนั้นเขาจึง (ก) ละเลยข้อมูลประกอบที่สำคัญ (ข) ไม่ค่อยจะบอกวิธีการที่แน่นอนในการทำให้เกิดบั๊กซ้ำ

ปัญหาของเรื่องนี้ ก็คือความไม่เข้ากันของมโนภาพเกี่ยวกับโปรแกรมของผู้ทดสอบและของผู้พัฒนา ผู้ทดสอบมองจากข้างนอกเข้ามาข้างใน แต่ผู้พัฒนามองจากข้างในออกข้างนอก ในการพัฒนาแบบซอร์สปิด ทั้งสองฝ่ายจะติดแหง็กอยู่กับบทบาททั้งสองนี้ และดูจะคุยกันไม่เข้าใจ รู้สึกว่าอีกฝ่ายน่ารำคาญ

การพัฒนาแบบโอเพนซอร์สทำลายพันธะดังกล่าวเสีย ทำให้ง่ายต่อผู้ทดสอบและผู้พัฒนาที่จะมองภาพร่วมกัน บนพื้นฐานของซอร์สโค้ดจริง และสื่อสารเข้าใจกัน ในทางปฏิบัติแล้ว มีความแตกต่างอย่างมากสำหรับนักพัฒนา ระหว่างรายงานบั๊กที่รายงานแค่อาการภายนอก กับที่พุ่งตรงไปยังเค้าโครงที่มีพื้นฐานจากซอร์สโค้ดของโปรแกรมเอง

แทบทุกครั้ง บั๊กจะแก้ง่ายถ้าบรรยายอาการของเงื่อนไขข้อผิดพลาดได้ในระดับซอร์สโค้ด แม้จะไม่สมบูรณ์ก็ตาม เมื่อผู้ทดสอบบางคนของคุณสามารถชี้ได้ว่า "มีปัญหาเรื่องค่าล้นที่บรรทัด nnn" หรือแม้เพียงแค่ "ภายใต้เงื่อนไข X, Y และ Z ตัวแปรนี้จะตีกลับ" แค่มองที่โค้ดที่มีปัญหาอย่างคร่าวๆ ก็มักเพียงพอที่จะบ่งชี้ชนิดของข้อผิดพลาด และแก้ไขได้ทันที

ดังนั้น การใช้ซอร์สโค้ดทั้งสองฝ่ายจึงช่วยเพิ่มทั้งการสื่อสาร และการเสริมแรงกันระหว่างสิ่งที่ผู้ทดสอบรายงานกับสิ่งที่ผู้พัฒนาหลักรู้ ผลก็คือ มีแนวโน้มจะช่วยประหยัดเวลานักพัฒนาหลักได้ดี แม้จะต้องประสานงานหลายฝ่าย

คุณลักษณ์อีกประการหนึ่งของวิธีการโอเพนซอร์สที่ช่วยประหยัดเวลานักพัฒนา ก็คือโครงสร้างของการสื่อสารของโครงการโอเพนซอร์สทั่วไป ในย่อหน้าก่อน ผมใช้คำว่า "นักพัฒนาหลัก" ซึ่งสะท้อนถึงความแตกต่างระหว่างแกนของโครงการ (ซึ่งมักจะเป็นกลุ่มเล็กๆ การมีนักพัฒนาหลักแค่คนเดียวถือเป็นเรื่องปกติ และหนึ่งถึงสามคนถือว่าธรรมดา) กับนักทดสอบและผู้ร่วมสมทบที่รายล้อม (ซึ่งมักมีจำนวนหลักร้อย)

ปัญหาพื้นฐานที่องค์กรพัฒนาซอฟต์แวร์แบบดั้งเดิมพยายามแก้ ก็คือกฎของบรูกส์: ``การเพิ่มโปรแกรมเมอร์ในโครงการที่ล่าช้า จะทำให้มันยิ่งช้าขึ้นไปอีก'' หรือกล่าวในรูปทั่วไป กฎของบรูกส์ทำนายว่า ความซับซ้อนและต้นทุนการสื่อสารของโครงการ จะเพิ่มในอัตรากำลังสองของจำนวนนักพัฒนา ในขณะที่งานที่ได้จะเพิ่มในแบบเชิงเส้น

กฎของบรูกส์สร้างขึ้นบนพื้นฐานของประสบการณ์ที่ว่า บั๊กต่างๆ มีแนวโน้มที่จะหนีไม่พ้นเรื่องการเชื่อมต่อระหว่างโค้ดที่เขียนโดยคนกลุ่มต่างๆ และค่าโสหุ้ยในการสื่อสาร/ประสานงานกันในโครงการ ก็มีแนวโน้มจะเพิ่มตามจำนวนการเชื่อมโยงระหว่างมนุษย์ ดังนั้น ขนาดของปัญหาจึงโตตามจำนวนช่องทางสื่อสารระหว่างนักพัฒนา ซึ่งแปรผันตรงกับกำลังสองของจำนวนนักพัฒนา (หรือพูดให้ละเอียดกว่านั้น คือเป็นไปตามสูตร N*(N - 1)/2 เมื่อ N คือจำนวนนักพัฒนา)

การวิเคราะห์ตามกฎของบรูกส์ (และความกลัวจำนวนนักพัฒนามากๆ ในทีมพัฒนาที่เป็นผลตามมา) ตั้งอยู่บนข้อสมมุติที่ซ่อนอยู่ คือโครงสร้างการสื่อสารของโครงการ จะต้องเป็นกราฟสมบูรณ์ (complete graph) เสมอไป กล่าวคือ ทุกคนจะพูดกับคนอื่นๆ ทุกคน แต่ในโครงการโอเพนซอร์ส นักพัฒนารอบนอกต่างทำงานกับสิ่งที่กลายเป็นงานย่อยที่แบ่งทำขนานกันได้ และมีปฏิสัมพันธ์กันเองน้อยมาก การแก้ไขโค้ดและรายงานบั๊กต่างส่งเข้าสู่ทีมพัฒนาหลัก และค่าโสหุ้ยตามกฎของบรูกส์ ก็จะเกิดกับเฉพาะ ภายใน กลุ่มนักพัฒนาหลักกลุ่มเล็กๆ นี้เท่านั้น [SU]

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

นักทดสอบที่ส่งรายงานสิ่งที่อาจเป็นบั๊กที่แสดงอาการหลายแบบดังกล่าว โดยรายงานในระดับซอร์สโค้ด (เช่น "ผมคิดว่ามันมีช่วงว่างระหว่างการจัดการสัญญาณแถวๆ บรรทัดที่ 1250" หรือ "คุณเติมค่าศูนย์ในบัฟเฟอร์นั้นตรงไหนหรือ?") อาจกำลังให้ข้อมูลที่สำคัญยิ่งยวดสำหรับแก้อาการหลายอาการต่อผู้พัฒนาซึ่งอาจอยู่ใกล้โค้ดเกินกว่าจะเห็นได้ ซึ่งในกรณีเช่นนั้น อาจจะยากหรือเป็นไปไม่ได้เลย ที่จะรู้ว่าอาการผิดปกติอันไหนเกิดจากบั๊กไหน แต่ด้วยการออกบ่อยๆ ก็แทบไม่จำเป็นต้องรู้เลย คนอื่นๆ อาจจะพบอย่างรวดเร็ว ว่าบั๊กของเขาได้รับการแก้ไขหรือยัง ในหลายๆ กรณี รายงานบั๊กในระดับซอร์สโค้ดจะทำให้อาการผิดปกติหลายอย่างหายไป โดยไม่ได้ชี้ชัดถึงวิธีที่แก้ไขเลย

ข้อผิดพลาดที่ซับซ้อนและแสดงหลายอาการ ยังมีแนวโน้มจะมีหลายทางที่จะไล่ไปสู่บั๊กที่แท้จริง ทางไหนที่ผู้พัฒนาหรือผู้ทดสอบคนหนึ่งๆ จะสามารถไล่ไปได้ ก็ขึ้นอยู่กับรายละเอียดปลีกย่อยของสภาพแวดล้อมของบุคคลนั้น และอาจกลายเป็นทางที่แน่นอนชัดเจนได้ในภายหลัง ผลก็คือ นักพัฒนาและผู้ทดสอบแต่ละคนจะช่วยสุ่มตัวอย่างสถานะของโปรแกรมแบบต่างๆ ขณะหาสมุฏฐานของอาการ ยิ่งบั๊กละเอียดอ่อนและซับซ้อนเท่าใด ความชำนาญโดยลำพังก็ช่วยเชื่อมโยงได้น้อยเท่านั้น

สำหรับบั๊กที่ง่ายและทำซ้ำได้ การสุ่มตัวอย่างก็ไม่จำเป็นนัก ความชำนาญในการตรวจบั๊กและความคุ้นเคยกับโค้ดและโครงสร้างโปรแกรมจะช่วยได้มาก แต่สำหรับบั๊กที่ซับซ้อนแล้ว ก็ต้องอาศัยการสุ่มตัวอย่างช่วย ในสภาวะดังกล่าว การมีผู้แกะรอยจากหลายเส้นทางจะได้ผลกว่าการใช้ไม่กี่คนแกะรอยทีละทาง แม้ว่าไม่กี่คนที่ว่านั้นจะมีความชำนาญโดยเฉลี่ยสูงกว่าก็ตาม

ผลของเรื่องนี้จะใหญ่โตมาก ถ้าความยากของการแกะรอยแบบต่างๆ จากอาการเพื่อหาบั๊กนั้น แตกต่างกันมากจนไม่สามารถทำนายได้จากอาการ นักพัฒนาเพียงคนเดียวที่ทดลองแกะรอยทีละแบบจะมีโอกาสที่จะเลือกแบบที่ยากก่อนพอๆ กับที่จะเลือกแบบที่ง่ายก่อน ในทางกลับกัน สมมุติว่ามีหลายคนลองแกะรอยพร้อมๆ กันขณะที่จะออกรุ่นอย่างกระชั้นชิด ก็มีโอกาสที่จะมีบางคนพบทางที่ง่ายที่สุดทันที และแก้บั๊กได้ในเวลาอันสั้น ผู้ดูแลโครงการจะเห็น แล้วก็ออกรุ่นใหม่ และคนอื่นๆ ที่กำลังแกะรอยบั๊กเดียวกันก็สามารถจะหยุดได้ ก่อนที่จะใช้เวลากับการแกะรอยแบบที่ยากนั้นนานเกินไป [RJ]