ตัวอย่างการคำนวณในหนังสือเล่มนี้ทั้งหมดค่อนข้างเล็ก ซึ่งดีสำหรับการอธิบายแนวคิดและหลักการ แต่เมื่อขยายขนาดขึ้นจะเป็นอย่างไร? คำถามเรื่องความสามารถในการปรับขนาด (scalability) เกิดขึ้นในบริบทต่างๆ。
ประการแรกคือคำถามว่าอัลกอริทึม (algorithm) จะทำงานได้ดีเมื่ออินพุตมีขนาดใหญ่หรือไม่ ปัญหานี้ถูกจัดการโดยการวิเคราะห์ความซับซ้อนทั้งด้านเวลา (runtime) และด้านพื้นที่ (space complexity) ซึ่งกล่าวถึงในส่วนแรกของหนังสือเล่มนี้ โดยเฉพาะใน chapters 2, , , , และ . บางอัลกอริทึมขยายตัวได้ค่อนข้างดี (เช่น การเดินตามเส้นทาง การชงกาแฟ การค้นหา และการเรียงลำดับ) แต่บางอันไม่สามารถทำได้ (เช่น การหาชุดเมนูที่เหมาะสมภายใต้งบประมาณจำกัด) ตามที่อธิบายใน chapter 7 เวลาในการรันของอัลกอริทึมแบบเลขชี้กำลัง (exponential) ทำให้การแก้ปัญหาบางประเภทเป็นไปไม่ได้จริง。
ประการที่สองคือคำถามเกี่ยวกับการสร้าง การเข้าใจ และการบำรุงรักษาระบบซอฟต์แวร์ขนาดใหญ่ การออกแบบและการเขียนโปรแกรมขนาดเล็กค่อนข้างง่าย แต่การพัฒนาระบบซอฟต์แวร์ขนาดใหญ่ยังคงเป็นความท้าทายสำคัญสำหรับวิศวกรซอฟต์แวร์。
เพื่อให้เห็นภาพปัญหา ลองนึกถึงแผนที่ของเมืองหรือประเทศที่คุณอาศัยอยู่ ขนาดมาตราส่วนที่เหมาะสมคืออะไร? ตามที่ Lewis Carroll อธิบายในนวนิยายเล่มสุดท้ายของเขา Sylvie and Bruno Concluded ขนาด 1 ต่อ 1 ไม่มีประโยชน์ เพราะถ้าแผนที่ถูกปูออกมา “มันจะคลุมทั้งประเทศและบังแสงอาทิตย์!” ดังนั้นแผนที่ที่ใช้ประโยชน์ได้จริงต้องมีขนาดเล็กกว่าสิ่งที่มันแทนอย่างมาก และจึงต้องละทิ้งรายละเอียดหลายอย่าง คำถามสำคัญในการสร้างแผนที่คือ ขนาดไหนจึงเล็กพอที่จะจัดการได้แต่ยังใหญ่พอที่จะแสดงรายละเอียดที่เพียงพอ? อีกคำถามคือ รายละเอียดใดควรถูกมองข้ามและรายละเอียดใดควรถูกคงไว้? คำตอบของคำถามหลังมักขึ้นกับบริบทการใช้งานของแผนที่ บางครั้งเราต้องเห็นถนนและที่จอดรถ; ในสถานการณ์อื่นเราอาจสนใจเส้นทางจักรยานและร้านกาแฟ ซึ่งหมายความว่าแผนที่ควรสามารถปรับแต่งได้ตามความต้องการแต่ละบุคคล。
คำอธิบายที่สั้นกว่าสิ่งที่มันกล่าวถึงจะต้องเผชิญกับความท้าทายเรื่องการหาระดับการทั่วไป (generalization) ที่เหมาะสมและการจัดให้มีวิธีการปรับแต่ง คำอธิบายเช่นนี้เรียกว่า abstractions (นามธรรม). วิทยาการคอมพิวเตอร์ส่วนใหญ่สนใจคำถามว่าจะแปลงนามธรรมให้เป็นรูปแบบที่ใช้งานได้อย่างไร อัลกอริทึมถือเป็นนามธรรมที่เด่นชัด มันสรุปลักษณะร่วมของการคำนวณหลายประเภท และพารามิเตอร์ของอัลกอริทึมกำหนดว่าการคำนวณเฉพาะใดจะเกิดขึ้นเมื่ออัลกอริทึมถูกดำเนินการ อัลกอริทึมจะจัดการกับ representations (การแทนข้อมูล) ซึ่งเองก็เป็นนามธรรมที่รักษารายละเอียดบางส่วนเพื่อให้อัลกอริทึมใช้ประโยชน์และละทิ้งรายละเอียดอื่น ๆ ระดับนามธรรมในอัลกอริทึมและอาร์กิวเมนต์ของมันมีความสัมพันธ์กัน การหา "ระดับทั่วไป" ที่เหมาะสมสำหรับอัลกอริทึมมักเกี่ยวข้องกับการแลกเปลี่ยนระหว่างความทั่วไปและประสิทธิภาพ การรองรับอินพุตที่กว้างขึ้นมักต้องการระดับนามธรรมของอินพุตที่สูงขึ้น ซึ่งหมายความว่าอัลกอริทึมจะมีรายละเอียดให้ใช้ประโยชน์น้อยลง。
อัลกอริทึมถูกแสดงออกในรูปของภาษาและถูกรันโดยคอมพิวเตอร์ แนวคิดทั้งหมดนี้ก็อาศัยนามธรรมเช่นกัน และสุดท้าย การย่อรายละเอียดจากการคำนวณเฉพาะเจาะจงที่อัลกอริทึมทำได้ ก็ต้องย่อรายละเอียดสำหรับแนวคิดเรื่องประสิทธิภาพด้านเวลา (runtime) และพื้นที่ (space efficiency) ด้วย เพราะการอธิบายประสิทธิภาพของอัลกอริทึมอย่างมีประสิทธิผลต้องไม่ขึ้นกับขนาดของอินพุตที่ต่างกัน。
ย่อให้สั้น (To Make a Long Story Short)
เรื่องราวหลากหลายถูกกล่าวถึงในหนังสือเล่มนี้ เช่น fairy tale, detective story, เรื่องผจญภัย, musical fantasy, romantic comedy, science fiction comedy และนิยายแฟนตาซี ถึงแม้เรื่องเหล่านี้จะแตกต่างกันมาก แต่ก็มีสิ่งที่เหมือนกันอยู่หลายประการ เช่น มักมีตัวเอกหนึ่งคนหรือมากกว่าที่ต้องเผชิญและเอาชนะความท้าทาย และมักลงท้ายด้วยตอนจบที่เรียกได้ว่าเป็น happy ending แทบทุกเรื่องเป็นรูปเล่มหนังสือ ยกเว้นเรื่องเดียว และเกือบทุกเรื่องมีองค์ประกอบของเวทมนตร์หรือกำลังเหนือธรรมชาติ แม้ว่าคำบรรยายสั้นๆ เหล่านี้จะละทิ้งรายละเอียดของแต่ละเรื่อง แต่ก็ยังให้ข้อมูลที่ช่วยแยกเรื่องเล่าออกจากสิ่งอื่น เช่น รายงานกีฬา อย่างไรก็ตาม มีการแลกเปลี่ยนระหว่างระดับรายละเอียดที่คำบรรยายเผยและจำนวนตัวอย่างที่มันครอบคลุม ดูเหมือนว่าจะมีการแลกเปลี่ยนอีกอย่างระหว่างปริมาณรายละเอียดกับเวลาที่ต้องใช้ในการทำความเข้าใจคำบรรยาย เพราะรายละเอียดมากขึ้นย่อมทำให้คำบรรยายยาวขึ้น ปัญหานี้สามารถจัดการได้ด้วยการตั้งชื่อให้กับคำบรรยายเฉพาะ เช่น detective story ซึ่งตัวเอกเป็นนักสืบที่สืบคดี แท็กไลน์ ตัวอย่างหนัง และบทสรุปสั้น ๆ เป็นสิ่งสำคัญเพราะเป็นวิธีที่มีประสิทธิภาพในการส่งข้อมูลเกี่ยวกับสิ่งที่ควรคาดหวังจากเรื่องนั้น ๆ และช่วยให้เราตัดสินใจได้เร็วขึ้น เช่น ถ้าคุณไม่ชอบเรื่องสืบสวน คุณก็น่าจะคาดได้ว่าไม่น่าจะเพลิดเพลินกับการอ่าน The Hound of the Baskervilles.
เราจะสร้างข้อความสรุปสำหรับชุดของเรื่องราวอย่างไร? คุณอาจเริ่มจากการเปรียบเทียบสองเรื่องและจดจำทุกแง่มุมที่ทั้งสองมีร่วมกัน จากนั้นเปรียบเทียบผลลัพธ์กับเรื่องที่สามและเก็บสิ่งที่ทั้งสามเรื่องมีร่วมกัน แล้วทำต่อไปเรื่อย ๆ กระบวนการนี้กรองทีละขั้นแง่มุมที่ไม่ใช้ร่วมกันและเก็บเฉพาะสิ่งที่เป็นร่วมกัน การกำจัดรายละเอียดที่แยกความต่างนี้เรียกว่า abstraction (นามธรรม) และบางครั้งก็เรียกว่า “abstraction from details.”
ในวิทยาการคอมพิวเตอร์ คำอธิบายที่เป็นผลของการย่อรายละเอียด (abstraction) เองก็ถูกเรียกว่า abstraction และตัวอย่างต่าง ๆ ถูกเรียกว่า instances ของนามธรรมนั้น การใช้คำว่า abstraction ทั้งสำหรับกระบวนการและผลลัพธ์อาจทำให้สับสน ทำไมเราไม่ใช้คำที่คล้ายกัน เช่น generalization? คำนี้ดูเหมาะเพราะ generalization ก็เป็นการสรุปที่ตรงกับตัวอย่างหลายกรณี อย่างไรก็ตาม ในบริบทของวิทยาการคอมพิวเตอร์ คำว่า abstraction มีความหมายมากกว่าแค่การสรุป เพราะนอกจากคำอธิบายที่เป็นสรุปแล้ว มักมีชื่อและประกอบด้วยพารามิเตอร์หนึ่งตัวหรือหลายตัวที่สามารถแทนค่าด้วยค่าจริงในกรณีตัวอย่าง ชื่อและพารามิเตอร์เหล่านี้เรียกรวมกันว่า interface ของนามธรรม Interface ให้กลไกในการใช้ประโยชน์จากนามธรรม และพารามิเตอร์เชื่อมโยงองค์ประกอบสำคัญของตัวอย่างเข้ากับนามธรรม ในขณะที่ generalization ถูกขับเคลื่อนเพียงโดยตัวอย่าง ความจำเป็นในการกำหนด interface ทำให้การสร้าง abstraction เป็นกระบวนการที่ต้องตัดสินใจกำหนดว่าจะละรายละเอียดใด ตัวอย่างเช่น เราสามารถยกระดับการสรุปของเรื่องราว “How protagonists overcome a challenge” ให้เป็นนามธรรมเรื่องราวโดยให้ชื่อว่า Story และกำหนดพารามิเตอร์ protagonist และ challenge:
Story(protagonist, challenge) = How protagonist(s) solve(s) the problem of challenge
เช่นเดียวกับพารามิเตอร์ของอัลกอริทึม พารามิเตอร์ของนามธรรม Story ถูกใช้ในคำอธิบายเป็นตำแหน่งที่ว่าง (placeholders) เพื่อแทนด้วยอาร์กิวเมนต์จริงที่ Story จะถูกใช้กับมัน (การใส่รูปแบบเอกพจน์/พหูพจน์ใน protagonist(s) และ solve(s) ใช้เพื่อให้คำอธิบายเข้ากับทั้งตัวเอกเดี่ยวและหลายตัว และการแทนคำว่า “overcome a” ด้วย “solve(s) the problem of” ทำให้ตัวอย่างต่อไปอ่านได้ง่ายขึ้น.)
ในเรื่อง Hansel and Gretel ตัวเอกคือ Hansel และ Gretel และความท้าทายคือการหาทางกลับบ้าน เราสามารถแสดงความจริงนี้โดยการประยุกต์ใช้นามธรรม Story กับค่าที่ตรงกับพารามิเตอร์:
Story(Hansel and Gretel, finding their way home)
การประยุกต์นี้หมายถึงเรื่องราวของตัวเอกสองคน Hansel และ Gretel ซึ่งแก้ปัญหาในการหาทางกลับบ้าน
เป็นประโยชน์ที่จะไตร่ตรองสิ่งที่ได้ทำไป สมมติว่าคุณต้องการอธิบายใจความของเรื่อง Hansel and Gretel ให้ใครสักคนอย่างรวดเร็ว คุณสามารถเริ่มโดยบอกว่าเป็นเรื่องราว กล่าวคือโดยการอ้างอิงถึงนามธรรม Story วิธีนี้ใช้ได้ก็ต่อเมื่ออีกฝ่ายรู้ว่า "เรื่องราว" หมายถึงอะไร กล่าวคือเมื่อเข้าใจนามธรรม Story ในกรณีนั้น การอ้างถึงนามธรรมจะกระตุ้นให้ผู้อื่นนึกถึงคำอธิบายของสิ่งที่เป็นเรื่องราว จากนั้นคุณเติมรายละเอียดเพื่อกรอกบทบาทที่พารามิเตอร์ protagonist และ challenge แทนที่ ซึ่งจะเปลี่ยนคำอธิบายทั่วไปของเรื่องให้เป็นคำอธิบายที่เฉพาะเจาะจงมากขึ้น
ในเชิงเทคนิค การประยุกต์ใช้นามธรรม Story นำไปสู่การแทนที่ชื่อของนามธรรมด้วยคำนิยามของมันและการแทนค่าของ "Hansel and Gretel" และ "finding their way home" ให้กับพารามิเตอร์ทั้งสองในคำนิยาม (ดู chapter 2) การแทนค่านี้นำไปสู่ตัวอย่างต่อไปนี้:
How Hansel and Gretel solve(s) the problem of finding their way home
ความสัมพันธ์ระหว่างตัวอย่างและนามธรรมถูกแสดงใน [figure 15.1]
เมื่อเราให้สรุปสำหรับเรื่อง Hansel and Gretel ในรูปของนามธรรม Story แล้ว เราอาจอยากอ้างถึงมันให้สั้นลงโดยตั้งชื่อให้ ในกรณีนี้ ชื่อเรื่องบังเอิญเหมือนกับชื่อตัวเอก:
Hansel and Gretel = Story(Hansel and Gretel, finding their way home)
สมการนี้บอกว่า Hansel and Gretel คือเรื่องของ Hansel and Gretel ที่แก้ปัญหาในการหาทางกลับบ้าน การที่ชื่อเรื่องและชื่อตัวเอกตรงกันเป็นเพียงความบังเอิญ แม้ในความเป็นจริงจะเกิดขึ้นค่อนข้างบ่อย ต่อไปคือตัวอย่างที่ไม่เกิดเหตุการณ์เช่นนี้:
Groundhog Day = Story(Phil Connors, escaping an endlessly repeating day)
Figure 15.1 นิยามและการใช้ของนามธรรม: การนิยามนามธรรมกำหนดชื่อให้และระบุพารามิเตอร์ที่คำนิยามอ้างอิง ชื่อและพารามิเตอร์คือ interface ของนามธรรม ซึ่งกำหนดวิธีการใช้: ผ่านชื่อและการส่งอาร์กิวเมนต์ให้พารามิเตอร์ การใช้งานเช่นนี้สร้างตัวอย่างของนามธรรม ซึ่งได้มาจากการแทนที่อาร์กิวเมนต์ในตำแหน่งพารามิเตอร์ตามคำนิยามของนามธรรม。
ในเรื่อง Hansel and Gretel การหาทางกลับบ้านไม่ใช่ความท้าทายเพียงอย่างเดียว อีกส่วนที่โดดเด่นของเรื่องคือพวกเขาต้องหนีแม่มดที่พยายามจะกินพวกเขา ดังนั้นเรื่องสามารถถูกอธิบายในลักษณะดังต่อไปนี้:
Story(Hansel and Gretel, escaping the witch)
คำอธิบายนี้ใช้พลวัตเดียวกันของนามธรรม Story โดยเปลี่ยนเพียงอาร์กิวเมนต์ของพารามิเตอร์ตัวที่สอง ข้อเท็จจริงนี้ยกคำถามหลายประการเกี่ยวกับนามธรรม ประการแรก เราจะจัดการความกำกวม (ambiguity) ในนามธรรมอย่างไร? เนื่องจากเรื่อง Hansel and Gretel สามารถมองได้ว่าเป็นตัวอย่างของนามธรรม Story ได้หลายวิธี และทั้งสองตัวอย่างที่แสดงให้เห็นก็ให้ข้อมูลที่ถูกต้องเกี่ยวกับเรื่องนั้น ไม่อาจกล่าวได้ว่าตัวอย่างใดตัวอย่างหนึ่งถูกต้องกว่าตัวอื่น นั่นหมายความว่าการนิยามของนามธรรมมีข้อบกพร่องหรือไม่? ประการที่สอง นามธรรม Story ไม่ได้เพียงแค่ abstract จากรายละเอียดของความท้าทายเฉพาะเท่านั้น แต่มันยัง focus ที่ความท้าทายหนึ่งโดยเฉพาะ (อย่างน้อยสำหรับเรื่องที่มีหลายความท้าทาย) ตัวอย่างเช่น การอธิบาย Hansel and Gretel ด้วยนามธรรม Story ทำให้ความท้าทายอย่างน้อยหนึ่งข้อไม่ได้ถูกกล่าวถึง ซึ่งทำให้เกิดคำถามว่าเราสามารถนิยามนามธรรม Story ให้รองรับความท้าทายหลายข้อในเรื่องเดียวได้หรือไม่ เรื่องนี้ไม่ยาก แต่คำถามคือระดับรายละเอียดใดที่เหมาะสมสำหรับนามธรรมเช่นนี้?
รู้ว่าเมื่อไหร่ (Say When)
เมื่อใดนามธรรม (abstraction) จะเป็นทั่วไปพอที่จะครอบคลุมตัวอย่างได้เพียงพอ? เมื่อใดมันจะละรายละเอียดมากเกินไปจนขาดความแม่นยำ? ทุกครั้งที่เราสร้างนามธรรม เราต้องตัดสินใจว่ามันควรทั่วไปแค่ไหนและควรให้รายละเอียดเท่าใด ตัวอย่างเช่น เราอาจใช้คำอธิบายว่า “sequence of events” แทนนามธรรม Story เพื่อบรรยายเรื่องราวในหนังสือเล่มนี้ ซึ่งจะเป็นจริงแต่จะละบางแง่มุมที่สำคัญและทำให้ความแม่นยำน้อยลง ในทางกลับกัน เราอาจใช้สิ่งที่เฉพาะกว่านั้น เช่น “fairy tale” หรือ “comedy” ถึงแม้สิ่งเหล่านี้จะให้รายละเอียดมากกว่านามธรรม Story แต่ก็ไม่ทั่วไปพอที่จะครอบคลุมทุกเรื่อง แท้จริงแล้วแม้แต่ Story ที่ค่อนข้างทั่วไปก็ยังไม่ทั่วพอสำหรับเรื่องที่ตัวเอกไม่สามารถแก้ปัญหาได้ เราอาจแก้ข้อบกพร่องนี้โดยเพิ่มพารามิเตอร์อีกตัวที่สามารถแทนด้วย “solve” หรือ “don’t solve” ขึ้นอยู่กับสถานการณ์ การขยายความทั่วไปของ Story ในลักษณะนี้เป็นความคิดที่ดีหรือไม่ขึ้นอยู่กับบริบทการใช้งานของนามธรรม หากกรณี “don’t solve” ไม่เกิดขึ้นเลย ความทั่วไปเพิ่มเติมก็ไม่จำเป็น และนิยามที่เรียบง่ายกว่าเดิมจะเหมาะกว่า อย่างไรก็ตาม บริบทการใช้งานของนามธรรมอาจเปลี่ยนไปได้เสมอ ดังนั้นจึงไม่มีทางแน่ใจได้อย่างเด็ดขาดเกี่ยวกับระดับความทั่วไปที่เลือก
นอกจากการหา "ระดับความทั่วไป" ที่เหมาะสมแล้ว ปัญหาอีกประการหนึ่งในการนิยามนามธรรมคือการตัดสินใจว่าจะให้รายละเอียดมากน้อยเพียงไรและจะใช้พารามิเตอร์กี่ตัว ตัวอย่างเช่น เราอาจเพิ่มพารามิเตอร์ให้กับนามธรรม Story ที่สะท้อนว่าความท้าทายถูกเอาชนะอย่างไร ในด้านหนึ่ง การเพิ่มพารามิเตอร์ทำให้นามธรรมมีความสามารถในการแสดงความแตกต่างระหว่างตัวอย่างต่าง ๆ ได้ละเอียดขึ้น แต่ในทางกลับกันมันก็ทำให้ interface ของนามธรรมซับซ้อนขึ้นและต้องใช้อาร์กิวเมนต์มากขึ้นเมื่อมีการใช้งาน Interface ที่ซับซ้อนขึ้นไม่เพียงแต่ทำให้นามธรรมยากต่อการใช้เท่านั้น แต่ยังทำให้การประยุกต์ใช้นามธรรมยากต่อการเข้าใจ เพราะต้องแทนที่พารามิเตอร์ด้วยอาร์กิวเมนต์หลายตำแหน่ง ซึ่งขัดแย้งกับเหตุผลสำคัญอย่างหนึ่งของการใช้ abstraction คือการให้ข้อสรุปที่กระชับและเข้าใจง่าย。
การถ่วงดุลความซับซ้อนของ interface และความแม่นยำของนามธรรมเป็นหนึ่งในปัญหาหลักของวิศวกรรมซอฟต์แวร์ เราสามารถอธิบายความทุกข์ของโปรแกรมเมอร์ได้ผ่านตัวอย่างของนามธรรม Story:
Software Engineering = Story(Programmers, finding the right level of abstraction)
แน่นอนว่ามีความท้าทายอื่น ๆ อีกมากมายสำหรับโปรแกรมเมอร์ และบางข้อก็สามารถสรุปได้อย่างเรียบร้อยโดยใช้นามธรรม Story นี่คือตัวอย่างปัญหาอีกเรื่องที่โปรแกรมเมอร์ทุกคนสามารถเข้าอกเข้าใจ:
Correct Software = Story(Programmers, finding and eliminating bugs)
การหาระดับนามธรรมที่เหมาะสมเป็นปัญหาสำหรับนามธรรม Story ด้วย มีสองวิธีต่างกันในการนิยาม Hansel and Gretel ให้เป็นตัวอย่างของนามธรรม Story การเลือกตัวอย่างหนึ่งที่มุ่งเน้นความท้าทายข้อเดียวย่อมหมายถึงการละรายละเอียดของอีกข้อหนึ่ง แต่ถ้าเราต้องการใช้ทั้งสองตัวอย่างเพื่อให้ภาพรวมเรื่อง Hansel and Gretel ที่ครอบคลุมขึ้น เราจะทำได้อย่างไร? มีหลายวิธี หนึ่งคือการกล่าวทั้งสองตัวอย่างเคียงข้างกัน:
Story(Hansel and Gretel, finding their way home) and
Story(Hansel and Gretel, escaping the witch)
วิธีนี้ดูค่อนข้างเกะกะ โดยเฉพาะการกล่าวซ้ำของชื่อตัวเอกและนามธรรม Story ดูเหมือนจะซ้ำซ้อน เมื่อเราทำการแทนค่าแล้ว จะได้ตัวอย่างดังนี้:
How Hansel and Gretel solve(s) the problem of finding their way home, and how Hansel and Gretel solve(s) the problem of escaping the witch
อีกทางเลือกคือรวมทั้งสองความท้าทายเป็นอาร์กิวเมนต์เดียวสำหรับพารามิเตอร์ challenge:
Story(Hansel and Gretel, finding their way home and escaping the witch)
วิธีนี้ใช้งานได้ค่อนข้างดี คุณอาจสังเกตได้ว่าทำแบบเดียวกันกับตัวเอกด้วย: Hansel and Gretel ถูกจัดกลุ่มและแทนที่เป็นหน่วยข้อความเดียวสำหรับพารามิเตอร์ protagonist แต่เรายังเห็นว่าความยืดหยุ่นในการใช้ตัวเอกเดี่ยวหรือหลายตัวไม่ได้มาฟรี ในนิยามของนามธรรม Story การใช้ protagonist(s) และ solve(s) ต้องทำงานได้ทางไวยากรณ์ทั้งกับประธานเอกพจน์และพหูพจน์ (เพื่อรองรับความท้าทายหลายข้อ ต้องทำเช่นเดียวกันกับ problem(s)) จะดีถ้านามธรรม Story สามารถสร้างตัวอย่างที่ถูกต้องตามไวยากรณ์แยกกันสำหรับแต่ละกรณีได้
สิ่งนี้สามารถทำได้โดยการนิยามนามธรรม Story ให้พารามิเตอร์ตัวแรกเป็นรายการของตัวเอก แล้วให้คำนิยามสองแบบที่แตกต่างกันเล็กน้อย ขึ้นอยู่กับว่าพารามิเตอร์เป็นตัวเอกเดี่ยวหรือรายการของสองคน:
Story(protagonist, challenge) = How protagonist solves the problem of challenge
Story(protagonist_1→_protagonist_2, _challenge) = How protagonist_1 and _protagonist_2 solve the problem of _challenge
เมื่อ Story ถูกประยุกต์กับตัวเอกเดี่ยว เช่น Phil Connors นิยามแรกที่ใช้กริยาเอกพจน์จะถูกเลือก แต่เมื่อ Story ถูกประยุกต์กับรายการของตัวเอกสองคน เช่น Hansel→Gretel นิยามที่สองที่ใช้กริยาพหูพจน์จะถูกเลือก ในกรณีนั้น นิยามที่สองจะแยกรายการออกเป็นสององค์ประกอบและใส่ and ระหว่างพวกมัน
ดูเหมือนว่านามธรรม Story จะให้วิธีในการสร้างประโยคภาษาอังกฤษ ใน chapter 8 ข้าพเจ้าได้แสดงตัวอย่างไวยากรณ์เป็นกลไกในการทำเช่นนั้น ดังนั้นเราไม่อาจนิยามไวยากรณ์สำหรับบทสรุปเรื่องราวได้หรือ? ได้ นี่คือไวยากรณ์ที่เป็นไปได้ตามคำนิยามล่าสุดของ Story. นอกเหนือจากความแตกต่างเชิงสัญลักษณ์เล็กน้อย เช่น การใช้ลูกศรแทนเครื่องหมายเท่ากับหรือการใช้กรอบจุดแทนเส้นประเพื่อทำเครื่องหมาย nonterminals แทนที่จะใช้เส้นประเพื่อทำเครื่องหมายพารามิเตอร์ กลไกทั้งสองพื้นฐานแล้วทำงานในลักษณะเดียวกันโดยการแทนค่าหรือ terminals สำหรับพารามิเตอร์หรือ nonterminals
| story | → | How protagonist solves the problem of challenge |
| story | → | How protagonists solve the problem of challenge |
| protagonists | → | protagonist and protagonist |
Table 8.1 ใน chapter 8 เปรียบเทียบ grammars, equations, และ algorithms แสดงบทบาทร่วมของส่วนประกอบของรูปแบบต่าง ๆ และเน้นว่าการใช้ grammars สมการ และอัลกอริทึมเป็นกลไกที่ต่างกันแต่มีความคล้ายคลึงกันในการอธิบายนามธรรม。
การอภิปรายก่อนหน้านี้แสดงให้เห็นว่าการออกแบบนามธรรมไม่ใช่งานที่ตรงไปตรงมา เมื่อเผชิญกรณีการใช้งานใหม่ อาจพบข้อกำหนดที่เปลี่ยนแปลงซึ่งบังคับให้ต้องเปลี่ยนคำนิยามของนามธรรม การเปลี่ยนแปลงดังกล่าวอาจนำไปสู่นามธรรมที่ทั่วไปขึ้นหรือไปสู่นามธรรมที่เปิดเผยรายละเอียดต่างออกไป ในบางกรณี สิ่งนี้อาจทำให้ต้องเปลี่ยน interface เช่น เมื่อมีการเพิ่มพารามิเตอร์ใหม่หรือเมื่อชนิดของพารามิเตอร์ถูกเปลี่ยน ตัวอย่างเช่น การเปลี่ยนพารามิเตอร์ protagonist จากค่าทีละค่าหนึ่งไปเป็นรายการ เมื่อ interface ของนามธรรมเปลี่ยน การใช้งานนามธรรมที่มีอยู่ทั้งหมดต้องถูกปรับให้สอดคล้องกับ interface ใหม่ ซึ่งอาจเป็นงานมากและอาจมีผลกระทบเป็นลูกโซ่ต่อการเปลี่ยนแปลง interface อื่น ๆ ด้วย ดังนั้นวิศวกรซอฟต์แวร์จึงพยายามหลีกเลี่ยงการเปลี่ยน interface เมื่อเป็นไปได้ และมักถือเป็นทางเลือกสุดท้าย
การรันของนามธรรม (A Run of Abstractions)
ลองพิจารณานิยามสุดท้ายของ Story ที่ใช้รายการของตัวเอก แม้ว่าสมการจะใช้ได้เฉพาะกับรายการที่มีหนึ่งหรือสององค์ประกอบ นิยามดังกล่าวสามารถขยายอย่างง่ายดายให้ทำงานกับรายการที่มีจำนวนองค์ประกอบใด ๆ ได้โดยใช้ loops หรือ recursion ดังที่แสดงใน chapters 10 และ การใช้สมการแยกต่างหากเพื่อต่างกรณีและแนวคิดของการประมวลผลรายการชี้ว่า นามธรรม Story อาจแท้จริงเป็นอัลกอริทึมสำหรับสร้างคำอธิบายเรื่องสั้น ตามที่ปรากฏยังมีมากกว่าที่ตามองเห็น และต่อไปฉันจะอธิบายความสัมพันธ์ระหว่างอัลกอริทึมและนามธรรมอย่างละเอียดขึ้น
ด้วยความสำคัญของนามธรรมในวิทยาการคอมพิวเตอร์ ไม่ใช่เรื่องน่าแปลกใจที่หนึ่งในแนวคิดหลักของมันคืออัลกอริทึมเองก็เป็นตัวอย่างของนามธรรม อัลกอริทึมอธิบายความเหมือนกันของการคำนวณหลาย ๆ แบบ ไม่ว่าจะเป็นการตามลูกกรวดหรือการเรียงลำดับ (ดู figure 15.2) การดำเนินการของอัลกอริทึมด้วยอาร์กิวเมนต์ที่ต่างกันสำหรับพารามิเตอร์จะให้การคำนวณเฉพาะต่าง ๆ
นามธรรม Story ดูเหมือนเป็นการสรุปทีหลัง (post hoc generalization) คือคำอธิบายสรุปถูกสร้างหลังจากได้เห็นเรื่องราวหลายเรื่องแล้ว ซึ่งสิ่งนี้อาจเกิดขึ้นกับอัลกอริทึมด้วยได้เช่นกัน ตัวอย่างเช่น หลังจากที่คุณทำอาหารจานหนึ่งหลายครั้ง ปรับส่วนผสมและวิธีการเพื่อให้ผลลัพธ์ดีขึ้น คุณอาจตัดสินใจจดสูตรไว้เพื่อให้ประสบการณ์การทำอาหารนั้นทำซ้ำได้ อย่างไรก็ตาม ในกรณีอื่น ๆ มากมาย อัลกอริทึมเป็นคำตอบต่อปัญหาที่ยังไม่ได้ถูกแก้และถูกสร้างขึ้นก่อนที่การคำนวณใด ๆ จะถูกรัน นี่คือสิ่งที่ทำให้นามธรรมของอัลกอริทึมทรงพลัง นอกจากจะอธิบายการคำนวณที่เคยเกิดขึ้นแล้ว อัลกอริทึมยังสามารถสร้างการคำนวณใหม่ ๆ ได้ตามต้องการ อัลกอริทึมมีพลังในการแก้ปัญหาใหม่ ๆ ที่ยังไม่เคยพบ ในบริบทของนามธรรม Story ลองคิดถึงตัวเอกสุ่ม ๆ และปัญหาเฉพาะ แล้วคุณจะมีจุดเริ่มต้นของเรื่องใหม่
Figure 15.2 อัลกอริทึมเป็นนามธรรมจากการคำนวณแบบเฉพาะเจาะจงแต่ละกรณี อัลกอริทึมแต่ละตัวแปลง representations ชนิดหนึ่ง Type จะย่อจากการแทนค่าแต่ละชิ้น หาก Input เป็นชนิดของการแทนที่อัลกอริทึมรับ และ Output เป็นชนิดของการแทนที่มันผลิต แสดงว่าอัลกอริทึมมีชนิด Input → Output
ตัวอย่างอนาล็อกนี้ช่วยอธิบายประเด็นต่อไป ลองพิจารณาเครือข่ายถนนอย่างง่าย และสมมติว่ามีการสร้างถนนสองเส้นเชื่อมเมือง A กับ B และ C กับ D ตามลำดับ ปรากฏว่าเส้นทั้งสองตัดกันและมีสี่แยกขึ้น ทำให้การเชื่อมต่อแบบใหม่ ๆ เป็นไปได้ และเราสามารถเดินทางจาก A ไป C จาก B ไป D เป็นต้น เครือข่ายถนนเอื้อต่อการเดินทางไม่เพียงแค่การเดินทางที่สร้างถนนไว้สำหรับเท่านั้น แต่ยังเอื้อต่อการเดินทางอื่น ๆ ที่ไม่ได้คาดคิดด้วย
การสังเกตว่านามธรรมคืออัลกอริทึมสามารถเข้าใจได้สองแง่มุม ประการแรก การออกแบบและการใช้อัลกอริทึมได้รับประโยชน์ทั้งหมดจากนามธรรมแต่ก็แบกรับต้นทุนทั้งหมดด้วย โดยเฉพาะปัญหาในการหา "ระดับนามธรรม" ที่เหมาะสมเกี่ยวข้องกับการออกแบบอัลกอริทึม เพราะประสิทธิภาพของอัลกอริทึมมักขึ้นกับความทั่วไปของมัน ตัวอย่างเช่น mergesort ใช้เวลาแบบ linearithmic (n log n). Mergesort ใช้งานได้กับลิสต์ขององค์ประกอบใด ๆ และต้องการเพียงว่าองค์ประกอบสามารถถูกเปรียบเทียบกันได้ ดังนั้นมันเป็นวิธีการเรียงลำดับที่ทั่วไปที่สุดที่คิดได้และใช้ได้อย่างกว้างขวาง อย่างไรก็ตาม หากองค์ประกอบของลิสต์ที่ต้องเรียงมาจากโดเมนขนาดเล็ก ก็สามารถใช้ bucket sort ได้ (ดู chapter 6) ซึ่งทำงานได้เร็วกว่าในเวลาเชิงเส้น (linear time). ดังนั้นนอกเหนือจากการแลกเปลี่ยนระหว่างความทั่วไปและความแม่นยำ อัลกอริทึมยังมีการแลกเปลี่ยนระหว่างความทั่วไปและประสิทธิภาพ
ประการที่สองคือเราสามารถนำองค์ประกอบเชิงอัลกอริทึมมาใช้ในการออกแบบนามธรรมได้ นามธรรม Story เป็นตัวอย่างที่ดี จุดประสงค์หลักของมันคือการผลิตคำอธิบายเรื่องราว ไม่มีการคำนวณเฉพาะเจาะจงที่ตั้งใจจะเกิดขึ้น แต่เมื่อการออกแบบนามธรรมระบุแง่มุมสำคัญของเรื่องแต่ละเรื่องผ่านพารามิเตอร์ เราจะเห็นความจำเป็นในการจัดการรายการของตัวเอกและความท้าทายในวิธีที่ยืดหยุ่นกว่า โดยเฉพาะการแยกระหว่างรายการที่มีจำนวนองค์ประกอบต่างกันมีประโยชน์ในการสร้างคำอธิบายเรื่องที่เฉพาะเจาะจงมากขึ้น
เนื่องจากการรันอัลกอริทึมเทียบเท่ากับพฤติกรรมเชิงฟังก์ชัน อัลกอริทึมจึงถูกเรียกว่า functional abstractions แต่ไม่ใช่อัลกอริทึมเพียงอย่างเดียวที่เป็นตัวอย่างของ functional abstractions ใน Harry Potter เมนูเวทมนตร์ (spells) เป็นนามธรรมเชิงฟังก์ชันของเวทมนตร์ เมื่อร่ายโดยพ่อมด คาถาจะก่อให้เกิดผลทางเวทมนตร์ แต่ละครั้งที่ร่ายจะให้ผลต่างกันขึ้นกับผู้รับหรือวัตถุเป้าหมายและความชำนาญในการร่าย คล้ายกับอัลกอริทึมซึ่งแสดงออกในภาษาและสามารถรันได้โดยคอมพิวเตอร์ที่เข้าใจภาษานั้น คาถาก็แสดงออกในภาษาของเวทมนตร์ที่ประกอบด้วยคำร่าย ท่าทางไม้กายสิทธิ์ ฯลฯ และร่ายได้โดยพ่อมดที่ชำนาญเท่านั้น ตำรับยา (potions) เป็นนามธรรมอีกชนิดของเวทมนตร์ ต่างจากคาถาตรงที่การใช้ตัวยา/ตำรับง่ายกว่า ไม่จำเป็นต้องใช้พ่อมดเพื่อทำให้ตัวยาออกฤทธิ์ ใคร ๆ แม้แต่ muggles ก็ทำได้
หลายเครื่องจักรก็เป็น functional abstractions ด้วยเช่นกัน ตัวอย่างเช่น เครื่องคิดเลขขนาดพกพาเป็นนามธรรมของการดำเนินการคณิตศาสตร์ เช่นเดียวกับที่ตำรับยาขยายการเข้าถึงเวทมนตร์ให้คนที่ไม่ใช่พ่อมด เครื่องคิดเลขก็ขยายการเข้าถึงการคำนวณให้คนที่ไม่มีทักษะทางคณิตศาสตร์ที่จำเป็น นอกจากนี้ยังช่วยเร่งกระบวนการแม้สำหรับคนที่มีทักษะดังกล่าว ตัวอย่างอื่น ๆ ได้แก่ เครื่องชงกาแฟและนาฬิกาปลุก ซึ่งเป็นเครื่องจักรที่สามารถปรับแต่งให้ทำหน้าที่เฉพาะได้อย่างสม่ำเสมอ ประวัติศาสตร์ของยานพาหนะแสดงให้เห็นว่าเครื่องจักรช่วยเพิ่มประสิทธิภาพของวิธีที่ถูกนามธรรมไว้ (ในกรณีนี้คือการเดินทาง) และบางครั้งยังทำให้ interface ง่ายขึ้นเพื่อขยายการเข้าถึงให้คนจำนวนมากขึ้น รถม้าเคยต้องการม้าและค่อนข้างช้า รถยนต์เป็นการปรับปรุงครั้งใหญ่แต่ยังต้องการทักษะการขับขี่ การมีเกียร์อัตโนมัติ เข็มขัดนิรภัย ระบบนำทาง—ทั้งหมดช่วยให้การใช้รถยนต์เป็นวิธีการเดินทางเข้าถึงได้ง่ายขึ้นและปลอดภัยขึ้น เราคาดว่าจะเห็นการขยายการเข้าถึงมากขึ้นในปีต่อ ๆ ไปด้วยการมาของรถยนต์ขับเคลื่อนอัตโนมัติ
หนึ่งชนิดเหมาะกับทุกอย่าง (One Type Fits All)
อัลกอริทึมและเครื่องจักร (และคาถาและตำรับยา) เป็นตัวอย่างของ functional abstractions เพราะพวกมันห่อหุ้มฟังก์ชันการทำงานบางอย่าง การแทนที่เฉย ๆ ที่ถูกแปลงใน computations ก็เป็นเรื่องของนามธรรมที่เรียกว่า data abstraction ในความเป็นจริง แนวคิดของ representation เป็นนามธรรมโดยเนื้อแท้ เพราะมันระบุคุณสมบัติบางอย่างของสัญลักษณ์ให้ยืนแทนบางสิ่ง (ดู chapter 3) และในกระบวนการนี้มันก็ละเว้นคุณสมบัติอื่น ๆ
เมื่อ Hansel และ Gretel หาทางกลับบ้านโดยติดตามลูกกรวด ขนาดและสีของลูกกรวดไม่สำคัญ การใช้ลูกกรวดเป็นการแทนตำแหน่งเป็นนามธรรมที่ละทิ้งความแตกต่างในขนาดและสี และมุ่งไปที่คุณสมบัติที่สะท้อนแสงจันทร์ เมื่อเราพูดว่า Harry Potter เป็นพ่อมด เรากำลังเน้นว่าคุณสมบัติที่เขามีคือการใช้เวทมนตร์ ในทางตรงกันข้าม เราไม่ได้สนใจอายุของเขาหรือการใส่แว่นตาของเขาหรือข้อมูลอื่น ๆ โดยเรียก Harry Potter ว่า "พ่อมด" เราได้ย่อรายละเอียดเหล่านั้นเช่นเดียวกันกับการเรียก Sherlock Holmes ว่า detective หรือ Doc Brown ว่า scientist เราเน้นคุณสมบัติที่เกี่ยวข้องกับคำพวกนี้และชั่วคราวละเว้นข้อมูลอื่น ๆ เกี่ยวกับบุคคล
คำศัพท์เช่น wizard, detective, และ scientist เป็นชนิด (types) แน่นอน พวกมันบ่งชี้คุณลักษณะที่โดยทั่วไปถือว่าเป็นจริงของสมาชิกของชนิดนั้น ๆ ความหมายของ protagonist และ challenge ในนามธรรม Story ก็เป็นชนิดเช่นกัน เพราะพวกมันเรียกภาพที่จำเป็นสำหรับนามธรรม Story ที่จะสื่อความหมาย ดูเหมือนว่า protagonist เป็นชนิดที่ทั่วไปกว่าตัวอย่างเช่น wizard หรือ detective เพราะมันให้รายละเอียดน้อยกว่า และความจริงที่ว่าสองคำหลังสามารถแทนที่คำแรกได้รองรับมุมมองนี้ อย่างไรก็ตาม นี่เป็นเพียงส่วนหนึ่งของเรื่อง นำ Lord Voldemort มาเป็นตัวอย่าง เขาเป็น wizard แต่ไม่ใช่ protagonist แต่เป็น antagonist ในเรื่อง Harry Potter เพราะทั้ง Harry Potter (protagonist) และ Voldemort (antagonist) เป็น wizard จึงดูเหมือนว่า wizard เป็นชนิดที่ทั่วไปกว่าเพราะมันละรายละเอียดบางอย่างที่ทำให้เกิดการแตกต่างระหว่าง protagonist และ antagonist ดังนั้นจึงไม่สามารถพูดได้ว่า protagonist หรือ wizard อะไรที่เป็นนามธรรมมากกว่าโดยทั่วไป ซึ่งไม่แปลกใจนักเพราะชนิดเหล่านี้มาจากโดเมนต่างกันคือ เรื่องราวและเวทมนตร์
ในโดเมนเดียวกัน ชนิดมักจะถูกจัดเรียงอย่างชัดเจนโดยวางพวกมันลงในลำดับชั้น ตัวอย่างเช่น Harry Potter, Draco Malfoy, และ Severus Snape ล้วนเป็นสมาชิกของ Hogwarts แต่เฉพาะ Harry และ Draco เท่านั้นที่เป็นนักเรียนที่ Hogwarts ถ้าคุณเป็นนักเรียนที่ Hogwarts คุณก็เป็นสมาชิกของ Hogwarts ซึ่งหมายความว่าชนิด member of Hogwarts เป็นนามธรรมที่ทั่วไปกว่าชนิด student at Hogwarts ยิ่งไปกว่านั้น เนื่องจาก Harry แต่ไม่ใช่ Draco เป็นสมาชิกของบ้าน Gryffindor ชนิด student at Hogwarts จึงทั่วไปกว่าชนิด student in the house of Gryffindor ในลักษณะเดียวกัน magic เป็นนามธรรมที่ทั่วไปกว่า spell ซึ่ง wiederum ทั่วไปกว่า teleportation spell หรือ patronus charm
ชนิดที่พบในภาษาการเขียนโปรแกรมน่าจะเป็นรูปแบบของ data abstraction ที่ชัดเจนที่สุด เลข 2 และ 6 เเตกต่างกัน แต่พวกมันมีหลายสิ่งเหมือนกัน เราสามารถหารพวกมันด้วย 2 เราสามารถนำมันไปรวมกับตัวเลขอื่น ๆ เป็นต้น ดังนั้นเราจึงสามารถมองข้ามความแตกต่างของพวกมันและจัดกลุ่มพวกมันเข้าด้วยกันในชนิด Number ชนิดนี้ย่อจากคุณสมบัติของเลขแต่ละตัวและเผยให้เห็นความเหมือนกันระหว่างสมาชิกทั้งหมด โดยเฉพาะชนิดสามารถใช้เพื่ออธิบายพารามิเตอร์ในอัลกอริทึม ซึ่งสามารถถูกนำมาใช้ตรวจสอบความสอดคล้องของอัลกอริทึมกับ type checker (ดู chapter 14) ดังนั้น data abstraction ไปคู่กับ functional abstraction: อัลกอริทึมย่อจากค่ารายตัวโดยการใช้พารามิเตอร์ อย่างไรก็ตาม ในหลายกรณีพารามิเตอร์ไม่สามารถแทนที่ด้วยค่าอะไรก็ได้แต่ต้องเป็นอาร์กิวเมนต์ที่เป็น representations ที่อัลกอริทึมสามารถจัดการได้ ตัวอย่างเช่นพารามิเตอร์ที่จะถูกคูณด้วย 2 ต้องเป็น number ซึ่งเป็นที่ที่ชนิดในฐานะ data abstraction เข้ามาเล่นบทบาท ชนิด Number ยังสามารถถูกมองว่าเป็นนามธรรมที่ทั่วไปกว่าชนิดตัวเลขที่เฉพาะเจาะจงมากกว่า เช่นชนิดของเลขคู่
สุดท้าย นอกเหนือจากชนิด (plain types) เช่น Number แล้ว data abstraction ยังใช้กับ data types โดยเฉพาะ (ดู chapter 4) data type ถูกกำหนดเพียงโดยการดำเนินการที่มันเสนอและคุณสมบัติของการดำเนินการเหล่านั้น รายละเอียดของการแทนค่าไม่ได้ถูกเปิดเผย นั่นคือ data type เป็นนามธรรมที่ทั่วไปกว่าข้อมูลโครงสร้างที่ใช้ในการดำเนินการ เช่น stack สามารถถูก implement ด้วย list หรือ array แต่รายละเอียดของโครงสร้างเหล่านั้นและความแตกต่างระหว่างพวกมันจะไม่ปรากฏเมื่อใช้ stack
นามธรรมข้อมูลที่ถูกเลือกอย่างดีจะเน้นคุณสมบัติของการแทนค่าที่สนับสนุนการคำนวณกับมัน นอกจากนี้ นามธรรมเช่นนี้ยังละเว้นและซ่อนคุณสมบัติที่อาจรบกวนการคำนวณ
เวลาในการย่อ (Time to Abstract)
ตามที่อธิบายใน chapter 2 เวลาในการรันของอัลกอริทึมไม่ได้ถูกรายงานในลักษณะเดียวกับที่ fitness tracker รายงานเวลาในการวิ่งหกไมล์ล่าสุดของคุณ การรายงานเวลาเป็นวินาที (หรือเป็นนาทีหรือชั่วโมง) จะไม่ใช่ข้อมูลที่มีประโยชน์นักเพราะมันขึ้นกับคอมพิวเตอร์เฉพาะ เมื่ออัลกอริทึมเดียวกันถูกรันบนคอมพิวเตอร์ที่เร็วหรือช้ากว่า เวลาในการรันของอัลกอริทึมเดียวกันก็จะแตกต่างกัน การเปรียบเทียบเวลาของคุณสำหรับการวิ่งหกไมล์กับเพื่อนมีความหมาย เพราะให้ข้อมูลเกี่ยวกับประสิทธิภาพสัมพัทธ์ของสองคอมพิวเตอร์ นั่นคือ ผู้วิ่ง แต่เวลาไม่ได้บอกอะไรที่มีความหมายเกี่ยวกับประสิทธิภาพของอัลกอริทึมการวิ่งเอง เพราะทั้งคุณและเพื่อนกำลังรันอัลกอริทึมเดียวกัน
ดังนั้นจึงเป็นความคิดที่ดีที่จะย่อจากเวลาเฉพาะและวัดความซับซ้อนของอัลกอริทึมเป็นจำนวนของขั้นตอนที่ต้องใช้ มาตรวัดดังกล่าวเป็นอิสระจากความเร็วของคอมพิวเตอร์และไม่ได้รับผลกระทบจากการพัฒนาเทคโนโลยี สมมติว่าก้าวขาของคุณขณะวิ่งค่อนข้างคงที่ ดังนั้นคุณจะใช้ประมาณจำนวนก้าวเท่าเดิมสำหรับการวิ่งหกไมล์ไม่ว่าเงื่อนไขจะเป็นอย่างไร การใช้จำนวนก้าวของก้าวที่คงที่ย่อจากลักษณะเฉพาะของผู้วิ่งและจึงให้การอธิบายการวิ่งที่เสถียรกว่า ในความจริง การบอกจำนวนก้าวก็เป็นวิธีหนึ่งในการบอกว่าการวิ่งนั้นยาวหกไมล์ ความยาวของการวิ่งคือมาตรวัดที่ดีกว่าสำหรับความซับซ้อนของมันมากกว่าระยะเวลา เพราะมันย่อจากความเร็วที่ต่างกันของผู้วิ่งต่างคนหรือแม้แต่ของผู้วิ่งคนเดียวในเวลาที่ต่างกัน
อย่างไรก็ตาม จำนวนก้าวหรือจำนวนปฏิบัติการ แม้จะย่อจากเวลาแล้ว แต่ก็ยังเป็นมาตรวัดที่ค่อนข้างเฉพาะเจาะจงสำหรับความซับซ้อนของอัลกอริทึมเพราะจำนวนนี้เปลี่ยนแปลงตามอินพุตของอัลกอริทึม ตัวอย่างเช่น ยิ่งลิสต์ยาวเท่าใด ก็ยิ่งใช้เวลามากขึ้นในการหาค่าน้อยสุดหรือเรียงลำดับ เช่นเดียวกัน การวิ่งหกไมล์ต้องใช้ก้าวมากกว่าการวิ่งห้าทไมล์ จำไว้ว่าเป้าหมายคือการอธิบายความซับซ้อนของอัลกอริทึมโดยทั่วไป ไม่ใช่ประสิทธิภาพสำหรับอินพุตเฉพาะ ดังนั้นจึงไม่ชัดเจนว่าเราควรรายงานจำนวนก้าวสำหรับอินพุตใด เราอาจจินตนาการสร้างตารางแสดงจำนวนก้าวสำหรับกรณีตัวอย่างหลายกรณี แต่ก็ไม่ชัดเจนว่าจะเลือกตัวอย่างใด
ดังนั้น การย่อเวลาสำหรับอัลกอริทึมจึงก้าวไปอีกขั้นและละเลยจำนวนก้าวที่แท้จริง แทนที่จะรายงานจำนวนก้าวจริง เรารายงานว่าจำนวนก้าวเติบโตอย่างไรเมื่ออินพุตใหญ่ขึ้น ตัวอย่างเช่น ถ้าอัลกอริทึมต้องการจำนวนก้าวสองเท่าถ้าไซส์ของอินพุตเพิ่มเป็นสองเท่า แสดงว่ามันเติบโตในอัตราเดียวกัน ตามที่อธิบายใน chapter 2 พฤติกรรมการรันเช่นนี้เรียกว่า linear นี่คือสิ่งที่เกิดขึ้นกับการหาค่าน้อยสุดของลิสต์หรือการวิ่ง แม้ว่าเวลาในการรันจะเติบโตตามปัจจัยมากกว่า 2 ความซับซ้อนของอัลกอริทึมยังถือว่าเป็นเชิงเส้นเพราะความสัมพันธ์ระหว่างขนาดอินพุตและจำนวนก้าวแสดงโดยการคูณด้วยค่าคงที่ ซึ่งเป็นกรณีสำหรับจำนวนก้าวที่ Hansel และ Gretel ต้องใช้ในการหาทางกลับบ้าน เวลาในการรันของอัลกอริทึมเชิงเส้นยังย่อจากปัจจัยนี้ด้วย ดังนั้นอัลกอริทึมของ Hansel และ Gretel ยังคงถูกพิจารณาว่าเป็นเชิงเส้น
ประโยชน์สำคัญสองประการของการย่อเวลาคือความสามารถในการบอกว่าโจทย์ใดแก้ได้จริง (tractable) และการเลือกอัลกอริทึมที่เหมาะสมสำหรับปัญหาเฉพาะ เช่น อัลกอริทึมที่มีเวลาแบบ exponential ทำงานได้เฉพาะกับอินพุตขนาดเล็กมาก และปัญหาที่รู้จักเฉพาะอัลกอริทึมที่มีเวลาแบบ exponential เท่านั้นจึงถือว่าเป็นปัญหาที่ยากแก้ (intractable) (ดู chapter 7) ในทางกลับกัน ถ้าเรามีอัลกอริทึมหลายตัวสำหรับแก้ปัญหาเดียวกัน เราควรเลือกอันที่มีความซับซ้อนเวลาเหมาะสมกว่า ยกตัวอย่างเช่น เรามักจะเลือก mergesort ซึ่งเป็นแบบ linearithmic แทน insertion sort ที่เป็น quadratic (ดู chapter 6) Figure 15.3 สรุปการย่อเวลา
Figure 15.3 การย่อเวลา (Time abstraction): เพื่อย่อจากความเร็วที่ต่างกันของคอมพิวเตอร์ เราใช้จำนวนขั้นตอนที่อัลกอริทึมต้องใช้ในระหว่างการรันเป็นมาตรวัดเวลาในการรันของมัน เพื่อย่อจากจำนวนขั้นตอนที่ต่างกันสำหรับอินพุตต่าง ๆ เราวัดเวลาในการรันของอัลกอริทึมในแง่ของอัตราการเติบโตเมื่ออินพุตเพิ่มขึ้น.
ภาษาในเครื่อง (The Language in the Machine)
อัลกอริทึมไม่สามารถผลิตการคำนวณได้ด้วยตัวเอง ตามที่อธิบายใน chapter 2 อัลกอริทึมต้องถูกรันโดยคอมพิวเตอร์ที่เข้าใจภาษาที่อัลกอริทึมเขียนขึ้น คำสั่งใด ๆ ที่ใช้ในอัลกอริทึมต้องอยู่ในชุดคำสั่งที่คอมพิวเตอร์นั้นสามารถจัดการได้
การผูกอัลกอริทึมเข้ากับคอมพิวเตอร์เฉพาะผ่านภาษาเป็นปัญหาด้วยหลายเหตุผล ประการแรก คอมพิวเตอร์ที่ออกแบบโดยอิสระจากกันมักจะเข้าใจภาษาที่ต่างกัน ซึ่งหมายความว่าอัลกอริทึมที่เขียนด้วยภาษาหนึ่งที่คอมพิวเตอร์หนึ่งเข้าใจและรันได้ อาจไม่ถูกเข้าใจหรือรันได้โดยคอมพิวเตอร์อีกเครื่อง ตัวอย่างเช่น ถ้า Hansel หรือ Gretel เขียนอัลกอริทึมการหาทางกลับบ้านด้วยภาษาเยอรมัน เด็กที่เติบโตในฝรั่งเศสหรืออังกฤษคงไม่สามารถรันมันได้โดยไม่ได้เรียนภาษาเยอรมัน ประการที่สอง ภาษาโปรแกรมของคอมพิวเตอร์เองก็เปลี่ยนแปลงตามกาลเวลา ซึ่งอาจไม่เป็นปัญหาสำหรับมนุษย์ที่ยังเข้าใจรูปแบบภาษาเก่า ๆ ได้ แต่เป็นปัญหาสำหรับเครื่องซึ่งอาจไม่สามารถรันอัลกอริทึมได้เลยถ้าคำสั่งใดคำสั่งหนึ่งถูกเปลี่ยนเล็กน้อย ความผูกมัดที่เปราะบางระหว่างภาษา อัลกอริทึม และคอมพิวเตอร์ดูเหมือนจะทำให้การแบ่งปันอัลกอริทึมเป็นเรื่องยาก โชคดีที่ซอฟต์แวร์ไม่จำเป็นต้องถูกเขียนใหม่ทุกครั้งที่มีคอมพิวเตอร์ใหม่สองรูปแบบเข้ามาในตลาด สองรูปแบบของนามธรรมที่ทำให้เป็นไปได้คือ language translation และ abstract machines.
เพื่ออธิบายแนวคิดของ abstract machine ให้พิจารณาอัลกอริทึมสำหรับการขับรถ คุณอาจเรียนรู้การขับรถจากรถคันหนึ่ง แต่ยังสามารถขับรถหลายรุ่นได้ ทักษะการขับที่ได้มาไม่ผูกติดกับยี่ห้อหรือรุ่นเฉพาะ แต่ย่อเป็นแนวคิดเช่นพวงมาลัย คันเร่ง และเบรก แบบจำลองรถยนต์นามธรรมถูกทำให้เป็นจริงโดยรถที่แตกต่างกันที่มีรายละเอียดต่างกันแต่ให้การเข้าถึงฟังก์ชันเดียวกันด้วยภาษาทั่วไปของการขับรถ
นามธรรมใช้กับเครื่องจักรทุกชนิด ตัวอย่างเช่น เราสามารถย่อจากรายละเอียดของเครื่องชงกาแฟ French press หรือ espresso โดยบอกว่าเครื่องชงกาแฟต้องมีความสามารถในการผสมน้ำร้อนกับผงกาแฟเป็นระยะเวลา แล้วแยกอนุภาคออกจากของเหลว อัลกอริทึมการชงกาแฟสามารถอธิบายในแง่นามธรรมนี้ ซึ่งยังคงเพียงพอที่จะนำไปปฏิบัติกับเครื่องชงกาแฟต่าง ๆ ได้ แน่นอนว่านามธรรมของเครื่องมีขีดจำกัด เราไม่สามารถใช้เครื่องชงกาแฟเพื่อรันอัลกอริทึมการขับรถ และเราไม่สามารถใช้อะไรบางอย่างในการชงกาแฟด้วยรถยนต์ แต่ abstract machines เป็นวิธีสำคัญในการลดความผูกติดของภาษาเข้ากับสถาปัตยกรรมคอมพิวเตอร์เฉพาะ (ดู figure 15.4)
เครื่องนามธรรมที่มีชื่อเสียงที่สุดสำหรับการคำนวณคือ Turing machine ซึ่งตั้งชื่อตามนักคณิตศาสตร์ชาวอังกฤษและผู้บุกเบิกวิทยาการคอมพิวเตอร์ Alan Turing ผู้คิดค้นมันในปี 1936 และใช้เพื่อทำให้แนวคิดของการคำนวณและอัลกอริทึมมีความเป็นทางการ Turing machine ประกอบด้วยเทปที่ถูกแบ่งเป็นช่อง แต่ละช่องมีสัญลักษณ์ เทปถูกเข้าถึงผ่านหัวอ่าน/เขียนที่ยังสามารถเคลื่อนเทปไปข้างหน้าและถอยหลังได้ เครื่องนี้จะอยู่ในสถานะหนึ่ง ๆ เสมอและถูกควบคุมโดยโปรแกรม ซึ่งเป็นชุดกฎที่บอกว่าจะเขียนสัญลักษณ์ใดบนช่องปัจจุบันของเทป จะเคลื่อนเทปไปทิศทางใด และจะเปลี่ยนไปสถานะใหม่ใด ขึ้นกับสัญลักษณ์ที่มองเห็นได้และสถานะปัจจุบัน Turing machine ถูกใช้เพื่อพิสูจน์ความไม่สามารถแก้ปัญหาการหยุดทำงานได้ (ดู chapter 11) โปรแกรมใด ๆ สามารถถูกแปลเป็นโปรแกรมของ Turing machine ได้ ซึ่งหมายความว่า Turing machine เป็นนามธรรมของคอมพิวเตอร์ (อิเล็กทรอนิกส์) ที่มีอยู่ในปัจจุบัน ข้อสำคัญของความเข้าใจนี้คือ ทุกคุณสมบัติทั่วไปที่เราพิสูจน์ได้สำหรับ Turing machine ก็จะใช้ได้กับคอมพิวเตอร์อื่น ๆ ที่มีอยู่เช่นกัน
อีกกลยุทธ์หนึ่งในการย่อจากคอมพิวเตอร์เฉพาะคือการใช้การแปลภาษา ตัวอย่างเช่น เราสามารถแปลอัลกอริทึมการตามลูกกรวดจากภาษาเยอรมันเป็นภาษาฝรั่งเศสหรือภาษาอังกฤษ ซึ่งขจัดอุปสรรคด้านภาษาและทำให้อัลกอริทึมนั้นเข้าถึงได้กว้างขึ้น แนวทางเดียวกันใช้ได้กับภาษาโปรแกรม แน่นอนว่าโปรแกรมเกือบทั้งหมดที่เขียนในปัจจุบันถูกแปลงเป็นบางรูปแบบก่อนจะถูกรันโดยเครื่อง ซึ่งหมายความว่าเกือบไม่มีภาษาโปรแกรมที่เครื่องเข้าใจโดยตรงจริง ๆ และอัลกอริทึมทุกตัวต้องถูกแปล ภาษาโปรแกรมย่อจากรายละเอียดของคอมพิวเตอร์เฉพาะและให้การเข้าถึงที่เป็นหนึ่งเดียวสำหรับการเขียนโปรแกรมบนคอมพิวเตอร์หลากหลายผ่านภาษาเดียว หากมีคอมพิวเตอร์ใหม่ถูกผลิตขึ้น สิ่งที่จำเป็นเพื่อรันอัลกอริทึมเก่าบนคอมพิวเตอร์ใหม่นั้นคือการปรับตัวแปล (translator) ให้ผลิตโค้ดที่เปลี่ยนแปลงสำหรับคอมพิวเตอร์นั้น การย่อผ่านการแปลนี้ทำให้การออกแบบภาษาโปรแกรมเป็นอิสระจากคอมพิวเตอร์ที่พวกมันจะถูกรันได้ในระดับสูง
Figure 15.4 Abstract machine เป็นนามธรรมที่ย่อจากคอมพิวเตอร์เชิงปฏิบัติ โดยการให้ interface ที่เรียบง่ายและทั่วไปขึ้น abstract machine ทำให้ภาษาสำหรับอัลกอริทึมไม่ขึ้นกับสถาปัตยกรรมคอมพิวเตอร์เฉพาะ และขยายช่วงของคอมพิวเตอร์ที่สามารถรันพวกมันได้。
มีหลายวิธีในการนิยามนามธรรม Translate เช่นเดียวกับนามธรรมใด ๆ คำถามคือจะย่อรายละเอียดอะไรและจะเปิดเผยอะไรเป็นพารามิเตอร์ใน interface นิยามต่อไปนี้ย่อจากโปรแกรมที่จะถูกแปล ภาษาต้นฉบับที่โปรแกรมเขียน และภาษาที่ต้องการให้แปลเป็น:
Translate(program, source, target) = “Translate program from source into _target_”
โปรดสังเกตว่าฉันใช้เครื่องหมายคำพูดรอบ “_Translate …_” เพราะการแปลเป็นอัลกอริทึมที่ซับซ้อนมากเกินไปและยาวเกินกว่าจะนำเสนอที่นี่ ตัวอย่างเช่น การแปลภาษาธรรมชาติอัตโนมัติยังเป็นปัญหาเปิด ในทางกลับกัน การแปลภาษาโปรแกรมเป็นปัญหาที่เข้าใจกันดีและแก้ไขได้ อย่างไรก็ตาม ตัวแปลก็ยังเป็นอัลกอริทึมที่ยาวและซับซ้อน ซึ่งเป็นเหตุผลว่าทำไมจึงไม่มีการแสดงรายละเอียดที่นี่
ตัวอย่างการใช้นามธรรม Translate ต่อไปนี้แสดงวิธีการแปลคำสั่งหาหนึ่งก้อนหินจากภาษาเยอรมันเป็นอังกฤษ:
Translate(Finde Kieselstein, German, English)
คำสั่ง Finde Kieselstein เป็นองค์ประกอบของภาษาต้นทางภาษาเยอรมัน และผลลัพธ์ของการแปลคือคำสั่ง Find pebble ซึ่งเป็นองค์ประกอบของภาษาปลายทางภาษาอังกฤษ
ใน Harry Potter ภาษาของคาถาและมนต์ต้องการพ่อมดเพื่อดำเนินการ คาถาบางตัวสามารถถูกแปลเป็นตำรับยาที่สอดคล้องกันได้ ซึ่งสามารถใช้ได้โดย muggles ด้วย ตัวอย่างเช่น ผลของคาถาบางตัวที่เปลี่ยนรูปลักษณ์สามารถจับย่อได้ใน Polyjuice Potion ซึ่งทำให้ผู้ดื่มเปลี่ยนรูปลักษณ์ของตน แม้ว่า Polyjuice Potion จะยากมากในการผลิต แม้กระทั่งสำหรับพ่อมดที่ชำนาญ แต่คาถาอื่น ๆ บางตัวมีการแปลที่ตรงไปตรงมา เช่นคำสาปสังหาร Avada Kedavra ที่แปลเป็นยาพิษร้ายแรงธรรมดาได้
เนื่องจากนามธรรม Translate เองก็เป็นอัลกอริทึม เราจึงสามารถย่อจากการแปลทั้งหมดผ่านภาษาที่พวกมันถูกแสดงออกได้ เช่นเดียวกับที่เราเคยย่อจากอัลกอริทึมทั้งหมดโดยใช้ภาษา ส่วนบนซ้ายของ figure 15.5 อธิบายกรณีนี้ เนื่องจากแต่ละภาษาตรงกับคอมพิวเตอร์หรือ abstract machine ที่สามารถรันโปรแกรมของมันได้ นี่หมายความว่าภาษาสามารถย่อจากคอมพิวเตอร์ได้ ดังที่แสดงที่มุมบนขวาของ figure 15.5
Figure 15.5 หอคอยของนามธรรม: อัลกอริทึมเป็นนามธรรมเชิงฟังก์ชันจากการคำนวณ อัลกอริทึมแปลง representations ซึ่งนามธรรมข้อมูลของพวกมันคือ types ข้อมูลอินพุตและเอาต์พุตที่ยอมรับได้สำหรับอัลกอริทึมก็ถูกแสดงเป็น types ด้วย อัลกอริทึมแต่ละตัวถูกแสดงในภาษา ซึ่งเป็นนามธรรมจากอัลกอริทึม อัลกอริทึมการแปลสามารถแปลงอัลกอริทึมจากภาษาหนึ่งไปยังอีกภาษาหนึ่งและด้วยเหตุนี้ทำให้อัลกอริทึมเป็นอิสระจากคอมพิวเตอร์หรือ abstract machine เฉพาะที่เข้าใจภาษาที่พวกมันถูกแสดงออก ภาษาเป็นนามธรรมของคอมพิวเตอร์เช่นกันเพราะการแปลสามารถขจัดความแตกต่างระหว่างคอมพิวเตอร์ได้ Types ยังถูกแสดงเป็นส่วนหนึ่งของภาษา ลำดับชั้นของนามธรรมแสดงให้เห็นว่านามธรรมทั้งหมดในวิทยาการคอมพิวเตอร์ถูกแสดงออกในบางภาษาเสมอ
เช่นเดียวกับที่ Turing machine เป็นนามธรรมสูงสุดของเครื่องคอมพิวเตอร์ใด ๆ lambda calculus ก็เป็นนามธรรมสูงสุดของภาษาโปรแกรมใด ๆ Lambda calculus ถูกประดิษฐ์ขึ้นประมาณเวลาเดียวกับ Turing machine โดยนักคณิตศาสตร์ชาวอเมริกัน Alonzo Church มันประกอบด้วยโครงสร้างสามอย่างสำหรับการนิยามนามธรรม การอ้างพารามิเตอร์ในคำนิยาม และการสร้างตัวอย่างของนามธรรมโดยการส่งอาร์กิวเมนต์ให้พารามิเตอร์ ซึ่งคล้ายคลึงกับที่ปรากฏใน figure 15.1 โปรแกรมใด ๆ ในภาษาอัลกอริทึมใด ๆ สามารถถูกแปลเป็นโปรแกรม lambda calculus ได้ ตอนนี้ดูเหมือนว่าเราจะมีสองนามธรรมสูงสุดจากคอมพิวเตอร์: lambda calculus และ Turing machine แล้วมันเป็นไปได้อย่างไร? ปรากฏว่าสองนามธรรมนี้เทียบเท่ากัน ซึ่งหมายความว่าโปรแกรมสำหรับ Turing machine ใด ๆ สามารถถูกแปลเป็นโปรแกรม lambda calculus ที่เทียบเท่าได้ และกลับกัน นอกจากนี้ รูปแบบทางการทั้งหมดที่รู้จักสำหรับการแสดงอัลกอริทึม ได้ถูกพิสูจน์ว่าไม่สามารถแสดงความสามารถมากกว่า Turing machines หรือ lambda calculus ได้ ดังนั้น ดูเหมือนว่าอัลกอริทึมใด ๆ สามารถถูกแสดงเป็น Turing machine หรือโปรแกรม lambda calculus ข้อสังเกตนี้เรียกว่า Church–Turing thesis ซึ่งตั้งชื่อตามผู้บุกเบิกทั้งสองของวิทยาการคอมพิวเตอร์ Church–Turing thesis เกี่ยวกับความสามารถในการแสดงออกและขอบเขตของอัลกอริทึม เนื่องจากการนิยามอัลกอริทึมอิงกับแนวคิดของคำสั่งที่มีประสิทธิผล ซึ่งเป็นแนวคิดเชิงสัญชาตญาณที่ผูกกับความสามารถของมนุษย์ อัลกอริทึมจึงไม่สามารถถูกทำเป็นรูปแบบทางคณิตศาสตร์ได้อย่างสมบูรณ์ Church–Turing thesis ไม่ใช่ทฤษฎีที่สามารถพิสูจน์ได้ แต่เป็นการสังเกตเกี่ยวกับแนวคิดเชิงสัญชาตญาณของอัลกอริทึม Church–Turing thesis มีความสำคัญมากเพราะมันบอกว่าทุกสิ่งที่สามารถรู้เกี่ยวกับอัลกอริทึมสามารถค้นพบได้โดยการศึกษาจาก Turing machines และ lambda calculus และ Church–Turing thesis ได้รับการยอมรับโดยนักวิทยาการคอมพิวเตอร์ส่วนใหญ่
การคำนวณถูกใช้ในการแก้ปัญหาอย่างเป็นระบบ แม้ว่าคอมพิวเตอร์อิเล็กทรอนิกส์จะอำนวยความสะดวกให้การเติบโตและการเข้าถึงการคำนวณอย่างที่ไม่เคยมีมาก่อน แต่พวกมันเป็นเพียงเครื่องมือหนึ่งของการคำนวณ แนวคิดของการคำนวณกว้างกว่าและนำไปใช้ได้ทั่วไปมากกว่า ตามที่เราเห็น Hansel และ Gretel รู้วิธีรันอัลกอริทึมและใช้การสร้างนามธรรม (abstractions) อย่างประสบความสำเร็จในการแทนเส้นทางด้วยลูกกรวด Sherlock Holmes เป็นผู้เชี่ยวชาญด้านสัญญาณและการแทน และเขาจัดการ data structures เพื่อแก้คดี และ Indiana Jones ก็ไม่ได้ใช้คอมพิวเตอร์อิเล็กทรอนิกส์ในการค้นหาที่น่าตื่นเต้นของเขา ภาษาของดนตรีอาจไม่แก้ปัญหาโดยตรง แต่ก็ประกอบด้วยทุกบิตของ syntax และ semantics ที่คุณอาจนึกได้ Phil Connors อาจไม่รู้วิชาทฤษฎีวิทยาการคอมพิวเตอร์ แต่เขาเผชิญปัญหาเดียวกันที่แสดงขีดจำกัดพื้นฐานของการคำนวณ: ความไม่สามารถแก้ปัญหา halting problem Marty McFly และ Doc Brown ดำรงชีวิตด้วย recursion และ Harry Potter เผยพลังวิเศษของ types และ abstraction
ฮีโร่ของเรื่องเหล่านี้อาจไม่ได้เป็นฮีโร่ของการคำนวณโดยตรง แต่เรื่องราวของพวกเขาได้บอกเรามากเกี่ยวกับสิ่งที่การคำนวณคือ เมื่อหนังสือเล่มนี้จบลง ฉันอยากทิ้งเรื่องราวอีกเรื่องไว้ให้คุณ—the story of computer science เรื่องนี้เป็นเรื่องของนามธรรมที่ยึดครองแนวคิดของการคำนวณ ตัวเอกหลักคือ algorithm ซึ่งสามารถแก้ problems ได้อย่างเป็นระบบผ่านการแปลงของ representations มันทำเช่นนั้นโดยการใช้เครื่องมือพื้นฐานอย่างชำนาญ เช่น control structures และ recursion แม้ว่าปัญหาสามารถแก้ได้ด้วยหลายวิธี อัลกอริทึมไม่ยอมรับการแก้ปัญหาเฉพาะหนึ่งเดียวแต่พยายามให้กว้างที่สุดโดยใช้อาวุธลับของมันคือ parameter อย่างไรก็ตาม ภารกิจใด ๆ ของมันก็เป็นการต่อสู้ตลอดเวลาเพราะอัลกอริทึมมักเผชิญกับศัตรูสำคัญคือ complexity:
Computation = Story(algorithm, solving problems)
เรื่องราวคลี่คลายเมื่อปัญหาใหม่ ๆ และใหญ่ขึ้นผลักอัลกอริทึมจนถึงขีดจำกัด แต่ในการต่อสู้ของมันมันยังได้รับมิตรภาพและการสนับสนุนจากญาติ ๆ ในตระกูล abstraction: พี่สาว efficiency ที่ให้คำปรึกษาเกี่ยวกับการใช้ทรัพยากรอย่างระมัดระวัง; พี่ชาย type ที่ปกป้องมันไม่ลดละจากข้อผิดพลาดในการเขียนโปรแกรมและอินพุตที่ไม่ถูกต้อง; และคุณย่าผู้ชาญฉลาด language ที่มอบความสามารถในการแสดงออกและทำให้แน่ใจว่ามันถูกเข้าใจโดยเพื่อนร่วมทางที่เชื่อถือได้คือ computer ซึ่งมันพึ่งพาในการรันแผนการใด ๆ ของมัน:
Computer Science = Story(abstractions, capturing computation)
อัลกอริทึมไม่ใช่ผู้ทรงพลังทุกอย่างและไม่สามารถแก้ปัญหาทั้งหมดได้ โดยเฉพาะมันอ่อนแอต่อความไม่มีประสิทธิภาพและข้อผิดพลาด แต่มันตระหนักดีถึงข้อจำกัดของตนเอง และความรู้นี้เกี่ยวกับขีดจำกัดของมันเองทำให้มันแข็งแกร่งและมั่นใจต่อการผจญภัยที่รออยู่ข้างหน้า。