5 คะแนน โดย GN⁺ 2025-06-18 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ความซับซ้อน คือองค์ประกอบที่อันตรายที่สุดในการพัฒนา
  • ประสิทธิภาพ ที่แท้จริงมาจากแนวทางเชิงปฏิบัติที่หลีกเลี่ยงความซับซ้อน เช่น "ทางออกแบบ 80/20"
  • การรักษาท่าทีที่สมดุลและยืดหยุ่นต่อ การทดสอบและการรีแฟกเตอร์ เป็นสิ่งสำคัญ
  • เน้นการ ใช้เครื่องมือ และการสร้างนิสัยในการเขียนโค้ดที่อ่านง่ายและดูแลรักษาง่าย
  • เตือนให้ระวัง การทำ abstraction มากเกินไป และการไล่ตามกระแส พร้อมแนะนำให้ยึดความเรียบง่าย

บทนำ

  • บทความนี้เป็นการรวบรวมความคิดของนักพัฒนา Grug Brain ที่สรุป สิ่งที่เรียนรู้จากประสบการณ์ ตลอดช่วงเวลายาวนานในการพัฒนาซอฟต์แวร์
  • นักพัฒนา Grug Brain คิดว่าตัวเองไม่ได้ฉลาดนัก แต่ได้เรียนรู้อะไรมากมายจากการเขียนโปรแกรมมาเป็นเวลานาน
  • เขาแบ่งปันข้อคิดใน รูปแบบที่เข้าใจง่ายและชวนขำ โดยหวังให้คนอื่นได้เรียนรู้จากความผิดพลาด
  • ความซับซ้อน นี่เองคือศัตรูตัวฉกาจที่สุดของชีวิตนักพัฒนา
  • ความซับซ้อนค่อย ๆ แทรกซึมเข้าไปใน codebase อย่างเงียบ ๆ จนทำให้โค้ดที่เคยเข้าใจง่ายในตอนแรก ค่อย ๆ กลายเป็นสิ่งที่แก้ไขไม่ได้

รับมือกับปีศาจแห่งความซับซ้อน

  • ความซับซ้อนแทรกซึมเข้ามาอย่างเงียบเชียบราวกับ วิญญาณที่มองไม่เห็น และบ่อยครั้งผู้จัดการโปรเจกต์รวมถึงนักพัฒนาที่ไม่ใช่ Grug ก็มักไม่ทันสังเกต
  • วิธีที่ดีที่สุดในการป้องกันความซับซ้อนคือการพูดว่า "ไม่"
    • "จะไม่สร้างฟีเจอร์นี้"
    • "จะไม่เพิ่ม abstraction นี้"
    • แน่นอนว่าในแง่อาชีพ การตะโกนว่า "ได้" อาจให้ผลดีกว่า แต่นักพัฒนา Grug Brain ให้ความสำคัญกับการเลือกอย่างซื่อสัตย์ต่อตัวเอง
  • บางครั้งก็ต้องประนีประนอมตามเงื่อนไข ("ok") และในกรณีแบบนี้จะชอบแก้ปัญหาอย่างเรียบง่ายด้วยแนวทาง 80/20 (ใช้กฎของ Pareto)
  • การไม่บอกผู้จัดการโปรเจกต์ทุกอย่าง และลงมือทำจริงด้วยวิธี 80/20 ก็เป็นกลยุทธ์ที่ฉลาดเช่นกัน

โครงสร้างโค้ดและ abstraction

  • หน่วยที่เหมาะสมของโค้ด (cut point) จะค่อย ๆ ปรากฏขึ้นเองตามเวลา ดังนั้นจึงควรหลีกเลี่ยง abstraction ตั้งแต่ช่วงต้น
  • cut point ที่ดีควรมี interface กับส่วนที่เหลือของระบบให้แคบที่สุด
  • ความพยายามทำ abstraction เร็วเกินไปมักล้มเหลว และนักพัฒนาที่มีประสบการณ์จะค่อย ๆ จัดโครงสร้างเมื่อรูปทรงของโค้ดเริ่มนิ่งแล้ว
  • นักพัฒนาที่ประสบการณ์น้อยหรือเป็นพวก “big brain” มักพยายามทำ abstraction มากเกินไปในช่วงต้นโปรเจกต์ และทิ้งภาระการดูแลรักษาไว้เบื้องหลัง

กลยุทธ์การทดสอบ

  • ความหมกมุ่นกับ การทดสอบ ต้องมีความสมดุล
  • เขาชอบเขียนเทสต์หลังจากทำต้นแบบเสร็จและเมื่อโค้ดเริ่มคงที่ในระดับหนึ่งแล้ว
  • แม้จะใช้ unit test ในช่วงต้น แต่ในทางปฏิบัติแล้วการทดสอบระดับกลาง (integration test) ให้ผลดีที่สุด
  • การทดสอบแบบ end-to-end ก็จำเป็น แต่ถ้ามีมากเกินไปจะดูแลรักษาไม่ได้ จึงควรมีเฉพาะเส้นทางสำคัญเท่าที่จำเป็น
  • เมื่อมี bug report ต้องเพิ่มเทสต์ที่ทำให้เกิดซ้ำได้ก่อน แล้วค่อยแก้บั๊ก

กระบวนการ, Agile, การรีแฟกเตอร์

  • Agile ไม่ได้แย่สำหรับนักพัฒนา Grug และก็ไม่ใช่สิ่งที่เลวร้ายที่สุด แต่การคาดหวังมากเกินไปจาก “Agile shaman” เป็นเรื่องอันตราย
  • การทำต้นแบบ เครื่องมือ และเพื่อนร่วมทีมที่ดี เป็นปัจจัยความสำเร็จที่สำคัญกว่าจริง ๆ
  • การรีแฟกเตอร์ก็เป็นนิสัยที่ดี แต่การรีแฟกเตอร์ครั้งใหญ่แบบฝืนเกินไปมีความเสี่ยง
  • การยัด abstraction ที่ซับซ้อนเข้ามาอย่างฝืน ๆ กลับทำให้โปรเจกต์ล้มเหลวได้ง่ายกว่า

การดูแลรักษา, ความสมบูรณ์แบบนิยม และความถ่อมตัว

  • การรื้อระบบเดิมโดยไม่มีเหตุผลเป็นเรื่องอันตราย และการลบ “โครงสร้างที่ไม่รู้ว่ามีไว้ทำไม” แบบไม่คิดหน้าคิดหลัง ก็ไม่ใช่นิสัยที่ดี
  • อุดมคตินิยมที่ฝันถึงโค้ดสมบูรณ์แบบ มักก่อปัญหาในโลกจริงเสียเป็นส่วนใหญ่
  • ยิ่งมีประสบการณ์มากขึ้น ก็ยิ่งสัมผัสได้ด้วยตัวเองว่า “โค้ดที่ทำงานได้ควรได้รับความเคารพ”

เครื่องมือและประสิทธิภาพการทำงาน

  • เครื่องมือพัฒนา ที่ดี (เช่น IDE autocomplete, debugger) ช่วยเพิ่มประสิทธิภาพได้มาก และควรทำความเข้าใจให้ลึก
  • เน้นว่าคุณค่าที่แท้จริงของ type system อยู่ที่ “autocomplete” และการป้องกันความผิดพลาด ส่วน abstraction และ generic ที่มากเกินไปกลับเป็นอันตราย

สไตล์โค้ดและการทำซ้ำ

  • แนะนำสไตล์อย่างการแยก conditional ออกเป็นหลายบรรทัด เพื่อให้โค้ดอ่านง่ายและดีบักง่ายขึ้น
  • แม้จะเคารพหลักการ DRY(Don’t Repeat Yourself) แต่ก็เน้นว่าความสมดุลสำคัญกว่าการพยายามกำจัดโค้ดซ้ำแบบฝืน ๆ
  • หลายครั้งการทำซ้ำแบบเรียบง่ายก็ดีกว่าการทำ DRY ที่ซับซ้อน

หลักการออกแบบซอฟต์แวร์

  • เขาชอบ locality of behavior มากกว่าหลัก SoC(Separation of Concerns) โดยมองว่า "ถ้าโค้ดที่ทำพฤติกรรมนั้นอยู่ใน object นั้นเลย จะดูแลรักษาง่ายกว่า"
  • เตือนว่าควรใช้ callback/closure, type system, generic, abstraction และสิ่งคล้ายกันอย่างพอประมาณ
  • การใช้ closure มากเกินไปอาจสร้าง "callback hell" ใน JavaScript ได้

การทำ logging, การปฏิบัติการระบบ

  • logging สำคัญมาก ควรบันทึกไว้ในทุกจุดแตกแขนงสำคัญ และในสภาพแวดล้อม cloud ควรออกแบบให้ติดตามได้ด้วยสิ่งอย่าง request ID
  • หากใช้ระดับ log แบบปรับได้ระหว่างรัน และ log แยกตามผู้ใช้ได้ ก็จะช่วยมากในการตามรอยปัญหาระหว่างปฏิบัติการจริง

Concurrency, การปรับแต่งประสิทธิภาพ

  • concurrency ควรเชื่อถือเฉพาะโมเดลที่เรียบง่ายที่สุดเท่านั้น (เช่น stateless web request, worker queue ที่แยกออกจากกัน)
  • ควรทำ optimization จริงก็ต่อเมื่อมีข้อมูลจาก performance profile จริงแล้วเท่านั้น
  • ต้องระวังค่าใช้จ่ายแฝงอย่าง network I/O และการมองแค่ความซับซ้อนของ CPU อย่างเดียวเป็นเรื่องอันตราย

การออกแบบ API

  • API ที่ดีต้องใช้งานง่าย และการออกแบบหรือ abstraction ที่ซับซ้อนเกินไปจะทำลายประสบการณ์ของนักพัฒนา
  • แนะนำโครงสร้างแบบ "API เรียบง่ายที่เหมาะกับ use case" ควบคู่กับ "API แบบเป็นชั้นที่รองรับเคสซับซ้อนได้"

การพัฒนา parser

  • recursive descent parser อาจถูกประเมินค่าต่ำไปในแวดวงวิชาการ แต่เป็นวิธีที่เหมาะกับ production code มากที่สุดและเข้าใจง่ายที่สุด
  • จากประสบการณ์การพัฒนา parser ส่วนใหญ่ parser ที่สร้างจาก tool มักให้ผลลัพธ์ที่ซับซ้อนเกินไป จนกลายเป็นผลเสียต่อการแก้ปัญหา
  • เขายก "Crafting Interpreters" เป็นหนังสือแนะนำอันดับหนึ่ง และบอกว่ามีคำแนะนำเชิงปฏิบัติมากมาย

Frontend และกระแส

  • frontend สมัยใหม่ (React, SPA, GraphQL ฯลฯ) กลับยิ่งเรียกปีศาจแห่งความซับซ้อนเข้ามาเพิ่ม และหลายครั้งก็ไม่จำเป็น
  • ตัว Grug เองชอบใช้เครื่องมือเรียบง่ายอย่าง htmx, hyperscript เพื่อลดความซับซ้อน
  • แม้ frontend จะมีความพยายามใหม่ ๆ เกิดขึ้นไม่หยุด แต่ก็ควรตระหนักว่าหลายอย่างเป็นเพียงการวนซ้ำของแนวคิดเดิม

ปัจจัยทางจิตวิทยา, imposter syndrome

  • นักพัฒนาส่วนใหญ่มักรู้สึกว่า “ฉันไม่รู้ว่ากำลังทำอะไรอยู่” อยู่บ่อยครั้ง และควรหลุดพ้นจากปรากฏการณ์ FOLD(Fear Of Looking Dumb)
  • ถ้านักพัฒนารุ่นพี่พูดอย่างเปิดเผยว่า “อันนี้ฉันก็ว่ายาก มันซับซ้อนเกินไป” นักพัฒนารุ่นน้องก็จะวางภาระทางใจลงได้
  • imposter syndrome เป็นความรู้สึกที่พบได้ทั่วไป และบทความนี้ให้กำลังใจว่าทุกคนสามารถเรียนรู้และเติบโตไปได้ทีละขั้น

บทสรุป

  • ในการเขียนโปรแกรม ความซับซ้อนคือสิ่งที่ต้องระวังอยู่เสมอ และการรักษาความเรียบง่ายคือหัวใจของการพัฒนาที่ประสบความสำเร็จ
  • ประสบการณ์ การใช้เครื่องมืออย่างมีประสิทธิภาพ ความถ่อมตัว และการเคารพโค้ดที่ใช้งานได้จริง จะนำไปสู่การพัฒนาที่มีประสิทธิผลและมีคุณค่าในระยะยาว
  • "ความซับซ้อนแย่มาก แย่มากจริง ๆ" — ควรจำประโยคนี้ไว้เสมอ

1 ความคิดเห็น

 
GN⁺ 2025-06-18
ความคิดเห็นจาก Hacker News
  • ฉันให้คุณค่ากับดีบักเกอร์สูงมากจนประเมินค่าไม่ได้ และยิ่งใช้ก็ยิ่งรู้สึกว่ามันยอดเยี่ยมกว่านั้นอีก ไม่ว่าจะเป็นสตาร์ตอัปเล็ก ๆ หรือทีมบิ๊กเทคชื่อดัง หลายครั้งฉันเป็นคนเดียวในทีมที่ใช้ดีบักเกอร์ ฉันเห็นความจริงว่าหลายคนยังคงดีบักด้วยคำสั่ง print อยู่เสมอ พอพยายามบอก workflow ของฉันให้เพื่อนร่วมงานฟังก็มักไม่ค่อยมีใครสนใจ ฉันเห็นด้วยว่าจุดเริ่มต้นที่ดีที่สุดในการทำความเข้าใจระบบก็คือดีบักเกอร์นี่แหละ การหยุดที่บรรทัดโค้ดที่น่าสนใจระหว่างรันทดสอบแล้วดู stack นั้นง่ายกว่าการไล่โค้ดในหัวมาก ถ้าเรียนรู้วิธีใช้ดีบักเกอร์ไว้ มันเหมือนได้พลังพิเศษเล็ก ๆ จริง ๆ ถ้ามีโอกาสอยากแนะนำให้ลองใช้ดูสักครั้ง
    • ฉันเองก็อยากใช้ดีบักเกอร์จริง ๆ แต่ในฐานะคนที่ทำงานมาแต่ในบริษัทใหญ่ สภาพความเป็นจริงคือแทบเป็นไปไม่ได้ ในสถาปัตยกรรม microservice mesh มันรันอะไรบนเครื่อง local ไม่ได้เลย และแม้แต่ในสภาพแวดล้อมทดสอบ ส่วนใหญ่ก็ตั้งค่าไม่ให้ต่อ step debugger ได้ ดังนั้นการดีบักด้วย print จึงเป็นทางเลือกเดียวที่ทำได้ ถ้ายิ่งระบบ log มีปัญหา หรือโปรแกรม crash ไปก่อนจะพิมพ์ log ออกมาได้ ก็จะอยู่ในสถานการณ์ที่แม้แต่ print ก็ใช้ไม่ได้
    • มีการถกเถียงที่ดีเกี่ยวกับเรื่องนี้เมื่อหลายปีก่อน มีคำพูดดังของ Brian Kernighan กับ Rob Pike ซึ่งทั้งคู่ก็ไม่ใช่นักพัฒนารุ่นเยาว์แล้ว: "เราไม่ได้ใช้ดีบักเกอร์เพื่อจุดประสงค์อื่นนอกจากดู stack trace หรือเช็กค่าตัวแปรไม่กี่ตัว โครงสร้างข้อมูลและ control flow ที่ซับซ้อนทำให้ติดอยู่กับรายละเอียดได้ง่าย การคิดกับโปรแกรมในหัวให้มากขึ้น แล้วคั่นด้วยการพิมพ์ output และใส่ self-checking code เป็นระยะ ๆ นั้นให้ผลมากกว่า การใส่ print เร็วกว่าการไล่ทีละ step ด้วยดีบักเกอร์มาก อีกอย่าง โค้ด print ยังอยู่ในโปรแกรม แต่ debugging session หายไป" ฉันก็เห็นด้วยกับความเห็นนี้ ในกระบวนการพัฒนาส่วนใหญ่ วงจร print-ตั้งสมมติฐาน-รัน ให้การแก้ปัญหาที่เร็วกว่า ไม่ใช่ว่าฉัน "ลองรัน" โค้ดในหัว แต่เป็นเพราะมีโมเดลการทำงานของ flow โค้ดอยู่แล้ว พอ print แสดง output ที่ผิด ส่วนใหญ่ก็พอจะจับความจริงได้อย่างรวดเร็ว ลิงก์ที่เกี่ยวข้อง: The unreasonable effectiveness of print debugging
    • เหตุผลที่ printf debugging เป็นเรื่องปกติในสาย Linux มาโดยตลอด ก็เพราะสภาพแวดล้อมที่เชื่อถือ GUI debugger ไม่ได้ GUI บน Linux มักไม่เสถียรจนไว้ใจไม่ได้ สำหรับฉัน จุดที่เริ่มใช้ดีบักเกอร์อย่างจริงจังคือเมื่อ (1) บน Windows GUI ใช้งานได้ดี แต่ CLI พังบ่อย และ (2) เคยปล่อยโค้ดสำหรับ print debugging ติดเข้าเวอร์ชันจริงโดยไม่ได้ตั้งใจจนเกิดปัญหาหลายครั้ง หลังจากนั้นก็ผจญภัยกับ CLI debugger อยู่พักหนึ่ง และรู้สึกว่ากระบวนการใช้ Junit+debugger (ผ่าน IDE อย่าง Eclipse) เพื่อทดลองเขียนโค้ดแล้วเก็บไว้เป็น test นั้นสะดวกพอ ๆ กับ Python REPL เลยทีเดียว เพียงแต่ต้องลงทุนตั้งค่าดีบักเกอร์ให้เข้ากับสภาพแวดล้อมก่อนในช่วงแรก
    • ในโค้ดของฉันเอง การใช้ดีบักเกอร์นั้นง่ายและฉันชอบมากจริง ๆ แต่พอดีบักเกอร์พาฉันลึกเข้าไปในไลบรารีหรือเฟรมเวิร์กมากกว่าโค้ดที่ฉันเขียนเอง ฉันก็หลงทางและเริ่มไม่ชอบมันทันที เฟรมเวิร์ก/ไลบรารีพวกนี้ถูกสร้างขึ้นด้วยเวลาหลายแสนชั่วโมง ดังนั้นสำหรับระดับของฉัน มันเกินขอบเขตความเข้าใจไปอย่างรวดเร็ว
  • ถ้าอาจารย์ Carson มาเห็นโพสต์นี้เข้า ผมอยากขอบคุณจากใจจริง ตอนอยู่มหาวิทยาลัยผมไม่เข้าใจว่าทำไมต้องเรียน HTMX และทำไมอาจารย์ถึงทุ่มเทกับมันมากขนาดนั้น แต่ไม่กี่ปีให้หลังผมก็เข้าใจอย่างแท้จริง HTML over the wire คือทุกสิ่งจริง ๆ ตอนนี้ผมทำงานเป็น Staff Ruby on Rails Engineer และเคยเห็นงานของอาจารย์ใน Hotwire หลายครั้ง พอเห็นอาจารย์โผล่บน GitHub หรือ Hacker News บ้างเป็นครั้งคราวก็ยังรู้สึกทึ่งเสมอ อาจารย์เป็นเหมือนแสงสว่างของชุมชนโปรแกรมเมอร์เสมอมา ขอแสดงความเคารพและขอบคุณอย่างสูง
    • ไม่ใช่มีแค่ฉันที่ซึ้งนะ นี่มันกินใจจริง ๆ
    • HTMX ไม่ใช่แค่มีมเหรอ? ด้วย Poe’s Law เลยไม่แน่ใจว่านี่พูดจริงหรือเปล่า
  • บทความนี้มีประโยคคม ๆ เยอะมาก แต่ฉันชอบประโยคเรื่อง microservice ที่สุด: "grug ไม่เข้าใจว่าทำไม big brain ถึงแยกระบบให้ถูกต้องยังยากอยู่แล้ว แต่ยังอยากเพิ่ม network call เข้าไปอีก"
    • บางคนรู้จักวิธีแยกระบบออกเป็นส่วน ๆ แค่แบบเดียวคือทำเป็น API ถ้าไม่ได้เปิดออกมาเป็น API ก็จะมองว่าเป็นโค้ดทึบแสงที่ทั้งเข้าใจไม่ได้และเอากลับมาใช้ซ้ำไม่ได้
    • ก็น่าเสียดายที่ microservice ถูกใช้งานเพราะในหลายกรณีมันก็ใช้ได้จริงในเชิงปฏิบัติ
    • ฉันเห็นอยู่เรื่อย ๆ ว่าแม้แต่เว็บแอปเล็ก ๆ ที่มีฟอร์มแค่ห้าอัน ทีมพัฒนาขนาดสองคนก็ยังทำให้มันซับซ้อนเป็นโครงสร้าง “microservice” (แชร์ฐานข้อมูล, จัดการ API, งาน batch ผ่านคิว, แจ้งเตือนอีเมล, เพิ่มแพลตฟอร์ม Observability ของตัวเอง ฯลฯ) แล้วสุดท้ายยังทำฟอร์มธรรมดาให้เป็น SPA ด้วย โดยบอกว่า ‘เพราะมันง่ายกว่า’ ตอนนี้ฉันเข้าใจแล้วว่า “architecture” และ “pattern” เป็นเพียงงานสร้างงานให้กับนักพัฒนาที่ไร้ประโยชน์ ถ้าไม่มีสิ่งเหล่านี้ พวกเขาคงยืนถือป้ายอยู่ข้างถนนว่า “ขอแซนด์วิชชิ้นหนึ่งก็พอ ผมจะเขียน JavaScript ให้”
    • ทฤษฎีสมคบคิดส่วนตัวของฉันคือ รูปแบบ microservice ถูก cloud vendor ผลักดันจนกลายเป็นแบบนี้ - ทำให้รันแทบไม่ได้เลยถ้าไม่มี orchestrator อย่าง K8S และนั่นก็ขาย managed cloud ได้ง่ายขึ้น - มี network traffic/การใช้ CPU มากขึ้น ก็เก็บเงินได้มากขึ้น - การแชร์ state ขนาดใหญ่ทำได้ยาก จึงต้องพึ่ง managed database/event queue - การรันบนเครื่อง local ยากขึ้น จนค่าใช้จ่ายลามไปถึงสภาพแวดล้อมพัฒนา - ผูกติดกับแนวทางเฉพาะของคลาวด์จนย้ายออกได้ยาก สมัยก่อนคลาวด์โฆษณาว่าจะช่วยลดค่าใช้จ่ายด้าน IT ซึ่งตลกมาก เรารู้กันมาตั้งแต่ยุค 2000 แล้วว่านั่นเป็นภาพลวงตา และสุดท้ายก็มีแต่แพงขึ้นทั้งหมด
  • ประโยค "ระหว่างความซับซ้อนกับการเผชิญหน้าตัวต่อตัวกับไทรันโนซอรัส grug เลือกไทรันโนซอรัส: อย่างน้อยไทรันโนซอรัสก็มองเห็นได้" ติดหัวฉันจนคิดถึงมันอย่างน้อยสัปดาห์ละครั้ง
    • คำคม: "แม้จะล้มลง Leyster ก็ยังไม่ปล่อยพลั่ว เขาลืมไปเสียสนิทท่ามกลางความแตกตื่น ดังนั้นเขาจึงกำพลั่วไว้แน่นแล้วเหวี่ยงใส่ขาของลูกไทรันโนซอรัสอย่างสุดแรง..." เป็นฉากที่บรรยายการต่อสู้เอาชีวิตรอดกับไทรันโนซอรัสได้อย่างสมจริงมาก สุดท้ายเพื่อนร่วมทางชื่อ Tamara ก็เสียบหอกเข้าไปกลางหน้าไทรันโนซอรัสอย่างกล้าหาญจนผ่านวิกฤตมาได้ เป็นช่วงเวลาที่ทั้งการต่อสู้ ความตึงเครียด และความเงียบหลังจากนั้นน่าประทับใจมาก
    • grug คงไม่เคยสู้กับไทรันโนซอรัสที่ ‘มองไม่เห็น’ แน่ ๆ ตอนนี้ฉันกำลังดวลตัวต่อตัวกับไทรันโนซอรัสล่องหนอยู่เหมือนกัน เหนื่อยมากจริง ๆ
  • สิ่งที่น่าทึ่งในบทความนี้คือ ผู้เขียน “ทำสิ่งที่ซับซ้อนกว่านี้ได้” แต่จากประสบการณ์กลับเลือกไม่เดินเส้นทางนั้น แน่นอนว่ามีเวลาและสถานที่ที่ abstraction หรือความซับซ้อนจำเป็น แต่ปรัชญาแบบ grug บอกว่าสิ่งเหล่านั้นไม่มีคุณค่าโดยเนื้อแท้ในตัวเอง ฉันคิดว่าจุดนี้มีเหตุผลมาก AI เองก็ดูจะทำงานได้ดีกว่ากับโค้ดที่สม่ำเสมอและอิงข้อมูล
    • เวลาใช้ความซับซ้อนและ abstraction ก็ควรเป็นตอนที่มันทำให้โค้ดเข้าใจง่ายกว่าเดิม อย่าลืมเงื่อนไขว่า ‘ต้องไม่ต้องมีคอร์สเสริมพิเศษเพื่อทำความเข้าใจมัน’ (แล้วแต่บริบท)
    • "ทุกสิ่งควรถูกทำให้เรียบง่ายที่สุดเท่าที่จะเป็นไปได้ แต่ไม่ใช่เรียบง่ายเกินไป"
  • ยากจะเชื่อว่าบทความนี้เขียนในปี 2022 รู้สึกเหมือนอ่านมันมาแล้วตั้งสิบปีก่อน และคิดว่ามันเป็น ‘งานคลาสสิก’ ไปแล้ว
  • นี่คือเอสเสย์เกี่ยวกับการสร้างซอฟต์แวร์ที่ฉันชอบที่สุด สไตล์การเขียนก็มีเสน่ห์มากด้วย (แม้บางคนอาจรู้สึกไม่ชอบ) แต่แก่นของมันยังใช้ได้เสมอ
  • โค้ดส่วนที่ว่า "น่าเศร้าแต่เป็นความจริง: เรียนรู้ที่จะพูด 'yes' แล้วถ้าล้มเหลวก็เรียนรู้ที่จะโทษ grug คนอื่น นี่คือกลยุทธ์สร้างอาชีพที่ดีที่สุด" คือความจริงสุด ๆ ตอนแรกฉันก็เข้าใจผิดว่าในบริษัทของฉันปัญหาเป็นแค่เรื่องการสื่อสารในทีมเทคนิค แต่พอเวลาผ่านไปฉันก็ได้เรียนรู้ว่า (แบบ grug) ที่จริงมันเป็นแบบนั้นจริง ๆ
  • นี่เป็นคำอธิบายเรื่อง visitor pattern ที่ดีที่สุดเท่าที่ฉันเคยเห็นมาในบทความไหนก็ตาม
    • ฉันไม่ได้ทำงานกับ codebase แบบ OO ทั่วไป เลยไม่ค่อยรู้จริง ๆ ว่า visitor pattern คืออะไร แต่อยากแนะนำหนังสือสร้าง interpreter/VM ชื่อ "Crafting Interpreters" ในหนังสือเล่มนั้นมีตัวอย่างการใช้ visitor pattern จริง ๆ ฉันพยายามอ่านเพื่อทำความเข้าใจว่าทำไมมันถึงซับซ้อน สุดท้ายกลับแทนที่มันด้วย tagged union แทน อาจเป็นเพราะฉันไม่ถนัด OO ก็ได้ แต่แก่นของบทความ grug ก็ประมาณนี้แหละ คือถ้าไม่จำเป็นต้องเลือกความซับซ้อนและความอ้อมค้อม ก็ยังมีวิธีที่ตรงไปตรงมากว่า
    • ฉันค่อนข้างจริงจังกับเรื่องการตั้งชื่อ และไม่ชอบที่ชื่อ visitor pattern มันคลุมเครือเกินไป ฉันไม่เคยตั้งชื่ออะไรว่า Visitor จริง ๆ เลย ตัวอย่างเช่น ถ้าเป็นการฝึกกับ syntax tree (AST) ชื่ออย่าง AstWalker, AstItem::dispatch(AstWalker), AstWalker::process(AstItem) จะสื่อความหมายกว่ามาก คำว่า visitor ที่แปลว่า “เข้าไปเยี่ยม” มันนามธรรมและไม่มีความหมายเกินไป มันขึ้นอยู่กับบริบท และถ้าจะให้คนรู้จัก pattern ก็แค่เขียนคอมเมนต์ว่าเป็น ‘visitor pattern’ ก็พอแล้ว สมัยก่อนตอนต้องจับคู่ object tree สองชุดเพื่อเทียบ/นำเข้าข้อมูล ฉันเคยใช้ชื่อว่า AbstractImporter ซึ่งเฉพาะเจาะจงกว่า เห็นกระบวนการและบทบาทชัดกว่า และก็ไม่เหมือน visitor pattern ทั่วไป
    • พอไปค้นดูจริง ๆ ก็เจอคนให้ความเห็นว่า “Bad” ฮ่า ๆ
  • ขอแชร์โพสต์ที่เกี่ยวข้อง มีใครมีความเห็นอื่นหรือมีบทความเพิ่มเติมไหม?<br/><i>The Grug Brained Developer (2022)</i> - https://news.ycombinator.com/item?id=38076886 - ตุลาคม 2023 (192 ความเห็น)<br/><i>The Grug Brained Developer</i> - https://news.ycombinator.com/item?id=31840331 - มิถุนายน 2022 (374 ความเห็น)