ผู้คนเขียนโปรแกรมสำหรับคอมพิวเตอร์อิเล็กทรอนิกส์มากว่า 80 ปีแล้ว แต่กลับมีการพูดคุยกันน้อยมากเกี่ยวกับวิธีการออกแบบโปรแกรมเหล่านั้น หรือว่าโปรแกรมที่ดีควรมีหน้าตาอย่างไร การอภิปรายเกี่ยวกับกระบวนการพัฒนาซอฟต์แวร์ เช่น agile development และเกี่ยวกับเครื่องมือพัฒนา เช่น debugger, version control system, และ test coverage tool นั้นมีอยู่พอสมควร รวมถึงมีการวิเคราะห์เทคนิคการเขียนโปรแกรมอย่างละเอียด เช่น object-oriented programming และ functional programming รวมถึง design pattern และ algorithm ต่างๆ ด้วย การอภิปรายทั้งหมดนี้มีประโยชน์ แต่ปัญหาแกนหลักของการออกแบบซอฟต์แวร์ยังคงไม่ถูกแตะต้องเป็นส่วนใหญ่ บทความคลาสสิกของ David Parnas เรื่อง "On the Criteria to be used in Decomposing Systems into Modules" ตีพิมพ์ในปี 1971 แต่สถานะของการออกแบบซอฟต์แวร์ก็ไม่ได้ก้าวหน้าไปมากกว่าบทความนั้นนักใน 45 ปีต่อมา
ปัญหาที่พื้นฐานที่สุดในคอมพิวเตอร์คือ problem decomposition : วิธีการนำปัญหาที่ซับซ้อนมาแบ่งออกเป็นชิ้นส่วนย่อยๆ ที่สามารถแก้ไขได้ independently Problem decomposition เป็นงานออกแบบหลักที่โปรแกรมเมอร์ต้องเผชิญทุกวัน แต่ทว่านอกเหนือจากงานที่อธิบายในหนังสือเล่มนี้แล้ว ผมไม่สามารถหาวิชาเรียนในมหาวิทยาลัยสักแห่งที่ให้ความสำคัญกับ problem decomposition เป็นหัวข้อหลัก เราสอน for loop และ object-oriented programming แต่เราไม่สอนการออกแบบซอฟต์แวร์
นอกจากนี้ คุณภาพและประสิทธิภาพของโปรแกรมเมอร์แต่ละคนนั้นแตกต่างกันอย่างมาก แต่เรากลับมีความพยายามน้อยมากที่จะทำความเข้าใจว่าอะไรที่ทำให้โปรแกรมเมอร์ที่เก่งที่สุดดีกว่าใคร หรือจะสอนทักษะเหล่านั้นในชั้นเรียนได้อย่างไร ผมได้พูดคุยกับหลายคนที่ผมคิดว่าเป็นโปรแกรมเมอร์ที่ยอดเยี่ยม แต่ส่วนใหญ่แล้วพวกเขามักจะอธิบายเทคนิคเฉพาะที่ทำให้พวกเขาได้เปรียบได้ยาก หลายคนมักคิดว่าทักษะการออกแบบซอฟต์แวร์เป็นพรสวรรค์ติดตัวที่ไม่สามารถสอนกันได้ อย่างไรก็ตาม มีหลักฐานทางวิทยาศาสตร์มากมายที่ชี้ให้เห็นว่าผลงานที่โดดเด่นในหลายสาขานั้นเกี่ยวข้องกับการฝึกฝนที่มีคุณภาพสูงมากกว่าความสามารถโดยกำเนิด (ดูตัวอย่างจากหนังสือ Talent is Overrated โดย Geoff Colvin)
เป็นเวลาหลายปีที่ประเด็นเหล่านี้สร้างความฉงนและความหงุดหงิดให้กับผม ผมสงสัยว่าการออกแบบซอฟต์แวร์สามารถสอนกันได้หรือไม่ และผมตั้งสมมติฐานว่าทักษะการออกแบบคือสิ่งที่ แยกโปรแกรมเมอร์ที่ยอดเยี่ยมออกจากโปรแกรมเมอร์ทั่วไป ในที่สุดผมก็ตัดสินใจว่าวิธีเดียวที่จะหาคำตอบสำหรับคำถามเหล่านี้ได้คือการลองสอนวิชาการออกแบบซอฟต์แวร์ดู ผลลัพธ์คือวิชา CS 190 ที่ Stanford University ในวิชานี้ผมได้นำเสนอชุดหลักการของการออกแบบซอฟต์แวร์ จากนั้นนักศึกษาจะทำงานผ่านโปรเจกต์ต่างๆ เพื่อซึมซับและฝึกฝนหลักการเหล่านั้น วิชานี้สอนในรูปแบบที่คล้ายกับวิชาเขียนภาษาอังกฤษแบบดั้งเดิม ในวิชาเขียนภาษาอังกฤษ นักศึกษาจะใช้กระบวนการ iterative ที่พวกเขาเขียนร่างแรก ได้รับ feedback แล้วจึงเขียนใหม่เพื่อปรับปรุง ใน CS 190 นักศึกษาจะพัฒนาซอฟต์แวร์ชิ้นสำคัญตั้งแต่เริ่มต้น จากนั้นเราจะทำการ review โค้ดอย่างละเอียดเพื่อระบุปัญหาในการออกแบบ และนักศึกษาจะปรับปรุงโปรเจกต์ของตนเพื่อแก้ไขปัญหาเหล่านั้น ซึ่งทำให้นักศึกษาได้เห็นว่าโค้ดของพวกเขาสามารถปรับปรุงได้โดยการใช้หลักการออกแบบ
ตอนนี้ผมได้สอนวิชาการออกแบบซอฟต์แวร์ไปแล้วสามครั้ง และหนังสือเล่มนี้ก็มีพื้นฐานมาจากหลักการออกแบบที่เกิดขึ้นจากวิชานั้น หลักการต่างๆ ค่อนข้างเป็นนามธรรมและกึ่งปรัชญา ("Define errors out of existence") ดังนั้นจึงเป็นเรื่องยากที่นักศึกษาจะเข้าใจแนวคิดเหล่านี้ในเชิงทฤษฎี นักศึกษาเรียนรู้ได้ดีที่สุดจากการเขียนโค้ด ทำผิดพลาด แล้วเห็นว่าข้อผิดพลาดและการแก้ไขที่ตามมานั้นเกี่ยวข้องกับหลักการอย่างไร
ถึงจุดนี้คุณอาจจะสงสัยว่าอะไรทำให้ผมคิดว่าผมรู้คำตอบทั้งหมดเกี่ยวกับการออกแบบซอฟต์แวร์? พูดตามตรง ผมไม่ได้รู้ทั้งหมด ไม่มีวิชาเกี่ยวกับการออกแบบซอฟต์แวร์ตอนที่ผมเรียนเขียนโปรแกรม และผมก็ไม่เคยมี mentor ที่สอนหลักการออกแบบให้ผม ในช่วงที่ผมเรียนรู้การเขียนโปรแกรม การ review โค้ดแทบจะไม่มีเลย ความคิดของผมเกี่ยวกับการออกแบบซอฟต์แวร์มาจากประสบการณ์ส่วนตัวในการเขียนและอ่านโค้ด ตลอดอาชีพของผม ผมเขียนโค้ดไปประมาณ 250,000 บรรทัดในภาษาต่างๆ มากมาย ผมเคยทำงานในทีมที่สร้างระบบปฏิบัติการตั้งแต่เริ่มต้นสามระบบ ระบบไฟล์และระบบจัดเก็บข้อมูลหลายระบบ เครื่องมือ infrastructure เช่น debugger, build system, และ GUI toolkit, ภาษา scripting, และ editor แบบโต้ตอบสำหรับข้อความ ภาพวาด งานนำเสนอ และวงจรรวม ตลอดเส้นทางนี้ผมได้สัมผัสกับปัญหาของระบบขนาดใหญ่ด้วยตัวเอง และได้ทดลองเทคนิคการออกแบบต่างๆ นอกจากนี้ ผมยังได้อ่านโค้ดของคนอื่นเป็นจำนวนมาก ซึ่งทำให้ผมได้เห็นแนวทางที่หลากหลาย ทั้งที่ดีและไม่ดี
จากประสบการณ์ทั้งหมดนี้ ผมพยายามที่จะสกัดเอาสิ่งที่เหมือนกันออกมา ทั้งข้อผิดพลาดที่ควรหลีกเลี่ยงและเทคนิคที่ควรใช้ หนังสือเล่มนี้สะท้อนประสบการณ์ของผม: ทุกปัญหาที่อธิบายในที่นี้คือปัญหาที่ผมเคยประสบด้วยตัวเอง และทุกเทคนิคที่แนะนำคือเทคนิคที่ผมใช้ได้สำเร็จในการเขียนโค้ดของตัวเอง
ผมไม่ได้คาดหวังให้หนังสือเล่มนี้เป็นคำตอบสุดท้ายเกี่ยวกับการออกแบบซอฟต์แวร์ ผมมั่นใจว่ายังมีเทคนิคที่มีค่าอีกมากที่ผมพลาดไป และคำแนะนำบางอย่างของผมอาจกลายเป็น ความคิดที่ไม่ดีในระยะยาว อย่างไรก็ตาม ผมหวังว่าหนังสือเล่มนี้จะเริ่มต้นการสนทนาเกี่ยวกับการออกแบบซอฟต์แวร์ ลองเปรียบเทียบแนวคิดในหนังสือเล่มนี้กับประสบการณ์ของคุณเอง และตัดสินใจด้วยตัวเองว่าแนวทางที่อธิบายไว้ที่นี่ช่วยลดความซับซ้อนของซอฟต์แวร์ได้จริงหรือไม่ หนังสือเล่มนี้เป็น opinion piece ดังนั้นผู้อ่านบางคนอาจไม่เห็นด้วยกับคำแนะนำบางข้อของผม ถ้าคุณไม่เห็นด้วย ลองทำความเข้าใจว่าทำไม ผมสนใจที่จะฟังสิ่งที่ใช้ได้ผลสำหรับคุณ สิ่งที่ใช้ไม่ได้ผล และแนวคิดอื่นๆ ที่คุณอาจมีเกี่ยวกับการออกแบบซอฟต์แวร์ ผมหวังว่าการสนทนาที่จะตามมาจะช่วยพัฒนาความเข้าใจร่วมกันของเราเกี่ยวกับการออกแบบซอฟต์แวร์ ผมจะนำสิ่งที่ได้เรียนรู้ไปรวมไว้ในหนังสือรุ่นต่อๆ ไป
วิธีที่ดีที่สุดในการติดต่อผมเกี่ยวกับหนังสือคือส่งอีเมลไปยังที่อยู่ต่อไปนี้:
ผมสนใจที่จะรับ feedback เฉพาะเกี่ยวกับหนังสือ เช่น ข้อบกพร่องหรือข้อเสนอแนะในการปรับปรุง รวมถึงความคิดเห็นและประสบการณ์ทั่วไปที่เกี่ยวข้องกับการออกแบบซอฟต์แวร์ ผมสนใจเป็นพิเศษในตัวอย่างที่น่าสนใจที่ผมสามารถนำไปใช้ในหนังสือรุ่นต่อๆ ไป ตัวอย่างที่ดีที่สุดคือตัวอย่างที่แสดงให้เห็นหลักการออกแบบที่สำคัญและเรียบง่ายพอที่จะอธิบายได้ในย่อหน้าหรือสองย่อหน้า ถ้าคุณอยากเห็นว่าคนอื่นพูดอะไรในอีเมลแอดเดรสนั้น และอยากร่วมสนทนา คุณสามารถเข้าร่วม Google Group software-design-book ได้
ถ้าด้วยเหตุผลบางอย่าง software-design-book Google Group หายไปในอนาคต ให้ค้นหาในเว็บสำหรับหน้า home page ของผม ซึ่งจะมีคำแนะนำที่อัปเดตแล้วสำหรับวิธีการติดต่อเกี่ยวกับหนังสือ กรุณาอย่าส่งอีเมลเกี่ยวกับหนังสือไปยังอีเมลส่วนตัวของผม
ผมแนะนำให้คุณรับคำแนะนำในหนังสือเล่มนี้ด้วยความระมัดระวัง (take with a grain of salt) เป้าหมายโดยรวมคือการลดความซับซ้อน ซึ่งสำคัญกว่าหลักการหรือแนวคิดเฉพาะใดๆ ที่คุณอ่านในนี้ ถ้าคุณลองใช้แนวคิดจากหนังสือเล่มนี้แล้วพบว่ามันไม่ได้ลดความซับซ้อนจริงๆ ก็ไม่จำเป็นต้องรู้สึกว่าต้องใช้มันต่อไป (แต่แจ้งให้ผมรู้เกี่ยวกับประสบการณ์ของคุณด้วยนะครับ ผมอยากได้ feedback ว่าอะไรใช้ได้ผลและอะไรใช้ไม่ได้)
หลายคนได้เสนอคำวิจารณ์หรือคำแนะนำที่ช่วยปรับปรุงคุณภาพของหนังสือ คนต่อไปนี้ได้ให้ความคิดเห็นที่เป็นประโยชน์ในร่างต่างๆ ของหนังสือ: 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 กระบวนการอ่านโค้ดของพวกเขาและพูดคุยกับพวกเขาได้ช่วยตกผลึกความคิดของผมเกี่ยวกับการออกแบบ