17 คะแนน โดย GN⁺ 2025-12-31 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • เมื่อ AI เอเจนต์เข้ามาเป็นศูนย์กลางของการเขียนโค้ด แนวปฏิบัติที่เคยเป็นเพียง ‘ตัวเลือก’ อย่างการทดสอบ การทำเอกสาร และ static typing จึงกลายเป็นองค์ประกอบที่ขาดไม่ได้
  • การครอบคลุมโค้ด 100% ถูกกำหนดเป็นข้อบังคับ เพื่อให้ทุกบรรทัดของโค้ดได้รับการตรวจสอบจริงและมีตัวอย่างการรันรองรับ
  • โครงสร้างไดเรกทอรีและการตั้งชื่อไฟล์ ต้องชัดเจน เพื่อให้ LLM สำรวจโค้ดเบสได้ง่าย และสนับสนุนการแยกไฟล์เป็นหน่วยเล็ก ๆ
  • สภาพแวดล้อมการพัฒนาที่รวดเร็ว ชั่วคราว และรองรับการทำงานพร้อมกัน ต้องถูกสร้างขึ้นเพื่อให้หลายเอเจนต์ทำงานแบบขนานได้
  • หัวใจสำคัญคือการรักษาระบบนิเวศของโค้ดที่ AI เชื่อถือได้ด้วย ระบบชนิดข้อมูลแบบสแตติกและเครื่องมือควบคุมคุณภาพอัตโนมัติ

AI กับความจำเป็นของ ‘โค้ดที่ดี’

  • เป็นเวลานานที่นักพัฒนามองว่า การทดสอบ การทำเอกสาร โมดูลขนาดเล็ก และ static typing เป็นเกณฑ์ของโค้ดที่ดี แต่ในความเป็นจริงมักถูกละไว้
  • แต่ AI เอเจนต์ไม่สามารถจัดระเบียบโค้ดได้ดีด้วยตัวเอง ดังนั้นแนวปฏิบัติเหล่านี้จึงจำเป็นอย่างยิ่ง
  • เพื่อไม่ให้เอเจนต์ทำงานไปในทิศทางที่ผิด จึงจำเป็นต้องมี การตั้ง guardrail ที่ชัดเจนและการบังคับใช้อย่างจริงจัง
  • หากมี guardrail ที่แข็งแรง LLM จะค่อย ๆ ลู่เข้าสู่เส้นทางที่ถูกต้องเท่านั้น แต่ในสภาพแวดล้อมที่ไม่สมบูรณ์ มันจะขยายปัญหาให้รุนแรงขึ้น

การครอบคลุมโค้ด 100%

  • ทีมงานกำหนดให้ การครอบคลุมโค้ด 100% เป็นข้อบังคับ ซึ่งไม่ใช่แค่เพื่อป้องกันบั๊ก แต่เพื่อ ยืนยันการทำงานของโค้ดทุกชิ้นที่เอเจนต์เขียนขึ้น
  • ที่ระดับ 95% หรือ 99.99% จะยังไม่ชัดเจนว่าโค้ดที่ไม่ถูกทดสอบมาจากไหน แต่ที่ 100% จะสามารถ ระบุทุกบรรทัดที่ยังไม่ได้รับการตรวจสอบได้อย่างชัดเจน
  • รายงานการครอบคลุมถูกใช้เป็นรายการงานที่ต้องทดสอบ และ เมื่อ LLM แก้ไขโค้ด จะต้องแสดงตัวอย่างที่รันได้จริงเสมอ
  • แนวทางนี้ยังให้ผลพลอยได้ เช่น การลบโค้ดที่ไม่มีทางถูกเรียกใช้ การระบุ edge case อย่างชัดเจน และการเพิ่มประสิทธิภาพของ code review

เนมสเปซและโครงสร้างไฟล์

  • เอเจนต์ สำรวจโค้ดเบสผ่านระบบไฟล์ ดังนั้นโครงสร้างไดเรกทอรีและชื่อไฟล์จึงทำหน้าที่เป็นอินเทอร์เฟซที่สำคัญ
  • เส้นทางที่ชัดเจนอย่าง ./billing/invoices/compute.ts ส่งข้อมูลได้มากกว่า ./utils/helpers.ts อย่างมาก
  • ควรใช้ ไฟล์ขนาดเล็กที่กำหนดขอบเขตไว้อย่างชัดเจน เพราะช่วยให้ LLM โหลดทั้งไฟล์เข้าเป็นบริบทได้ และ ป้องกันประสิทธิภาพตกลง
  • การจัดโครงสร้างแบบนี้นำไปสู่ การเพิ่มความเร็วและความแม่นยำในการสำรวจของเอเจนต์

สภาพแวดล้อมการพัฒนาที่รวดเร็ว ชั่วคราว และรองรับการทำงานพร้อมกัน

  • จากเดิมที่ใช้สภาพแวดล้อมพัฒนาแบบเดี่ยว การพัฒนาแบบอิงเอเจนต์กำลังเปลี่ยนไปเป็น รูปแบบที่จัดการหลายโปรเซสแบบขนาน
  • Fast: ขั้นตอนการทดสอบและการตรวจสอบต้องรันได้อย่างรวดเร็ว โดยทีมได้ปรับแต่งให้ assertion มากกว่า 10,000 รายการ เสร็จภายใน 1 นาที
    • เพิ่มความเร็วด้วยการทำงานขนานระดับสูง การแยกสภาพแวดล้อมอย่างเข้มงวด และ เลเยอร์แคชสำหรับการเรียก third-party
  • Ephemeral: สร้างสภาพแวดล้อมใหม่ได้ภายใน 1~2 วินาที ด้วยคำสั่ง new-feature <name> พร้อมตั้งค่าอัตโนมัติและเริ่มให้เอเจนต์ทำงาน
    • หากยังต้องตั้งค่าด้วยมือ ความถี่ในการใช้งานจะลดลงอย่างมาก ดังนั้นการทำให้เป็นอัตโนมัติทั้งหมดจึงเป็นหัวใจสำคัญ
  • Concurrent: เพื่อให้รันหลายสภาพแวดล้อมพร้อมกันได้ จำเป็นต้องมี การตั้งค่าเพื่อป้องกันการชนกันของพอร์ต DB แคช ฯลฯ
    • อาจใช้ Docker หรือจัดการการแยกสภาพแวดล้อมด้วย environment variable

ระบบชนิดข้อมูลแบบ end-to-end และการควบคุมคุณภาพอัตโนมัติ

  • ทำ แนวปฏิบัติที่ดีให้เป็นอัตโนมัติให้มากที่สุด เพื่อลดอิสระของ LLM และรักษาคุณภาพให้สม่ำเสมอ
  • ตั้งค่า linter และ formatter อัตโนมัติ อย่างเข้มงวด เพื่อให้มีการแก้ไขอัตโนมัติทุกครั้งที่ LLM ทำงานเสร็จ
  • แนะนำให้ใช้ ภาษาแบบ static type โดยเฉพาะการใช้ระบบชนิดข้อมูลที่แข็งแรงของ TypeScript
    • ใช้ ชื่อชนิดข้อมูลที่มีความหมาย อย่าง UserId, WorkspaceSlug, SignedWebhookPayload เพื่อสื่อเจตนาของโค้ดให้ชัดเจน
  • ใช้ OpenAPI เพื่อรักษาความตรงกันของชนิดข้อมูลระหว่างฟรอนต์เอนด์และแบ็กเอนด์
  • ใช้ระบบชนิดข้อมูลและ trigger ของ Postgres เพื่อคงความถูกต้องของข้อมูล และสร้างไคลเอนต์ที่ปลอดภัยด้านชนิดข้อมูลด้วย Kysely
  • ไคลเอนต์ third-party ทั้งหมดก็ควรมี นิยามชนิดข้อมูลที่ถูกต้อง หรือถูกห่อใช้งานในรูปแบบที่เหมาะสม

บทสรุป: นิยามใหม่ของคุณภาพโค้ดในยุค AI

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

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

 
GN⁺ 2025-12-31
ความคิดเห็นจาก Hacker News
  • กับดัก ของการทำให้ได้ coverage 100% คือ ถ้าโค้ดกับเทสต์ถูกเขียนโดยเอเจนต์ตัวเดียวกัน ก็อาจตกอยู่ในภาวะ ตรวจสอบตัวเองแบบขัดแย้งกันเอง
    ถ้าเอเจนต์สร้างตรรกะที่ผิด แล้วก็เขียนเทสต์ที่ใช้ตรวจตรรกะผิดนั้นออกมาผิดเหมือนกัน เทสต์ก็จะผ่าน แต่โค้ดจริง ๆ ยังมีข้อผิดพลาดอยู่
    coverage แบบนี้จะมีความหมายก็ต่อเมื่อมีการเขียนเทสต์ก่อนโค้ด หรือมีมนุษย์ตรวจอย่างเข้มงวดเท่านั้น
    ไม่อย่างนั้นมันก็แค่สร้าง ความน่าเชื่อถือปลอม ๆ ขึ้นมา

    • ที่คุณพูดก็ถูก แต่ทางแก้ไม่ใช่แค่ “ให้คนทำ” หรือ “เขียนเทสต์ก่อนโค้ด”
      แก่นสำคัญคือให้ คนหลายคนที่มีวิธีคิดต่างกัน มาตรวจจุดบอดของกันและกัน
      ต่อให้มี AI หลายโมเดล สุดท้ายก็ควรมองว่าเป็น ‘จิตใจ’ เดียวกันอยู่ดี
      ให้คนเขียนเทสต์ให้โค้ดของ AI, ให้ AI เขียนเทสต์ให้โค้ดของคน หรือให้รีวิวโค้ดซึ่งกันและกัน จะดีกว่า
      แต่แม้ในหมู่มนุษย์เองก็ยังมีกรณีที่ความสัมพันธ์เชิงอำนาจทำให้สะท้อนออกมาแค่ความเห็นของคนเดียว และ AI ก็ไม่ได้ช่วยกันเรื่องนั้น
    • เพราะงั้นจึงต้องมี การทดสอบเทสต์อีกชั้นหนึ่ง
      ต้องใส่บั๊กเข้าไปโดยตั้งใจแล้วดูว่ามันล้มเหลวหรือไม่
      นี่ไม่ใช่ปัญหาเฉพาะของ AI มนุษย์ก็เหมือนกัน
      ถึงอย่างนั้น การที่ AI ทำให้นักพัฒนาจำนวนมากได้เรียนรู้ หลักวิศวกรรมที่ถูกต้อง ก็ถือเป็นเรื่องดี
    • ดูเหมือนว่าการเปลี่ยนแปลงจริง ๆ จะเกิดขึ้นไม่ใช่ที่ coverage 100% แต่เป็น MC/DC coverage 100%
      SQLite กับซอฟต์แวร์การบินก็ตั้งเป้าระดับนี้
      อย่างไรก็ตาม นี่ยังไม่ใช่สมมติฐานที่ผ่านการยืนยันทางวิชาการ
    • แม้แต่ unit test ที่คนเขียนเองก็มีปัญหาเดียวกัน
      เพราะงั้นจึงควรใช้ integration test หรือ UI automation test เพื่อตรวจสอบสถานการณ์การใช้งานจริงของผู้ใช้
      การใช้ข้อมูลจากสภาพแวดล้อม production หรือการทดสอบใน shadow environment ก็ช่วยได้เช่นกัน
    • เรามีแนวทางแก้ที่ดีบนฐานโค้ดอยู่แล้ว เช่น BDD หรือ Acceptance Test
      ก่อนยุค LLM การตั้งค่ามันยุ่งยาก แต่ตอนนี้ ROI ดีขึ้นแล้ว
      อย่างที่ Uncle Bob เน้นไว้ การลงทุนกับการจัดโครงสร้างเทสต์เป็นเรื่องสำคัญ
      LLM อาจเขียนเทสต์ที่ซ้ำ ๆ แต่ถ้าขอ มันก็ใช้ หลักการ DRY หรือแพตเทิร์น factory ได้ดีเหมือนกัน
  • นี่เป็นวิธีที่ผมเริ่มลองตั้งแต่เมื่อวาน คือเขียนสเปกด้วย TLA+/PlusCal ก่อน แล้วให้ Codex นำสเปกนั้นไป implement ตรง ๆ
    ผมสั่งให้ยึดตามสเปกอย่างเดียวโดยไม่ต้องสร้างสรรค์
    โค้ดที่ออกมา หน้าตาไม่สวยแต่ถูกต้อง, และเร็วกว่าการแปลด้วยตัวเองมาก
    แต่ถ้าการ optimize ยังไม่ดีพอหรือรกเกินไป ผมก็จะแก้บางส่วนเอง
    โดยเฉพาะตอนนี้กำลังลองกับ lock-free data structure แต่ Codex ยังชอบใส่ lock มาอยู่ เลยต้องคอยแก้เอง
    สุดท้ายผมก็โฟกัสกับตรรกะเชิงคณิตศาสตร์ ส่วน AI รับหน้าที่รายละเอียดการ implement
    นี่แหละคือเวิร์กโฟลว์ในอุดมคติแบบ “spec ก่อน โค้ดทีหลัง

    • ผมก็พัฒนาแบบคล้าย ๆ กัน
      เห็นด้วยกับ บทความของ Martin Kleppmann
    • ช่วงนี้ผมลองวนซ้ำกับ Haskell หรือ Prolog อยู่ และอยากให้มีกลุ่มที่ศึกษา LLM ควบคู่กับการทำ modeling/verification
    • ถ้าให้ LLM มีส่วนร่วมในการเขียนสเปกด้วย ประสิทธิภาพจะยิ่งสูงขึ้น
      ในโมเดลรุ่นใหม่ ๆ มันใช้ได้ผลจริง และ ความคุ้มค่าด้านต้นทุน ก็ดีขึ้น 10~100 เท่า
  • นี่ดูเหมือน ภาพหลอน หรือไม่ก็ สำนวนขายของ
    ถ้าบั๊กในระบบจริงกับภาระการบำรุงรักษายังบังคับให้เกิดโค้ดที่ดีไม่ได้ AI ก็ทำไม่ได้เหมือนกัน
    AI ระดับปัจจุบันกลับมีแนวโน้มจะทำให้โค้ดแย่ลงด้วยซ้ำ

    • สมมติฐานที่มีปัญหาคือ “ทุกคนรู้ว่าคือโค้ดที่ดี”
      แค่เรื่องความยาวของเมธอดก็ยังตกลงกันไม่ได้เลย ดังนั้นจึงไม่มี เกณฑ์คุณภาพสากล
      แม้แต่ตัวชี้วัดอย่าง test coverage ก็ปั่นแต่งได้ง่าย และถ้าใช้ผิดก็ยิ่งเป็นโทษ
    • test coverage ไม่ใช่ตัวแทนของโค้ดที่ดี
      โดยเฉพาะเมื่อ AI เป็นคนเขียนเทสต์ มันอาจสร้าง ความมั่นใจปลอม ๆ ได้
    • ผู้เขียนต้นฉบับเป็น CEO ของบริษัท AI เลยอาจมี อคติ ก็ได้ /s
  • ผมคิดว่าการพัฒนาซอฟต์แวร์อาจเป็น การประยุกต์ใช้ LLM ที่ใช้งานได้จริงเพียงด้านเดียว
    เพราะมันสร้าง feedback loop ได้เร็วกว่าแขนงอื่น
    วางแผนกับ LLM แล้วอีกไม่กี่ชั่วโมงก็รู้ว่าล้มเหลว จากนั้น LLM ก็จะบอกว่า “เพราะงั้นถึงทำแบบนั้นไม่ได้”
    มันคล้ายกับสร้างบ้านตามมาตรฐานไฟฟ้าแบบอเมริกัน แล้วค่อยไปพบปัญหาตอนติดตั้งเครื่องล้างจานมาตรฐานแคนาดา

    • เพราะเหตุนี้เอง วิศวกรรมสาขาอื่นจึงมี กฎเข้มงวดและระบบใบอนุญาต
      ซอฟต์แวร์ค่อนข้างปลอดภัยกว่าเลยมีการพัฒนาแบบนิรนามได้ แต่ตอนนี้กำลังเกิด วัฒนธรรมการลงนามรับผิดชอบ ขึ้นมา
      ต่อไปอาจมีแค่คนที่เขียน โค้ดความเสี่ยงสูงและมีนวัตกรรม เท่านั้นที่ได้ค่าตอบแทนสูง
    • แต่ผมไม่เข้าใจว่าทำไมประสบการณ์แบบนั้นถึงนำไปสู่ข้อสรุปว่า LLM มีประโยชน์
      AI ก็ยังคงปล่อย โค้ดเพี้ยน ๆ ออกมา เราก็ดีบัก แล้วมันก็ปล่อยของเพี้ยนใหม่ เป็น ลูปไม่รู้จบ เท่านั้นเอง
    • เครื่องล้างจานมาตรฐานแคนาดาก็ติดตั้งได้เหมือนกัน
      แค่ต้องให้ มาตรฐานกระแสไฟ ตรงกันก็ปลอดภัย
    • ถ้านึกถึง simulator หรือ digital twin ก็สร้าง feedback loop ได้โดยไม่ต้องลงมือสร้างของจริง
      ถึงอย่างนั้นผมก็ยังคิดว่าอย่างน้อย unit test ก็ช่วยยืนยันจุดเชื่อมกับโลกจริงได้
    • การบอกว่า “นอกจากซอฟต์แวร์แล้วไม่มีการใช้งานจริง” เป็นคำกล่าวที่ หยิ่งเกินไป
      ตอนนี้ผมกำลังใช้ LLM เพื่อเรียน วงจร RLC และ inerter
  • หลายคนตกใจกับการที่ LLM สร้างโค้ดได้เร็ว แต่ ความเร็วหรือปริมาณไม่ใช่คอขวดของคุณภาพ
    การปฏิวัติที่แท้จริงจะเกิดขึ้นเมื่อ AI สร้าง โค้ดที่แม่นยำกว่ามนุษย์ ได้

    • เมื่อใช้ LLM วิศวกรจะยิ่งห่างจาก ความเข้าใจ implementation จริงของระบบ
      คุณค่าที่แท้จริงมาจากการ รู้ว่าโค้ดทำงานอย่างไร
      ในการประชุมที่วิศวกรคนอื่นกำลังเดากันอยู่ ช่วงเวลาที่มีคนหนึ่งเปิดโค้ดจริงให้ดูนั้นแหละมีค่าที่สุด
  • ‘โค้ดที่ดี’ อาจเป็นแค่โค้ดที่ถูกปรับให้เหมาะกับ working memory อันจำกัดของมนุษย์ ก็ได้
    แต่โมเดลสามารถมองเห็นบริบททั้งหมดพร้อมกัน จึงไม่มีข้อจำกัดแบบนั้น
    ถ้า context window ใหญ่ขึ้น 100 เท่า การถกเถียงแบบนี้อาจสำคัญน้อยลง

  • ผมกังวลว่าถ้าบังคับให้ LLM ทำ coverage 100% มันจะทำให้ สมมติฐานที่ผิดถูกตรึงแน่น
    แต่ถ้ายังมีการรีวิวโดยมนุษย์ ก็น่าจะพูดได้ว่า “อันนี้ผิด ลบเทสต์แล้วเขียนใหม่กันเถอะ” ใช่ไหม?

    • ใช่ เรายังให้ มนุษย์รีวิว test case อยู่
      LLM ยังช่วยเขียน PRD แบบสัมภาษณ์ไปด้วย เพื่อให้ ขอบเขตและความคาดหวัง ชัดเจนขึ้น
    • ในความเป็นจริง LLM มักสร้าง เทสต์ไร้ความหมาย เยอะมาก เช่น “1=1 หรือเปล่า?”
  • best practice” เปลี่ยนไปตามสภาพแวดล้อมทางเทคนิค
    ตอนนี้การเขียนโค้ดง่ายขึ้นแล้ว ดังนั้น coverage 100% อาจมีประโยชน์กับ LLM มากกว่าเดิม
    เทสต์ช่วยให้ LLM มี เป้าหมายที่ชัดเจน และทำให้การโต้ตอบหลังจากนั้นปลอดภัยขึ้น

    • สำหรับระบบที่พัฒนาเปลี่ยนแปลงระยะยาว เทสต์คือ เส้นชีวิต
      แต่ละเทสต์อ้างอิง bug ticket ในอดีต และรับประกันว่าการแก้ไขยังคงอยู่
    • “best practice” ถึง implementation จะต่างกัน แต่ รูปแบบมักคล้ายกัน
      ถ้าให้สถานการณ์กับ LLM มันมักสร้างโค้ดที่มีคุณภาพใกล้เคียงกันเป็นส่วนใหญ่
      ต่างจากงานศิลปะเชิงสร้างสรรค์ ซอฟต์แวร์คืออุตสาหกรรมที่เหมาะกับการทำอัตโนมัติเป็นพิเศษ
  • ตอนเห็นบทความ ผมนึกว่าจะพูดว่า “ถ้าอยากให้ AI มีประสิทธิภาพ เราต้อง เขียนโค้ดให้ดี
    ในความเป็นจริง Claude มักพลาดกับ ชื่อตัวแปรที่กำกวมหรือโค้ดที่ไม่เป็นตรรกะ
    ถ้าชื่อตัวแปรเป็น “iteration_count” แต่จริง ๆ เก็บผลรวม AI ก็จะโดนหลอก
    สุดท้ายแล้ว โค้ดที่สะอาด ก็มีประโยชน์ทั้งกับ AI และมนุษย์

    • เพราะ AI ทีมของเราจึงเริ่มใส่ใจกับ เอกสารและการดูแลคอมเมนต์ มากขึ้น
      เนื่องจาก AI ใช้เอกสารภายในเป็นทรัพยากรในการเรียนรู้ ตอนนี้ เอกสารที่อัปเดตแล้ว จึงถูกมองว่าเป็นสิ่งจำเป็น
      เมื่อก่อนมันเป็นเรื่องลำดับความสำคัญต่ำ แต่ตอนนี้ มีผลต่อคุณภาพของโมเดลโดยตรง
    • มนุษย์จำบริบทของโค้ดที่เคยเห็นได้ แต่ AI ต้อง เรียนรู้ใหม่ทุกเซสชัน
      อย่างไรก็ตาม เมื่อเวลาผ่านไป ส่วนนี้ก็น่าจะดีขึ้น
    • วิธีที่ได้ผลคือ เขียนเจตนาและตรรกะให้ชัดผ่าน method signature กับคอมเมนต์
      แบบนั้นโอกาสที่ LLM จะ implement ได้ถูกตั้งแต่ครั้งเดียวจะสูงขึ้น
  • บทความนี้เผยให้เห็น ความเข้าใจด้านวิศวกรรมแบบตื้น ๆ ของบริษัทสาย prompt
    coverage 100% ไม่ได้ตรวจทุกชุดของอินพุต
    มันแค่รันทุกบรรทัดด้วยตัวอย่างไม่กี่แบบเท่านั้น
    สุดท้ายแล้วสิ่งที่ต้องการคือ formal proof แต่ต้นทุนมันสูงมหาศาลและ LLM ก็ไม่มีประโยชน์กับเรื่องนี้

    • ถ้างั้นทางออกคืออะไร? ให้ซีเนียร์ดู PR แล้วบอก “LGTM” มันก็เป็นแค่ การทดสอบทางอารมณ์
      ตรงกันข้าม การสร้าง สภาพแวดล้อมพัฒนาแบบตอบสนองรวดเร็ว ผ่านเทสต์อาจเปิดยุคทองใหม่ได้
      ถ้ามีปัญหากับ coverage ก็ค่อยขยายทีหลังได้
      ทางที่ดีคือตั้งระบบเทสต์ให้ ครอบคลุมที่สุดเท่าที่ทำได้ ตั้งแต่ต้น
    • การบอกว่า LLM ไม่มีประโยชน์ต่อ formal verification เป็นคำกล่าวที่แรงเกินไป
      ตอนนี้ก็มีความพยายามมากมายในการเชื่อมมันเข้ากับ proof assistant
      ต่อให้ในสเปกจะมีข้อผิดพลาดเล็กน้อย ส่วนใหญ่ก็ยังให้ ผลลัพธ์ที่ใช้งานได้