มนุษย์เขียนโปรแกรมสำหรับคอมพิวเตอร์อิเล็กทรอนิกส์มาเกือบ 80 ปีแล้ว แต่น่าแปลกที่การสนทนาเกี่ยวกับวิธีการออกแบบโปรแกรมหรือลักษณะของโปรแกรมที่ดีนั้นมีน้อยมาก มีการอภิปรายอย่างมากเกี่ยวกับกระบวนการพัฒนา Software เช่น Agile development และเครื่องมือพัฒนา เช่น Debugger, Version control system และ Test coverage tool มีการวิเคราะห์เทคนิคการโปรแกรม เช่น Object-oriented programming และ Functional programming ตลอดจน Design pattern และ Algorithm อย่างกว้างขวาง การอภิปรายเหล่านี้ล้วนมีค่ากับเราทั้งสิ้น แต่ปัญหาหลักของการออกแบบ Software ยังคงเป็นที่สัมผัสไม่ได้เป็นส่วนใหญ่ เอกสารคลาสสิกของ David Parnas "On the Criteria to be used in Decomposing Systems into Modules" ปรากฏขึ้นในปี 1971 แต่ระดับศิลปะในการออกแบบ Software ยังคงไม่ก้าวหน้าไปไกลกว่าบทความนั้นมากนักในรอบ 45 ปี
ปัญหาพื้นฐานที่สุดในวิทยาศาสตร์คอมพิวเตอร์คือ การแยกย่อยปัญหา (problem decomposition): วิธีการนำปัญหาที่ซับซ้อนมาแบ่งออกเป็นชิ้นส่วนที่สามารถแก้ไขได้อย่างเป็นอิสระ การแยกย่อยปัญหาคือภารกิจการออกแบบหลักที่ Programmer ต้องเผชิญทุกวัน แต่นอกจากงานที่อธิบายไว้ที่นี่แล้ว ผมไม่สามารถหากลุ่มวิชาในมหาวิทยาลัยใดที่ให้ความสำคัญอย่างจริงจังกับการแยกย่อยปัญหาได้เลย เราสอน for loop และ Object-oriented programming แต่ไม่ได้สอนการออกแบบ Software
นอกจากนี้ยังมีความแตกต่างที่มากมายในด้านคุณภาพและความเป็นประสิทธิผลระหว่าง Programmer แต่เราไม่ได้พยายามทำความเข้าใจว่าสิ่งใดทำให้ Programmer ที่ดีที่สุดมีความเก่งกว่าคนอื่น หรือสอนทักษะเหล่านั้นในชั้นเรียนของเรา ผมได้คุยกับคน ๆ หนึ่งที่ผมถือว่าเป็น Programmer ที่เก่ง แต่คนส่วนใหญ่พบว่ามีความยากลำบากในการอธิบายเทคนิคเฉพาะที่ให้เหตุผลในความสำเร็จของพวกเขา หลายคนสันนิษฐานว่าทักษะการออกแบบ Software เป็นพรสวรรค์ที่กำเนิดมาซึ่งไม่สามารถสอนได้ อย่างไรก็ตาม มีหลักฐานทางวิทยาศาสตร์ที่ค่อนข้างชัดเจนว่าผลงานที่ยอดเยี่ยมในสาขาต่าง ๆ มากมายเกี่ยวข้องกับการฝึกฝนที่มีคุณภาพสูงมากกว่าความสามารถที่กำเนิดมา (ดูเช่น Talent is Overrated โดย Geoff Colvin)
มานานแล้วเหล่าปัญหาเหล่านี้ทำให้ผมงุนงง และท่อแท้ใจ ผมได้สงสัยว่าสามารถสอนการออกแบบ Software ได้หรือไม่ และผมสันนิษฐานว่าทักษะการออกแบบคือสิ่งที่แยกแยะระหว่าง Programmer ที่เก่งกับเฉลี่ย ในที่สุดผมตัดสินใจว่าวิธีเดียวที่จะตอบคำถามเหล่านี้ได้คือพยายามสอนวิชาการออกแบบ Software ผลลัพธ์คือ CS 190 ที่มหาวิทยาลัย Stanford ในชั้นเรียนนี้ ผมได้นำเสนอหลักการของการออกแบบ Software นักศึกษาจากนั้นทำโครงการต่าง ๆ เพื่อเข้าใจ และฝึกฝนหลักการเหล่านั้น ชั้นเรียนนี้สอนในลักษณะที่คล้ายกับชั้นเรียนการเขียนภาษาอังกฤษแบบดั้งเดิม ในชั้นเรียนภาษาอังกฤษ นักเรียนใช้กระบวนการวนซ้ำ โดยเขียนฉบับร่าง รับข้อเสนอแนะ จากนั้นเขียนใหม่เพื่อการปรับปรุง ใน CS 190 นักศึกษาพัฒนา Software ที่มีขนาดใหญ่ตั้งแต่เริ่มต้น จากนั้นเราดำเนินการ Code review อย่างกว้างขวางเพื่อค้นหาปัญหาการออกแบบ และนักศึกษาแก้ไขโครงการของพวกเขาเพื่อแก้ไขปัญหา นี่ทำให้นักเรียนเห็นว่า Code ของพวกเขาสามารถปรับปรุงได้อย่างไรโดยการนำหลักการออกแบบไปใช้
ปัจจุบัน ผมสอนวิชาการออกแบบ Software สามครั้งแล้ว และหนังสือเล่มนี้อิงจากหลักการออกแบบที่โผล่ออกมาจากชั้นเรียน หลักการต่างๆ มีระดับค่อนข้างสูง และเข้าใกล้เชิงปรัชญา ("นิยาม Error ออกจากการมีอยู่") จึงยากสำหรับนักเรียนที่จะเข้าใจแนวคิดในทางนามธรรม นักเรียนเรียนรู้ได้ดีที่สุดโดยการเขียน Code สร้างข้อผิดพลาด จากนั้นเห็นว่าข้อผิดพลาดของพวกเขาและการแก้ไขในภายหลังเกี่ยวข้องกับหลักการอย่างไร
ณ จุดนี้คุณอาจจะสงสัยว่า: อะไรทำให้ผมคิดว่าผมรู้คำตอบทั้งหมดเกี่ยวกับการออกแบบ Software เพื่อให้สัตย์ต่อสติ ผมไม่รู้ ไม่มีชั้นเรียนเกี่ยวกับการออกแบบ Software เมื่อผมเรียนรู้การโปรแกรม และผมไม่เคยมี Mentor ที่สอนหลักการออกแบบให้ผม ในเวลาที่ผมเรียนรู้การโปรแกรม Code review เกือบจะไม่มีเลย แนวคิดของผมเกี่ยวกับการออกแบบ Software มาจากประสบการณ์ส่วนตัวในการเขียนและอ่าน Code ตลอดอาชีพของผม ผมเขียน Code มากกว่า 250,000 บรรทัดในภาษาต่าง ๆ มากมาย ผมทำงานในทีมที่สร้าง Operating system สามตัวตั้งแต่เริ่มต้น ระบบแฟ้มและแฟ้มเก็บข้อมูลหลายตัว เครื่องมือ Infrastructure เช่น Debugger, Build system และ GUI toolkit, ภาษา Scripting, และ Interactive editor สำหรับข้อความ, ภาพวาด, การนำเสนอ, และ Integrated circuit ในการดำเนินการ ผมได้สัมผัสปัญหาของระบบขนาดใหญ่โดยตรงและทดลองเทคนิคการออกแบบต่างๆ นอกจากนี้ ผมได้อ่าน Code ที่เขียนโดยคนอื่นจำนวนมาก ซึ่งทำให้ผมเข้าสัมผัสกับวิธีการต่างๆ ทั้งที่ดีและไม่ดี
จากประสบการณ์ทั้งหมดนี้ ผมพยายามแยกเส้นด้ายทั่วไป ทั้งเกี่ยวกับข้อผิดพลาดที่ต้องหลีกเลี่ยงและเทคนิคที่จะใช้ หนังสือเล่มนี้เป็นการสะท้อนประสบการณ์ของผม: ปัญหาทุกประการที่อธิบายไว้ที่นี่คือสิ่งที่ผมได้สัมผัสเป็นการส่วนตัว และเทคนิคที่เสนอแนะทุกประการคือสิ่งที่ผมใช้ได้สำเร็จในการ Coding ของผมเอง
ผมไม่คาดหวังว่าหนังสือเล่มนี้จะเป็นคำพูดสุดท้ายเกี่ยวกับการออกแบบ Software; ผมแน่ใจว่ามีเทคนิคที่มีค่าที่ผมพลาดไป และข้อเสนอแนะบางส่วนของผมอาจกลับกลายเป็นความคิดที่ไม่ดีในระยะยาว อย่างไรก็ตาม ผมหวังว่าหนังสือจะเริ่มการสนทนาเกี่ยวกับการออกแบบ Software เปรียบเทียบแนวคิดในหนังสือเล่มนี้กับประสบการณ์ของคุณเอง และตัดสินใจด้วยตัวเองว่าวิธีการที่อธิบายไว้ที่นี่ลดความซับซ้อนของ Software ได้จริงหรือไม่ หนังสือเล่มนี้เป็นงานวิจารณ์ดังนั้นผู้อ่านบางคนจะไม่เห็นด้วยกับข้อเสนอแนะบางส่วนของผม หากคุณไม่เห็นด้วย พยายามทำความเข้าใจว่าทำไม ผมสนใจที่จะได้ยินเรื่องต่างๆ ที่เหมาะสมกับคุณ สิ่งต่างๆ ที่ไม่ได้ผล และความคิดอื่น ๆ ที่คุณอาจมีเกี่ยวกับการออกแบบ Software ผมหวังว่าการสนทนาต่อเนื่องจะปรับปรุงความเข้าใจของเราเกี่ยวกับการออกแบบ Software รวมกัน ผมจะรวมสิ่งที่ผมได้เรียนรู้ในฉบับฉบับต่อไปของหนังสือ
วิธีที่ดีที่สุดในการติดต่อผมเกี่ยวกับหนังสือคือการส่ง Email ไปที่ที่อยู่ต่อไปนี้:
ผมสนใจที่จะได้รับข้อเสนอแนะเฉพาะเกี่ยวกับหนังสือ เช่น จุดบกพร่องหรือข้อเสนอแนะในการปรับปรุง ตลอดจนความคิดและประสบการณ์ทั่วไปที่เกี่ยวข้องกับการออกแบบ Software ผมสนใจเป็นพิเศษในตัวอย่างที่น่าสนใจซึ่งฉันสามารถใช้ได้ในฉบับต่อไปของหนังสือ ตัวอย่างที่ดีที่สุดแสดงให้เห็นหลักการออกแบบที่สำคัญและเรียบง่ายพอที่จะอธิบายในย่อหน้าหรือสองย่อหน้า หากคุณต้องการดูว่าคนอื่น ๆ พูดอะไรในแอดเดรส Email นี้และเข้าร่วมการอภิปราย คุณสามารถเข้าร่วม Google Group software-design-book
หากด้วยเหตุผลบางประการ software-design-book Google Group ควรหายไปในอนาคต ให้ค้นหาบนเว็บสำหรับหน้าแรกของผม; มันจะมีคำแนะนำที่อัปเดตเกี่ยวกับวิธีการติดต่อเกี่ยวกับหนังสือ โปรดอย่าส่ง Email ที่เกี่ยวข้องกับหนังสือไปที่ที่อยู่ Email ส่วนตัวของผม
ผมแนะนำให้คุณใช้ข้อเสนอแนะในหนังสือเล่มนี้ด้วยความเครื่องครัวที่เท่าเทียม เป้าหมายโดยรวมคือการลดความซับซ้อน นี่มีความสำคัญมากกว่าหลักการหรือแนวคิดโดยเฉพาะที่คุณอ่านที่นี่ หากคุณลองแนวคิดจากหนังสือเล่มนี้และพบว่าไม่ได้ลดความซับซ้อนลง คุณไม่จำเป็นต้องรู้สึกผูกพันให้คงใช้มัน (แต่ให้บอกผมเกี่ยวกับประสบการณ์ของคุณ; ผมอยากได้ข้อเสนอแนะเกี่ยวกับสิ่งที่ได้ผลและสิ่งที่ไม่ได้ผล)
หลายคนได้เสนอวิจารณ์หรือให้ข้อเสนอแนะที่ปรับปรุงคุณภาพของหนังสือ บุคคลต่อไปนี้ได้เสนอความเห็นที่เป็นประโยชน์เกี่ยวกับฉบับร่างต่างๆ ของหนังสือ: Jeff Dean, Sanjay Ghemawat, John Hartman, Brian Kernighan, James Koppel, Amy Ousterhout, Kay Ousterhout, Rob Pike, Partha Ranganathan, Keith Schwartz, และ Alex Snaps Christos Kozyrakis แนะนำคำว่า "deep" และ "shallow" สำหรับ Class และ Interface ซึ่งแทนที่คำศัพท์ก่อนหน้านี้ "thick" และ "thin" ซึ่งค่อนข้างคลุมเครือบ้าง ผมรู้สึกขอบคุณต่อนักเรียนใน CS 190; กระบวนการอ่าน Code ของพวกเขาและอภิปรายกับพวกเขาได้ช่วยชี้แจงความคิดของผมเกี่ยวกับการออกแบบ