Image

Een schip op het strand is een baken in zee.
[ เรือที่เกยตื้นบนหาดทราย คือประภาคารให้แก่ท้องทะเล ]
DUTCH PROVERB

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

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

ดังนั้น เรามาเริ่มต้นด้วยการระบุถึงศาสตร์แห่งการเขียนโปรแกรมระบบ และทั้งความสุขและความทุกข์ที่แฝงอยู่ในนั้น

The Programming Systems Product (ผลิตภัณฑ์ระบบซอฟต์แวร์)

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

แล้วทำไมทีมพัฒนาในอุตสาหกรรมทั้งหมดถึงยังไม่ถูกแทนที่ด้วยคู่หูในโรงรถที่ทุ่มเทเช่นนั้นล่ะ? เราต้องดูที่ สิ่งที่ กำลังถูกผลิตขึ้น

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

Figure 1.1. Evolution of the programming systems product (วิวัฒนาการของผลิตภัณฑ์ระบบซอฟต์แวร์)

Image

มีสองวิธีที่โปรแกรมสามารถถูกแปลงเป็นวัตถุที่มีประโยชน์มากขึ้นแต่มีต้นทุนสูงขึ้น ทั้งสองวิธีนี้แสดงด้วยเส้นแบ่งในแผนภาพ

เมื่อเคลื่อนลงมาผ่านเส้นแบ่งแนวนอน โปรแกรมจะกลายเป็น programming product หรือผลิตภัณฑ์ซอฟต์แวร์ นี่คือโปรแกรมที่ใครก็ตามสามารถเรียกใช้งาน ทดสอบ ซ่อมแซม และขยายต่อได้ มันใช้งานได้ในสภาพแวดล้อมการทำงานหลายแบบ สำหรับชุดข้อมูลหลากหลาย เพื่อให้กลายเป็น programming product ที่ใช้งานได้ทั่วไป โปรแกรมจะต้องถูกเขียนในลักษณะที่เป็น generalization โดยเฉพาะอย่างยิ่ง ช่วงและรูปแบบของอินพุตจะต้องถูกทำให้เป็น general เท่าที่อัลกอริทึมพื้นฐานจะอนุญาตอย่างสมเหตุสมผล จากนั้นโปรแกรมจะต้องถูกทดสอบอย่างละเอียดเพื่อให้สามารถพึ่งพาได้ หมายความว่าต้องเตรียม ชุดทดสอบจำนวนมากที่สำรวจช่วงอินพุตและตรวจสอบขอบเขตของมัน จากนั้นจึงรันและบันทึกผล สุดท้าย การเลื่อนสถานะโปรแกรมเป็น programming product ต้องมีเอกสารที่สมบูรณ์เพื่อให้ทุกคนสามารถใช้งาน แก้ไข และขยายมันได้ ตามกฎคร่าว ๆ ผมประมาณว่า programming product มีต้นทุนอย่างน้อยสามเท่าของโปรแกรมที่ debug แล้วซึ่งมีฟังก์ชันเดียวกัน

เมื่อเคลื่อนผ่านเส้นแบ่งแนวตั้ง โปรแกรมจะกลายเป็นส่วนประกอบใน programming system หรือระบบซอฟต์แวร์ นี่คือกลุ่มของโปรแกรมที่ทำงานร่วมกัน มีการประสานงานในเชิงฟังก์ชันและมีระเบียบในเชิงรูปแบบ เพื่อให้การประกอบกันเป็นสิ่งอำนวยความสะดวกที่สมบูรณ์สำหรับงานขนาดใหญ่ เพื่อเป็นส่วนประกอบของ programming system โปรแกรมจะต้องถูกเขียนให้ทุกอินพุตและเอาต์พุตสอดคล้องกันในไวยากรณ์และความหมายกับอินเทอร์เฟซที่ถูกกำหนดไว้อย่างแม่นยำ โปรแกรมจะต้องถูกออกแบบให้ใช้เฉพาะทรัพยากรตามงบประมาณที่กำหนดไว้เท่านั้น — พื้นที่หน่วยความจำ อุปกรณ์รับเข้า-ส่งออก เวลาเครื่องคอมพิวเตอร์ สุดท้าย โปรแกรมจะต้องถูกทดสอบร่วมกับส่วนประกอบอื่น ๆ ของระบบในทุกชุดค่าผสมที่คาดไว้ การทดสอบนี้ต้องทำอย่างกว้างขวาง เพราะจำนวนเคสเพิ่มขึ้นแบบ combinatorial และใช้เวลานาน เพราะบั๊กที่ละเอียดอ่อนเกิดจากการโต้ตอบที่ไม่คาดคิดระหว่างส่วนประกอบที่ debug แล้ว ส่วนประกอบของ programming system มีต้นทุนอย่างน้อยสามเท่าของโปรแกรมเดี่ยวที่มีฟังก์ชันเดียวกัน ต้นทุนอาจสูงกว่านี้ถ้าระบบมีหลายส่วนประกอบ

ที่มุมล่างขวาของ Fig. 1.1 คือ programming systems product หรือผลิตภัณฑ์ระบบซอฟต์แวร์ สิ่งนี้แตกต่างจากโปรแกรมธรรมดาในทุกด้านที่กล่าวมา มันมีต้นทุนสูงกว่าเก้าเท่า แต่มันคือสิ่งที่มีประโยชน์อย่างแท้จริง ซึ่งเป็นผลผลิตที่ตั้งใจของความพยายามในการเขียนโปรแกรมระบบส่วนใหญ่

The Joys of the Craft (ความสุขในวิชาชีพ)

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

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

อย่างที่สองคือความพอใจจากการสร้างสิ่งที่มีประโยชน์ต่อผู้อื่น ในส่วนลึก เราอยากให้คนอื่นได้ใช้งานผลงานของเราและพบว่ามันมีประโยชน์ ในแง่นี้ programming system ก็ไม่ได้แตกต่างไปจากที่ใส่ดินสอดินเหนียวชิ้นแรกของเด็ก "สำหรับโต๊ะทำงานของคุณพ่อ"

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

อย่างที่สี่คือความสุขจากการเรียนรู้อยู่เสมอ ซึ่งเกิดจากธรรมชาติของงานที่ไม่เคยซ้ำซาก ไม่ทางใดก็ทางหนึ่ง ปัญหาก็ใหม่อยู่เสมอ และผู้แก้ปัญหาก็ได้เรียนรู้สิ่งใหม่ ๆ บางครั้งเป็นเชิงปฏิบัติ บางครั้งเป็นเชิงทฤษฎี และบางครั้งก็ทั้งสองอย่าง

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

แต่สิ่งที่โปรแกรมสร้างขึ้นนั้น ไม่เหมือนกับคำพูดของกวี คือจับต้องได้ในแง่ที่ว่ามันเคลื่อนไหวและทำงานได้ สร้างผลลัพธ์ที่มองเห็นได้แยกจากตัวโครงสร้างเอง มันพิมพ์ผลลัพธ์ วาดรูป สร้างเสียง ขยับแขนกล เวทมนตร์ในตำนานและเทพนิยายได้เป็นจริงขึ้นมาในยุคของเราแล้ว เราพิมพ์คาถาที่ถูกต้องบนคีย์บอร์ด และจอแสดงผลก็มีชีวิตขึ้นมา แสดงสิ่งที่ never were nor could be

การเขียนโปรแกรมจึงสนุกเพราะมันตอบสนองความปรารถนาในการสร้างสรรค์ที่ฝังลึกอยู่ในตัวเรา และทำให้ประสาทสัมผัสที่เรามีร่วมกับมนุษย์ทุกคนพึงพอใจ

The Woes of the Craft (ความทุกข์ในวิชาชีพ)

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

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

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

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

ความทุกข์ถัดมาคือ การออกแบบแนวคิดใหญ่ ๆ นั้นสนุก แต่การหาเจอบั๊กเล็ก ๆ น่ารำคาญนั้นเป็นแค่งาน ไม่ว่ากิจกรรมสร้างสรรค์ใด ๆ ก็ต้องมีชั่วโมงอันน่าเบื่อของงานที่ meticulous และ tedious และการเขียนโปรแกรมก็ไม่มีข้อยกเว้น

ต่อมา เราพบว่าการ debug มีการลู่เข้าแบบ linear หรือแย่กว่านั้น ในขณะที่เรา somehow คาดหวังการเข้าใกล้จุดจบแบบ quadratic ดังนั้นการทดสอบก็ยืดเยื้อเรื่อยไป บั๊กยาก ๆ ตัวสุดท้ายใช้เวลาในการค้นหามากกว่าบั๊กแรก ๆ

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

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

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

นี่คือการเขียนโปรแกรม — ทั้งหลุมยางมะตอยที่ทำให้ความพยายามมากมายจมปลัก และกิจกรรมสร้างสรรค์ที่มีทั้งความสุขและความทุกข์ในแบบของมันเอง สำหรับหลายคน ความสุขนั้นมีมากกว่าความทุกข์มากมาย และสำหรับพวกเขา หนังสือเล่มนี้ที่เหลือจะพยายามวางสะพานไม้บางส่วนข้ามหลุมยางมะตอยนี้