- ตั้งแต่ราว 5 ปีก่อน ผู้เขียนได้รับบทบาทเป็น Engineering Manager ทำให้ในงานหลักมีโอกาสเขียนโค้ดด้วยตัวเองน้อยลง
- นอกเหนือจากงานประจำ ก็ยังทำโปรเจกต์ส่วนตัวอย่างต่อเนื่องเพื่อรักษาความคุ้นเคยกับการเขียนโปรแกรมและฝึกฝนทักษะทางเทคนิค
- ในอดีต โปรเจกต์มักเดินหน้าได้ช้าเพราะข้อจำกัดด้านเวลา และหลายครั้งก็หยุดไปก่อนจะทำเสร็จ
- แต่ในปี 2024 ผู้เขียนเริ่มสร้างและปล่อยเครื่องมือที่ต้องการได้ค่อนข้างรวดเร็วขึ้น จนสร้างนิสัยในการทำเวอร์ชันแรกให้ “เสร็จ” ได้สำเร็จ
ตัวอย่าง side project ที่เพิ่งทำเสร็จไม่นานนี้
- jsonplayground.com : เป็นทั้ง JSON formatter และมีฟังก์ชัน JQ ที่รันภายในเบราว์เซอร์ (ใช้ WebAssembly) จึงไม่ส่งข้อมูลออกไปภายนอก
- webtomarkdown.com : แปลงไฟล์เป็น Markdown หรือดึงบางส่วนของเว็บไซต์ออกมาเป็น Markdown เพื่อส่งเป็น context ให้ LLM ได้
- ร่างการปรับปรุงดีไซน์ของหน้าเว็บชมรมการบิน Evergreen Soaring
- สร้าง ส่วนขยาย Chrome เพื่อทำให้การตอบข้อความที่ส่งมาถึงชมรมการบินเป็นแบบอัตโนมัติ
- fitinterval.com : ให้ฟังก์ชัน interval timer สำหรับการออกกำลังกาย
ที่มาของการใช้ LLM และ Cursor IDE
- LLM ช่วยเพิ่มประสิทธิภาพในการทำ side project ได้อย่างมาก
- โดยเฉพาะการใช้ LLM กับงานเขียนโค้ดผ่าน Cursor IDE ที่สะดวกมาก
- บทความนี้ต้องการแชร์ภาพรวมของขั้นตอนการสร้างโปรเจกต์ใหม่ เพื่อให้ผู้อ่านนำไปปรับใช้ได้
- LLM ไม่ได้มีประโยชน์ในทุกด้านเสมอไป จึงควรลองใช้ด้วยตนเองเพื่อเลือกว่าจะนำไปใช้ตรงไหน
โปรเจกต์ตัวอย่าง: เว็บไซต์ติดตามนิสัย
- ผู้เขียนต้องการสร้างแอปติดตามนิสัยที่ใช้อยู่ในปัจจุบันขึ้นมาใหม่ในรูปแบบเว็บไซต์
- ข้อมูลทั้งหมดจะถูกเก็บไว้ในอุปกรณ์ภายในเครื่อง เพื่อคำนึงถึงความเป็นส่วนตัวของผู้ใช้
เริ่มต้นออกแบบสเปก
- เริ่มจากอธิบายสั้น ๆ ให้ ChatGPT ฟัง แล้วค่อยตอบคำถามเพิ่มเติมเพื่อทำให้สเปกของแอปชัดเจนขึ้น
- เมื่อสเปกเริ่มชัดแล้ว ก็ขอให้ช่วยสรุปให้อยู่ในระดับที่ “คนอื่นสามารถดูสเปกนี้อย่างเดียวแล้วสร้างทั้งแอปได้”
- ระบุไว้ชัดเจนว่าจะใช้ TypeScript, React, Tailwind CSS เพื่อให้ได้สเปกที่อิงตามเทคโนโลยีเหล่านี้
- เก็บสเปกสุดท้ายไว้ใน
SPEC.md เพื่อใช้อ้างอิงระหว่างการพัฒนาต่อไป
บูตสแตรปโปรเจกต์
- ใช้ Vite เพื่อเตรียมโครงโปรเจกต์ได้อย่างรวดเร็ว
- ตั้งค่าเริ่มต้นด้วยคำสั่ง
npm create vite@latest . และนำ SPEC.md ไปวางไว้ในโฟลเดอร์โปรเจกต์
- ใช้ฟีเจอร์ agent ใน Composer ของ Cursor IDE เพื่อทำงานอย่างการตั้งค่า Tailwind และแก้ไขไฟล์พื้นฐานแบบอัตโนมัติ
- วิธีนี้ช่วยให้ฟีเจอร์แรก ๆ เช่น เลย์เอาต์ UX ตามที่คาดไว้, การใช้ localStorage และการ export เป็น Markdown ถูกสร้างขึ้นได้ในเวลาอันสั้น
ทำงานซ้ำแบบแบ่งเป็นหน่วยเล็ก
- แทนที่จะขอฟีเจอร์จำนวนมากในครั้งเดียว ผู้เขียนจะแยกสิ่งที่ต้องการปรับปรุงออกเป็นส่วนย่อย แล้วค่อยให้ LLM อัปเดตทีละขั้น
- เช่น แยกคำสั่งเรื่องการเปลี่ยน UX หรือการแก้บั๊กออกเป็นงานเล็ก ๆ แล้วสั่งผ่านโหมด Chat หรือ Composer
- สามารถแนบรูปภาพใน Chat เพื่ออธิบายดีไซน์ที่ต้องการ แล้วให้ LLM นำไปสร้างเป็นโค้ดได้
ตั้งค่าการดีพลอยอย่างต่อเนื่อง
- อ้างอิง GitHub Actions เพื่อตั้งค่าให้เมื่อมี commit เข้า main branch ระบบจะ build อัตโนมัติแล้ว deploy ไปยัง GitHub Pages
- ใน Cursor สามารถส่งลิงก์ไฟล์ตัวอย่าง
.yml จาก repo อื่นให้ LLM ใช้อ้างอิง เพื่อช่วยสร้าง deployment pipeline ได้
เคล็ดลับโดยรวม
- ใช้ LLM ช่วยจัดระเบียบภาพรวมและรายละเอียดของโปรเจกต์ไว้ก่อน แล้วบันทึกเก็บไว้ใช้เป็น context ภายหลัง
- ใช้เครื่องมือหรือโอเพนซอร์สเทมเพลตเพื่อบูตสแตรปโปรเจกต์และวางโครงสร้าง
- จัดเตรียมเครื่องมือพัฒนาที่จำเป็นและโครงสร้างไดเรกทอรีให้พร้อมในคราวเดียว พร้อมยึดตามแพตเทิร์นโปรเจกต์ที่ดูแลง่าย
- ใช้ Cursor Composer (โหมด agent) เพื่อเริ่มต้นโปรเจกต์ได้อย่างรวดเร็ว
- ใช้งาน Claude-3.5-Sonnet และ o1 ร่วมกัน
- ใช้ o1 สำหรับงานร่างภาพกว้าง ๆ (first draft)
- ประมาณ 80% ของงาน ใช้ Claude-3.5-Sonnet สำหรับการแก้ไขและเติมรายละเอียดอย่างเจาะจง
- เลือกโหมดให้เหมาะสม (Chat, Composer ปกติ, Composer agent)
- Chat: ใช้เมื่อจำเป็นต้องแก้จุดที่เฉพาะเจาะจง และต้องตรวจผลการแก้ทุกครั้ง
- Composer(ปกติ): ใช้เมื่อเพิ่มฟีเจอร์ที่ครอบคลุมหลายไฟล์ หรือมีการเปลี่ยนแปลงหลายไฟล์พร้อมกัน
- Composer(agent): แม้ยังไม่ได้ใช้มากนัก แต่เหมาะเมื่อจำเป็นต้องรันคำสั่ง, lint หรือทำงานอัตโนมัติแบบวนซ้ำ (แต่ก็ควรแยกเป็นงานย่อยเพื่อให้จัดการง่าย)
- เวลาให้ context ควรส่งไฟล์ เอกสาร หรือลิงก์ที่เฉพาะเจาะจงไปด้วย
- หากจำเป็น สามารถตั้งค่าในโหมด Chat ให้ดูทั้งโค้ดเบส เพื่อให้ LLM ค้นหาและเสนอโค้ดที่เหมาะกับ context ได้
- เก็บเอกสารของโปรเจกต์ในรูปแบบ Markdown (
SPEC.md เป็นต้น) เพื่อให้สามารถนำมาใส่เป็น context ได้
- ใช้ไฟล์
.cursorrules ในโฟลเดอร์โปรเจกต์
- เช่น สั่งไม่ให้ใช้ไลบรารีบางตัว หรือบังคับให้ใช้ Tailwind และไลบรารีคอมโพเนนต์ shadcn
- หากกำหนดกฎที่อยากให้สะท้อนใน prompts ไว้ล่วงหน้า ก็จะช่วยชี้นำผลลัพธ์ของคำขอส่วนใหญ่ไปในทิศทางที่ต้องการได้
- ทำงานโดยพยายามเข้าใจโค้ดทั้งระบบ
- เพื่อหลีกเลี่ยงสถานการณ์ที่ LLM ดีบักต่อไม่ได้ ควรรักษาคุณภาพและโครงสร้างของโค้ดไว้
- แบ่งงานออกเป็นหน่วยเล็กอย่างต่อเนื่อง และหากจำเป็นก็ใช้ LLM ช่วย refactor หรือแยกโมดูล
สรุป
- หากใช้วิธีนี้เพื่อทำโปรเจกต์ให้เสร็จและปล่อยเวอร์ชัน deploy ได้อย่างรวดเร็ว ต่อให้พักไปช่วงหนึ่งก็จะกลับมาเริ่มต่อได้ง่ายขึ้นมาก
- นิสัยการทำของชิ้นเล็ก ๆ ให้เสร็จช่วยรักษาแรงขับเคลื่อน และทำให้เห็นผลลัพธ์เล็ก ๆ ได้อย่างรวดเร็วซึ่งช่วยเพิ่มแรงจูงใจ
3 ความคิดเห็น
ขอบคุณสำหรับข้อมูลดี ๆ!
ดูเหมือนว่ารูปแบบการลองทำของแต่ละคนจะคล้าย ๆ กันนะ
ช่วงนี้ผมได้ลองทำโปรเจ็กต์เล็ก ๆ ด้วย Cursor และ LLM โดยใช้วิธีคล้ายกับข้างต้น แล้วพบว่าช่วยเพิ่มประสิทธิภาพการทำงานได้มาก
ผมให้ LLM ช่วยทำ SPEC หรือ PRD แล้วใส่เข้าไปเป็นคอนเท็กซ์ใน Cursor จากนั้นก็กำหนดกฎเกี่ยวกับเทคโนโลยีที่จะใช้ไว้ใน
cursorrulesแล้วค่อยสั่งงานทีละอย่างผ่าน Composer ผลคือโค้ดที่ได้ออกมามีความสม่ำเสมอและใช้ได้ดีครับ