การเขียนโปรแกรมในฐานะการสร้างทฤษฎี (1985)
(gwern.net)- 「Programming as Theory Building」 ของ Peter Naur มองว่าการเขียนโปรแกรมไม่ใช่กิจกรรมในการ ผลิตตัวบทของโปรแกรม แต่เป็นกิจกรรมที่โปรแกรมเมอร์ ก่อรูปทฤษฎี เกี่ยวกับปัญหาและวิธีแก้
- คำว่า “ทฤษฎี” ในที่นี้ไม่ใช่เพียงข้อความนามธรรมหรือคำอธิบายการออกแบบที่ถูกบันทึกไว้
- เป็นความเข้าใจว่าปัญหาในโลกจริงมีความหมายอย่างไร
- สามารถอธิบายได้ว่าโครงสร้างของโปรแกรมสอดคล้องกับโลกจริงนั้นอย่างไร
- ให้เหตุผลได้ว่าทำไมจึงออกแบบเช่นนั้น
- และสามารถตัดสินได้ว่าเมื่อมีความต้องการใหม่เข้ามา จะบูรณาการเข้าไปในโครงสร้างเดิมอย่างไร
- ดังนั้น ความรู้แกนกลางของโปรแกรมจึงไม่ได้ถูกบรรจุไว้อย่างครบถ้วนในโค้ดหรือเอกสาร แต่ อยู่ในหัวของโปรแกรมเมอร์ที่เข้าใจโปรแกรมนั้น
การเขียนโปรแกรมและความรู้
- Naur มองว่าการเขียนโปรแกรมคือกิจกรรมที่จับคู่กิจกรรมในโลกจริงเข้ากับการจัดการสัญลักษณ์เชิงรูปแบบที่คอมพิวเตอร์สามารถทำได้
- ในมุมมองนี้ การแก้ไขโปรแกรมก็เป็นส่วนหนึ่งของการเขียนโปรแกรมด้วย
- เพราะเมื่อกิจกรรมในโลกจริงเปลี่ยนไป โปรแกรมก็ต้องเปลี่ยนตาม
- แก่นแท้ของการเขียนโปรแกรมไม่ใช่เอกสารหรือผลลัพธ์เป็นโค้ด แต่เป็นความรู้เฉพาะที่โปรแกรมเมอร์ค่อย ๆ สั่งสมขึ้น
- เอกสารมีความสำคัญ แต่เป็นเพียงสิ่งสนับสนุน
- เอกสารไม่สามารถทดแทนทฤษฎีได้อย่างสมบูรณ์
- เอกสารเป็นเครื่องมือที่ช่วยให้เกิดการก่อรูปทฤษฎีมากกว่า
กรณีศึกษา 1: การถ่ายทอดคอมไพเลอร์และความล้มเหลว
- กลุ่ม A สร้างคอมไพเลอร์สำหรับภาษา L
- กลุ่ม B ได้รับโค้ด เอกสาร และคำแนะนำจาก A เพื่อสร้างคอมไพเลอร์สำหรับภาษา L + M ที่ขยายเพิ่ม
- แม้จะได้รับโค้ดและเอกสารอย่างเพียงพอ แต่ B ไม่สามารถใช้พลังของโครงสร้างเดิมในบางการออกแบบได้ และเสนอวิธีแก้แบบแปะเพิ่มเป็นจุด ๆ
- A มองเห็นปัญหาได้ทันที และเสนอวิธีแก้ที่เรียบง่ายและเป็นธรรมชาติกว่าภายในโครงสร้างเดิม
- แก่นของกรณีนี้คือ
- ตัวบทของโปรแกรมและเอกสารเพียงอย่างเดียวไม่สามารถถ่ายทอดทฤษฎีเชิงออกแบบที่ลึกซึ้งได้
- คำตอบของคำถามว่าเหตุใดจึงออกแบบเช่นนั้น และควรขยายต่ออย่างไร ไม่อาจถ่ายทอดได้เพียงพอด้วยเอกสารอย่างเดียว
- หลังจากนั้น เมื่อโปรแกรมเมอร์คนอื่นที่ไม่ได้รับการชี้นำจาก A เข้ามาแก้ไขคอมไพเลอร์ โครงสร้างที่แข็งแรงเดิมก็ค่อย ๆ อ่อนแอลงจากส่วนเพิ่มเติมที่ไร้รูปแบบ
- สิ่งนี้แสดงให้เห็นว่าตัวบทของโปรแกรมและเอกสารมีข้อจำกัดในการรักษาทฤษฎีการออกแบบหลักไว้
กรณีศึกษา 2: ระบบเรียลไทม์ขนาดใหญ่
- มีการยกกรณีของระบบเรียลไทม์เชิงอุตสาหกรรมขนาดประมาณ 200,000 บรรทัด
- โปรแกรมเมอร์ที่รับผิดชอบการติดตั้งและวิเคราะห์ข้อบกพร่องมีความเชื่อมโยงใกล้ชิดกับระบบมาอย่างยาวนานตั้งแต่ช่วงต้นของการออกแบบ
- เมื่อตรวจวินิจฉัยปัญหา พวกเขาพึ่งพาความเข้าใจระบบแบบฉับพลันของตนเองและโค้ดที่มีคำอธิบายกำกับเป็นหลัก
- ในทางตรงกันข้าม โปรแกรมเมอร์ปฏิบัติการจากภายนอกที่ได้รับเอกสารและการฝึกอบรมกลับประสบความยากลำบากซ้ำแล้วซ้ำเล่า
- ส่วนโปรแกรมเมอร์ผู้ชำนาญของผู้ผลิตสามารถแก้ปัญหาเหล่านั้นได้อย่างง่ายดาย
- ข้อสรุปคือ
- การบำรุงรักษาและแก้ไขโปรแกรมขนาดใหญ่พึ่งพาความรู้ของผู้ที่อยู่กับโปรแกรมนั้นมายาวนานอย่างเป็นสาระสำคัญ
- คำอธิบายที่ถูกจัดทำเป็นเอกสารไม่สามารถทดแทนความรู้นั้นได้อย่างสมบูรณ์
แนวคิดเรื่อง “ทฤษฎี” ของ Ryle
- Naur นำแนวคิดเรื่องทฤษฎีของ Gilbert Ryle มาใช้
- การมีทฤษฎีไม่ได้หมายถึงเพียงการรู้ข้อความบางอย่าง
- แต่หมายถึงการรู้ว่าจะทำบางสิ่งอย่างไร
- สามารถอธิบายสิ่งนั้นได้
- สามารถตอบคำถามได้
- และสามารถให้เหตุผลรองรับการตัดสินใจของตนเองได้
- กิจกรรมที่ชาญฉลาดไม่จำเป็นต้องถูกลดรูปเป็นกิจกรรมที่แค่ทำตามกฎเสมอไป
- เพราะตัวการทำตามกฎเองก็ต้องถูกกระทำอย่างชาญฉลาด
- หากบอกว่าต้องมีกฎอีกชุดสำหรับวิธีทำตามกฎ ก็จะเกิดการถอยไม่รู้จบ
- ดังนั้น กิจกรรมทางปัญญาจึงไม่ใช่เพียงการปฏิบัติตามกฎ แต่รวมถึงความสามารถในการมองเห็นความคล้ายคลึงของสถานการณ์และตอบสนองอย่างเหมาะสม
ทฤษฎีไม่อาจแสดงออกเป็นกฎได้ทั้งหมด
- ผู้ที่มีทฤษฎีจะมองเห็นความคล้ายคลึงที่มีความหมายระหว่างสถานการณ์ต่าง ๆ ในโลกจริง
- แต่ความคล้ายคลึงเช่นนี้ยากจะอธิบายออกมาได้ครบถ้วนด้วยเกณฑ์หรือกฎที่ชัดเจน
- ตัวอย่างเช่น
- ความคล้ายกันของใบหน้า
- ความคล้ายกันของท่วงทำนอง
- ความคล้ายกันของรสไวน์
- เช่นเดียวกัน ในการเขียนโปรแกรม การจะมองเห็นว่าความต้องการใหม่คล้ายกับโครงสร้างเดิมอย่างไร และควรผนวกรวมไว้ตรงไหน ก็ยากจะลดรูปเป็นกฎง่าย ๆ
- นี่คือแก่นของความรู้โดยนัย
ทฤษฎีที่โปรแกรมเมอร์ต้องมี
- โปรแกรมเมอร์ที่มีทฤษฎีของโปรแกรมควรต้องทำสิ่งต่อไปนี้ได้
1. ต้องอธิบายความสอดคล้องระหว่างโลกจริงกับโปรแกรมได้
- ต้องอธิบายได้ว่าแต่ละส่วนของโปรแกรมสอดคล้องกับกิจกรรมหรือแนวคิดใดในโลกจริง
- และในทางกลับกัน ก็ต้องอธิบายได้ด้วยว่ากิจกรรมบางอย่างในโลกจริงถูกแทนอย่างไรภายในโปรแกรม
- การจะตัดสินได้ว่าอะไรเกี่ยวข้องและอะไรไม่เกี่ยวข้อง จำเป็นต้องมีความเข้าใจต่อโลกจริงโดยรวม
2. ต้องให้เหตุผลได้ว่าทำไมโปรแกรมจึงเป็นเช่นนั้น
- ต้องอธิบายได้ว่าเหตุใดโครงสร้างและรายละเอียดการติดตั้งใช้งานของโปรแกรมจึงถูกออกแบบเช่นนั้น
- การให้เหตุผลนี้อาจอาศัยกฎ การอนุมาน หลักการออกแบบ หรือการประมาณเชิงปริมาณ
- แต่ท้ายที่สุดแล้ว การตัดสินว่าจะใช้หลักการใดขึ้นอยู่กับวิจารณญาณโดยตรงของโปรแกรมเมอร์
3. ต้องตอบสนองต่อความต้องการแก้ไขใหม่อย่างสร้างสรรค์ได้
- ต้องมองเห็นได้ว่าความต้องการใหม่คล้ายกับฟังก์ชันหรือโครงสร้างใดในโปรแกรมเดิม
- และต้องสามารถออกแบบให้การแก้ไขนั้นผสานเข้าไปในทฤษฎีเดิมได้อย่างเป็นธรรมชาติบนพื้นฐานของความคล้ายคลึงดังกล่าว
- ความสามารถนี้ยากจะทดแทนได้ด้วยขั้นตอนที่ถูกทำเป็นเอกสารเท่านั้น
การแก้ไขโปรแกรมและต้นทุน
- ซอฟต์แวร์ย่อมต้องถูกแก้ไขอย่างหลีกเลี่ยงไม่ได้
- เพราะระหว่างการใช้งานจะเกิดความต้องการใหม่
- และเงื่อนไขของโลกจริงก็เปลี่ยนไปด้วย
- โดยทั่วไปมักคิดว่าการแก้ไขโปรแกรมเดิมย่อมถูกกว่าสร้างใหม่
- แต่ในมุมมองของ Naur ความคาดหวังนี้ไม่ได้ถูกต้องเสมอไป
- ต้นทุนของการแก้ไขโปรแกรมไม่ใช่ต้นทุนของการแก้ข้อความในไฟล์
- ต้นทุนหลักคือการทำความเข้าใจทฤษฎีของโปรแกรมเดิม
- และการผสานความต้องการใหม่เข้าไปในทฤษฎีนั้น
- ดังนั้น แค่เพราะโค้ดเป็นข้อความที่แก้ไขได้ง่าย ก็ไม่ได้แปลว่าการแก้ไขจะง่าย
ข้อจำกัดของความยืดหยุ่น
- แนวคิดที่ว่าควรใส่ความยืดหยุ่นเพื่อรองรับการเปลี่ยนแปลงในอนาคตไว้ล่วงหน้า มีความถูกต้องเพียงบางส่วน
- ความยืดหยุ่นไม่ใช่ของฟรี
- ต้องตัดสินใจก่อนว่าจะเตรียมรับสถานการณ์อนาคตแบบใด
- ต้องออกแบบพารามิเตอร์และโครงสร้าง
- และมีต้นทุนด้านการพัฒนา การทดสอบ และการอธิบาย
- ประโยชน์ของมันขึ้นอยู่กับเหตุการณ์ในอนาคตที่ไม่แน่นอน
- เพราะฉะนั้น ความยืดหยุ่นจึงไม่อาจเป็นคำตอบทั่วไปของการรับมือกับการเปลี่ยนแปลง
- สิ่งสำคัญไม่ใช่การฝังโครงสร้างไว้ล่วงหน้าเพื่อรองรับทุกการเปลี่ยนแปลง แต่คือความสามารถในการตัดสินอย่างเหมาะสมเมื่อการเปลี่ยนแปลงมาถึง โดยอาศัยทฤษฎีของโปรแกรม
การแก้ไขที่ดีและการแก้ไขที่ไม่ดี
- แม้เป็นการแก้ไขที่ทำให้พฤติกรรมภายนอกเป็นไปตามต้องการเหมือนกัน ก็อาจถูกทำได้หลายวิธี
- เมื่อมองจากภายนอก วิธีเหล่านั้นอาจดูถูกต้องทั้งหมด
- แต่เมื่อมองจากมุมของทฤษฎีโปรแกรม ความแตกต่างกลับมีมาก
- การแก้ไขบางแบบเป็นการขยายทฤษฎีเดิมอย่างเป็นธรรมชาติ
- บางแบบทำงานเหมือนแพตช์ที่ไปแปะทับบนโครงสร้างเดิม
- หากการแก้ไขแบบหลังเกิดขึ้นซ้ำ ๆ โปรแกรมก็จะค่อย ๆ กลายเป็นงานปะชุน
- ความสามารถในการอยู่รอดระยะยาวของโปรแกรมขึ้นอยู่กับว่าการแก้ไขแต่ละครั้งหยั่งรากในทฤษฎีเดิมได้ดีเพียงใด
ชีวิต ความตาย และการฟื้นคืนของโปรแกรม
ชีวิตของโปรแกรม
- โปรแกรมยังมีชีวิตอยู่เมื่อโปรแกรมเมอร์ที่มีทฤษฎีของโปรแกรมนั้นยังคงควบคุมมันอย่างแข็งขัน
- คนเหล่านี้สามารถตอบสนองต่อคำขอแก้ไขได้อย่างใช้ปัญญา
ความตายของโปรแกรม
- เมื่อทีมที่มีทฤษฎีของโปรแกรมสลายตัว โปรแกรมก็ถือว่าตาย
- โปรแกรมที่ตายแล้วอาจยังรันได้และยังให้ผลลัพธ์ที่มีประโยชน์
- แต่ความตายนั้นจะเผยให้เห็นเมื่อมันไม่สามารถตอบสนองต่อคำขอแก้ไขได้อย่างเหมาะสม
การฟื้นคืนของโปรแกรม
- นี่คือความพยายามของทีมใหม่ที่จะสร้างทฤษฎีของโปรแกรมเดิมขึ้นมาอีกครั้ง
- Naur มองว่าในความหมายที่เคร่งครัดแล้ว สิ่งนี้เป็นไปไม่ได้
- เพราะไม่สามารถกู้คืนทฤษฎีที่ทีมเดิมมีได้อย่างครบถ้วนจากเอกสารและโค้ดเพียงอย่างเดียว
- ต่อให้ฟื้นคืนได้ ก็มีแนวโน้มว่าจะมีต้นทุนสูง ยากลำบาก และก่อให้เกิดทฤษฎีที่ต่างจากเดิม
- ในบางกรณี การให้ทีมใหม่แก้ปัญหาใหม่ตั้งแต่ต้นอาจดีกว่าและถูกกว่าการพยายามรักษาโค้ดเดิม
คำวิจารณ์ต่อวิธีวิทยา
- Naur มองว่าวิธีวิทยาการเขียนโปรแกรมคือ “ชุดของกฎที่กำหนดว่าโปรแกรมเมอร์ควรทำงานอะไร ตามลำดับใด”
- แต่ในมุมมองของการก่อรูปทฤษฎี วิธีวิทยาในความหมายนี้ไม่สามารถจับแก่นแท้ของการเขียนโปรแกรมได้
- เหตุผลคือ
- การก่อรูปทฤษฎีไม่มีลำดับตายตัว
- ทฤษฎีโดยเนื้อแท้แล้วไม่ใช่การประกอบส่วนต่าง ๆ แบบเส้นตรง
- สัญกรณ์หรือรูปแบบเอกสารอาจช่วยการก่อรูปทฤษฎีได้ แต่ไม่ใช่ตัวทฤษฎีเอง
- ดังนั้น จึงได้ข้อสรุปว่าไม่มีวิธีใดที่ถูกต้องเป็นสากลสำหรับกิจกรรมหลักของการเขียนโปรแกรม
ไม่ได้แปลว่าวิธีวิทยาไร้ค่าโดยสิ้นเชิง
- สิ่งที่ Naur ปฏิเสธคือวิธีวิทยาในฐานะกระบวนการที่รับประกันการออกแบบที่ดีได้อย่างเชิงกล
- วิธีวิทยา เทคนิคการออกแบบ สัญกรณ์ และเทคนิคการตรวจสอบ ยังอาจมีคุณค่าเชิงการศึกษาได้
- โปรแกรมเมอร์ที่คุ้นเคยกับกรณีศึกษาที่ดี หลักการจัดโครงสร้าง และเทคนิคการตรวจสอบ มีโอกาสสูงกว่าจะก่อรูปทฤษฎีที่ดีกว่าได้
- อย่างไรก็ตาม จะใช้เทคนิคใด เมื่อใด และตามลำดับใด ต้องปล่อยให้เป็นการตัดสินของโปรแกรมเมอร์ที่เข้าใจปัญหาจริง
สถานะของโปรแกรมเมอร์
- หากมองการเขียนโปรแกรมเหมือนการผลิตเชิงอุตสาหกรรม โปรแกรมเมอร์ก็จะถูกปฏิบัติราวกับเป็นชิ้นส่วนที่เปลี่ยนแทนกันได้
- นั่นคือมุมมองที่เชื่อว่าเพียงทำตามกระบวนการและกฎ ใครก็สร้างผลลัพธ์เดียวกันได้
- Naur ปฏิเสธมุมมองนี้
- หากผลผลิตหลักของโปรแกรมคือทฤษฎีที่โปรแกรมเมอร์มีอยู่ โปรแกรมเมอร์ก็ไม่ใช่แรงงานที่เปลี่ยนแทนกันได้ง่าย
- โปรแกรมเมอร์ใกล้เคียงกับวิชาชีพที่รับผิดชอบการพัฒนาและดูแลกิจกรรมทั้งหมดที่มีคอมพิวเตอร์รวมอยู่ด้วยอย่างมีความรับผิดชอบ
- เพราะฉะนั้น โปรแกรมเมอร์ควรได้รับทั้งสถานะและความรับผิดชอบอย่างต่อเนื่อง
- การศึกษาก็ควรมุ่งไปไกลกว่าการสอนไวยากรณ์ สัญกรณ์ หรือเทคนิคการประมวลผลข้อมูลแบบพื้นฐาน ไปสู่การพัฒนาความสามารถในการก่อรูปทฤษฎี
อุปมาใน XP และการก่อรูปทฤษฎี
- “อุปมา” ของ XP อธิบายได้ดีด้วยมุมมองการก่อรูปทฤษฎีของ Naur
- อุปมาที่ดีช่วยให้ทีมตั้งข้อคาดหมายคล้ายกันเกี่ยวกับโครงสร้างของโปรแกรม
- ตัวอย่างเช่น
- เข้าใจโปรแกรมว่าเป็น “สายการประกอบ”
- เข้าใจโปรแกรมว่าเป็น “ร้านอาหาร”
- อุปมาที่ดีไม่ใช่เพียงการเปรียบเทียบเล่น ๆ
- แต่มันช่วยให้นักออกแบบตัดสินได้ว่าควรคาดหวังโครงสร้างแบบใด
- ควรเพิ่มโค้ดใหม่ไว้ตรงไหน
- และควรทำให้มันประสานกับโค้ดที่คนอื่นเขียนไว้อย่างไร
- ยิ่งมีสมาชิกทีมมากและมีการทำงานแบบขนานมากเท่าไร คุณค่าของอุปมาที่ใช้ร่วมกันก็ยิ่งสูงขึ้น
- หากไม่มีทฤษฎีร่วมกัน โปรแกรมเมอร์แต่ละคนก็จะสร้างทฤษฎีของตัวเอง และระบบจะยิ่งไม่สอดคล้องกันและซับซ้อนขึ้นเรื่อย ๆ
บทบาทของเอกสาร
- เอกสารยากที่จะตามสถานะปัจจุบันของโปรแกรมให้ทันอย่างสมบูรณ์
- แต่ก็ไม่ได้หมายความว่าเอกสารไม่จำเป็น
- เป้าหมายของเอกสารไม่ใช่การบันทึกทุกสิ่ง แต่คือการช่วยให้โปรแกรมเมอร์คนถัดไปก่อรูปทฤษฎีที่เหมาะสมได้
- เอกสารที่ดีจะกระตุ้นความทรงจำและประสบการณ์ของผู้อ่าน และเปิดเส้นทางความคิดที่ถูกต้องให้
- เอกสารลักษณะนี้อยู่ได้นานกว่าเอกสารที่เพียงไล่รายการคลาส ฟังก์ชัน หรือโมดูลในปัจจุบัน
องค์ประกอบของเอกสารการออกแบบที่ดี
- นักออกแบบที่มีประสบการณ์มักเริ่มเอกสารด้วยหัวข้อต่อไปนี้
- อุปมาหลัก
- คำอธิบายวัตถุประสงค์ของคอมโพเนนต์หลัก
- แผนภาพปฏิสัมพันธ์หลักระหว่างคอมโพเนนต์สำคัญ
- ทั้งสามอย่างนี้ช่วยทีมถัดไปอย่างมากในการก่อรูปทฤษฎีการออกแบบ
- ตัวซอร์สโค้ดเองก็เป็นสื่อสำหรับถ่ายทอดทฤษฎีเช่นกัน
- การตั้งชื่อที่สม่ำเสมอ
- โครงสร้างที่เรียบง่าย
- รูปแบบที่คาดเดาได้
- การลดข้อยกเว้นที่ไม่จำเป็นให้น้อยที่สุด
- ส่วนสำคัญจำนวนมากของ “โค้ดสะอาด” เกี่ยวข้องกับการที่ผู้อ่านสามารถก่อรูปทฤษฎีที่สอดคล้องเกี่ยวกับระบบได้ง่ายเพียงใด
ยังไม่มีความคิดเห็น