- เป็นบทสนทนาเกี่ยวกับการออกแบบซอฟต์แวร์ระหว่าง Robert “Uncle Bob” Martin และ John Ousterhout ที่ดำเนินต่อเนื่องตั้งแต่เดือนกันยายน 2024 ถึงกุมภาพันธ์ 2025
- ทั้งสองคนต่างก็เป็นผู้เขียนหนังสือเกี่ยวกับการออกแบบซอฟต์แวร์
- ทั้งคู่มีความเห็นต่างกันใน 3 ประเด็นหลัก ได้แก่ ความยาวของเมธอด, คอมเมนต์, และ Test-Driven Development
- แก่นของบทสนทนาคือวิธีลดความซับซ้อนของโค้ด เพิ่มความสามารถในการอ่าน และแนวทางการเขียนเทสต์ที่เหมาะสม
ความยาวของเมธอด
- Uncle Bob (ต่อไปจะเรียกว่า UB) เน้นจุดยืนว่า “ฟังก์ชันสั้นดีกว่า และถ้าเป็นไปได้ก็ควรแยกให้สั้นลงอีก”
- หนึ่งเมธอดควรทำเพียง “สิ่งเดียว (One Thing)” เท่านั้น
- อย่างไรก็ตาม หากใช้แนวคิดนี้แบบสุดโต่งเกินไป ก็อาจนำไปสู่การแยกย่อยมากเกินความจำเป็น (over-decomposition)
- John ชี้ว่าเมธอดที่เล็กเกินไปกลับทำให้เข้าใจภาพรวมของการทำงานได้ยากขึ้น
- เมื่อมี “เมธอดตื้น (shallow)” จำนวนมาก จะเกิดปัญหาว่าต้องไล่ดูเมธอดที่เกี่ยวข้องทั้งหมดเพื่อทำความเข้าใจฟังก์ชันเดียว
- การพึ่งพากันระหว่างเมธอด (“entanglement”) สูงขึ้น ทำให้ภาระในการอ่านโค้ดมากขึ้น
- ตัวอย่าง
PrimeGenerator
- โค้ดต้นฉบับของ UB ถูกแยกเป็นเมธอดย่อยเล็ก ๆ ราว 8 เมธอด และเมธอดเหล่านั้นเชื่อมโยงกันจนเข้าใจได้ยาก
- เวอร์ชันของ John เขียนให้เป็นเมธอดเดียวพร้อมคอมเมนต์อย่างเพียงพอ เพื่อให้เห็นลำดับการทำงานทั้งหมดได้ในครั้งเดียว
- UB ก็ยอมรับในระดับหนึ่งว่า “มีการแยกย่อยมากเกินไป”
- สรุปแล้ว ทั้งสองเห็นตรงกันว่าการแยกโค้ดเป็นสิ่งสำคัญ แต่หัวใจคือการหาสมดุลระหว่าง “การแยกย่อยเล็กเกินไป” กับ “การปล่อยให้ใหญ่เกินไป”
คอมเมนต์
- UB มองคอมเมนต์ว่าเป็น “สิ่งจำเป็นที่หลีกเลี่ยงไม่ได้ (necessary evil)”
- เขาเห็นว่าคอมเมนต์มักไม่ค่อยถูกอัปเดต หรือเสี่ยงต่อการให้ข้อมูลที่ผิด
- เขาจึงชอบแนวทางที่ให้โค้ดสื่อเจตนาให้มากที่สุด และถ้าจำเป็นก็ยอมใช้ชื่อที่ยาวมาก
- John ยืนยันว่าคอมเมนต์เป็นสิ่งจำเป็น
- หากเขียนวัตถุประสงค์ของอินเทอร์เฟซ (เมธอด) หรือเจตนาของการ implementation เป็นภาษาอังกฤษอย่างชัดเจน จะช่วยลดเวลาที่นักพัฒนาคนอื่นต้องไปคุ้ยโค้ดโดยไม่จำเป็น
- เขามองว่า “สิ่งที่อันตรายที่สุดคือสถานการณ์ที่ไม่มีคอมเมนต์จนต้องตีความโค้ดเอง”
- จากตัวอย่าง
PrimeGenerator John ชี้ว่าหากไม่มีคอมเมนต์อธิบายว่า “อัลกอริทึมทำงานแบบนั้นเพราะอะไร” ก็จะเข้าใจได้ยากมาก
- UB เห็นว่า “ถ้าคอมเมนต์ไม่แม่นยำก็ยิ่งเป็นโทษ” ขณะที่ John อยู่ฝั่งที่มองว่า “คอมเมนต์ที่ไม่มีเลยอันตรายกว่าคอมเมนต์ที่ผิด”
- แม้ทั้งคู่จะเห็นพ้องกันอยู่บ้างว่า “ควรใส่คอมเมนต์ในระดับที่เหมาะสมตามทีมและสถานการณ์” แต่โดยรวมแล้ว John ให้คุณค่ากับคอมเมนต์สูงกว่ามาก
การรีแฟกเตอร์ PrimeGenerator ของ John
- John ปรับโค้ดที่เดิมแยกเป็น 8 เมธอด ให้กลายเป็นเมธอดเดียว หรืออยู่ในรูปแบบ 2–3 เมธอด
- เขาใส่คอมเมนต์อย่างละเอียดในจุดที่จำเป็น เพื่ออธิบายว่า “ทำไมจึง implementation ด้วยวิธีนี้”
- เขาใช้คอมเมนต์อธิบายทั้งเจตนาของตัวแปรหลัก (
multiples, primes) และวิธีทำงานของอัลกอริทึม เพื่อช่วยให้เข้าใจโค้ดได้รวดเร็วขึ้น
- UB ระบุว่าโค้ดนี้เองก็ยังไม่ถึงกับเข้าใจได้ทันที
- การอธิบายอัลกอริทึมที่ซับซ้อนยังคงต้องใช้เวลา และแม้แต่ผู้เขียนเองก็รู้สึกว่ายากระหว่างการทบทวนอีกครั้ง
การรีแฟกเตอร์ PrimeGenerator2 ของ Bob
- เป็นเวอร์ชันที่ UB ปรับจากโค้ดของ John เล็กน้อย
- เขาแยกบางเมธอดเพิ่มเติมและทำ “การรีแฟกเตอร์ต่อเนื่อง”
- ในส่วนของลูป เขาเพิ่มความอ่านง่ายขึ้น แต่ก็ทำให้ประสิทธิภาพลดลงชั่วคราว
- John ชี้ว่า “ถ้าแบ่งเป็นเมธอดเล็กเกินไป อาจเกิดปัญหาด้านประสิทธิภาพได้” และ UB ก็ปรับแก้อีกครั้งเพื่อให้ประสิทธิภาพดีขึ้น
- อย่างไรก็ตาม ด้วยความชอบของ UB ที่ต้องการ “ลดคอมเมนต์ให้น้อยที่สุด” John จึงยังคงยืนยันว่า “ถ้ามีคำอธิบายเพิ่มจะเข้าใจได้ง่ายกว่า”
Test-Driven Development
- UB สนับสนุนอย่างมากต่อแนวทาง TDD ที่เขียนเทสต์ก่อนในรอบสั้น ๆ แล้วค่อย ๆ เพิ่มโค้ดเพื่อให้ผ่านเทสต์ที่ล้มเหลว
- เขาอ้างว่าวิธีนี้ช่วยให้โค้ดยังคงมี test coverage อยู่เสมอ และหลีกเลี่ยงการดีบักที่ซับซ้อนได้
- เขามองว่าโค้ดจะค่อย ๆ สะอาดขึ้นผ่านการรีแฟกเตอร์บ่อย ๆ
- John กังวลว่า TDD อาจไหลไปสู่ “แนวทางเชิงยุทธวิธี” มากเกินไป
- เขาชี้ว่า “ควรมีการออกแบบนำหน้าก่อน แต่ TDD กลับชี้นำให้เขียนโค้ดก่อน (ในรูป implementation ขั้นต่ำเพื่อให้ผ่านเทสต์)”
- เขามองว่าการออกแบบที่ดีควรคิดในกรอบที่กว้างกว่าในคราวเดียว และเขียนเทสต์แบบรวมชุด (bundling) สำหรับโค้ดส่วนนั้นจะดีกว่า
- UB ยอมรับว่าอาจมี “ปัญหาที่เกิดจากการใช้ TDD ผิดวิธี” แต่ยืนยันว่าหากปฏิบัติอย่างถูกต้อง มันจะช่วยทั้งเรื่อง test coverage และการออกแบบใหม่ (refactoring)
- John แสดงความกังวลว่า “สำหรับมือใหม่ TDD อาจกลับทำให้โค้ดเละได้อย่างรวดเร็วมากกว่า”
- ในท้ายที่สุด ทั้งสองเห็นตรงกันว่า “ทั้ง TDD และแนวทาง bundling ต่างก็สร้างโค้ดที่ยอดเยี่ยมได้ ถ้าใช้อย่างถูกต้อง” แต่ยังมีจุดยืนต่างกันว่าแนวทางไหนดีกว่า
บทส่งท้าย
- John:
- เขากังวลว่า “Clean Code” เน้นการแยกฟังก์ชันให้เล็กมากและกดบทบาทของคอมเมนต์มากเกินไป จนผู้อ่านอาจทำตามแบบสุดโต่ง
- หากไม่ใส่คอมเมนต์อย่างเพียงพอ โค้ดจะเข้าใจได้ยาก และสุดท้ายนักพัฒนาก็ต้องเสียเวลามากขึ้น
- เขายังชี้ว่า TDD ก็อาจทำให้มองข้ามการออกแบบในภาพใหญ่ได้เช่นกัน
- UB:
- เขาระบุว่าใน “Clean Code” ฉบับพิมพ์ครั้งที่ 2 ได้มีการปรับปรุงบางส่วน และนำความเห็นของ John มาผสานไว้บางส่วนแล้ว
- เขาเน้นย้ำจุดร่วมว่า แม้แต่ละคนจะมีประสบการณ์และมุมมองต่างกัน แต่ท้ายที่สุด “ทุกคนควรมุ่งไปสู่โค้ดที่สะอาดและดูแลรักษาได้ง่าย”
- โดยสรุป ทั้งสองให้ความสำคัญกับการออกแบบซอฟต์แวร์และ “การทำให้โค้ดอ่านง่าย” เป็นคุณค่าสูงสุด
- เพียงแต่ยังมีความต่างกันในเรื่องเกณฑ์การแยกเมธอด วิธีใช้คอมเมนต์ และลำดับการเขียนเทสต์
- แก่นสำคัญคือ ต้องหาสมดุลให้เหมาะกับสภาพแวดล้อมของทีมและโครงสร้างโค้ด พร้อมพัฒนาการออกแบบอย่างต่อเนื่อง
14 ความคิดเห็น
ผมมีหนังสือชุด Clean อยู่หลายเล่ม แต่คิดว่าน่าจะเหมาะกับการใช้อ้างอิงในระดับเมตาคอกนิชันมากกว่า ถ้าปฏิบัติกับมันเหมือนเป็นหลักการหรือกฎตายตัวจะเหนื่อยมากและก็ไม่ค่อยใช้งานได้จริงด้วย ลุงบ๊อบพูดถึงหลักการ SOLID อยู่ตลอด แต่โดยส่วนตัวแล้วผมรู้สึกว่าเนื้อหาเชิงปฏิบัติจริงมีไม่มากนัก
ผมคิดว่า
Code Complete,Clean Codeน่าจะเป็นหนังสือที่ถูกประเมินค่าสูงเกินจริงจนได้อันดับ 1 ร่วมกันหนังสือ A Philosophy of Software Design มีฉบับแปลออกมาหรือยังครับ? ลองค้นหาแล้วแต่ยังหาไม่เจอเลยครับ
ฟังดูย้อนแย้ง แต่สำหรับโค้ดที่ดี หนังสือแนวประชดประชันอย่างวิธีเขียนโค้ดให้บำรุงรักษายาก น่าจะซึมซับเข้าใจได้มากกว่าหนังสือประเภทที่บอกว่าอันนี้ดีครับ
ช่วงนี้ดูเหมือนว่าจะทะเลาะกันมากกว่าเพราะคนที่เป็นแฟนของเทคสแตกหรือสถาปัตยกรรมบางแบบ มักพูดราวกับว่าถ้าไม่เอาเทคสแตกหรือสถาปัตยกรรมนั้นมาใช้จะเกิดเรื่องใหญ่โต ทั้งที่จริงก็ควรเลือกใช้ให้เหมาะกับสถานการณ์ และคงไม่มีอะไรที่ดีเสมอไปแบบไม่มีเงื่อนไข
เป็นการถกเถียงที่ยอดเยี่ยมครับ
คิดดูแล้ว ผมเองก็แนะนำ
philosophy of sw designของ John ให้กับรุ่นน้องอยู่เหมือนกัน แต่ไม่ได้แนะนำclean codeเป็นพิเศษเลยดูเหมือนว่าสิ่งสำคัญคือไม่ยึดติดกับแค่พาดหัวอย่างไร้การไตร่ตรอง แต่ต้องเข้าใจบริบทให้ดีและนำไปใช้ให้เหมาะสม
ผมคิดว่าหนังสือพัฒนาตัวเองด้านการเขียนโค้ดนั้นเหมาะกับผู้เริ่มต้นที่ยังไม่มีมุมมองเรื่องเทคนิคหรือวิธีการพัฒนาอยู่บ้าง แต่ยิ่งมีประสบการณ์มากขึ้น ประโยชน์ที่ได้รับก็จะยิ่งลดลง เพราะไม่มีความจริงแบบสัมบูรณ์ที่ใช้ได้กับทุกโปรเจกต์และทุกสภาพแวดล้อม และก็มีสถานการณ์ที่หลักการทั่วไปใช้ไม่ได้ด้วย เช่นเดียวกับคำแนะนำจากหนังสือพัฒนาตัวเองในสาขาทั่วไปอื่น ๆ ดูเหมือนว่าจะดีกว่าหากเว้นระยะกับมันพอสมควร เลือกใช้เฉพาะคำแนะนำที่เหมาะกับสถานการณ์ และไม่ไล่ตามคำแนะนำเหล่านั้นแบบมืดบอด
ผมเห็นด้วยกับที่ John พูดมากกว่าเล็กน้อย
ประเด็นสำคัญน่าจะอยู่ที่เราไม่ควรทำตามคำพูดของทั้งสองคนแบบยึดติดเป็นหลักตายตัว แต่ควรทำความเข้าใจว่าเพราะอะไรจึงเป็นเช่นนั้น แล้วค่อยก้าวต่อไป
อย่าลืมว่า Clean Code ไม่ใช่เป้าหมาย แต่เป็นเครื่องมือ
อย่างที่คิดเลยว่า ความพอดีนั้นสำคัญ
มีประโยชน์มาก 👍🏻
ความเห็นจาก Hacker News
บางคนอาจเคร่งครัดกับบางเรื่องมากเกินไป และฉันไม่เข้าใจว่าทำไมถึงรับสิ่งเหล่านี้เหมือนเป็นคำสอนศักดิ์สิทธิ์
ถ้าเคยเจอโครงการที่ทำตามคำแนะนำของ Uncle Bob แบบไม่ลืมหูลืมตา ก็จะรู้ว่ามันมีคุณค่าต่ำแค่ไหน
Clean Code เป็นเพียงหนึ่งในเครื่องมือในกล่องเครื่องมือของวิศวกรซอฟต์แวร์ที่ดี
บางคน "รีแฟกเตอร์" แค่ด้วยการจับบรรทัดที่อยู่ใกล้กันมามัดรวมกัน แทนที่จะแยกฟังก์ชันเมื่อมันนำกลับมาใช้ซ้ำได้หรือมีความหมายเชิงตรรกะ
มีกรณีสำคัญที่ไม่ได้พูดถึงเรื่องความสำคัญของคอมเมนต์
ขอแนะนำ "A Philosophy of Software Design" อย่างมาก
มันเป็นปฏิกิริยาต่อปัญหาจริงของอุตสาหกรรมซอฟต์แวร์ก่อนยุคขบวนการ Clean Code
ความเห็นของ Bob เกี่ยวกับคอมเมนต์นั้นแปลก
หนังสือของ Uncle Bob เป็นสิ่งที่เมื่อเวลาผ่านไปแล้วจะก้าวข้ามมันไปได้
มีข้อไม่พอใจเกี่ยวกับชื่อ Clean Code