บันทึกเบื้องหลังการแบ่งปันเรื่อง Modern React with Testing

เมื่อเดือนก่อนได้โอกาสไปแบ่งปันความรู้และทักษะเรื่อง Modern React with Testing เป็นประสบการณ์ใหม่ที่ได้เตรียมตั้งแต่เนื้อหาจนถึงสอนจบด้วยตัวคนเดียว ซึ่งเป็นโจทย์ที่ท้าทาย ก็ดีใจที่ผลตอบรับออกมาดี ก็เลยอยากจะมาเล่าให้ฟังว่ามีวิธีการเตรียมตัวอย่างไร เทคนิคการสอน การอ่านใจคนเรียน เพื่อปรับแก้สถานการณ์หน้างานต่อไป
เริ่มที่การปรับทัศนคติของตัวเองก่อน
จะบอกว่างานชิ้นแรกที่เป็นจุดเริ่มประสบการณ์ในการพัฒนา software คืองาน frontend ของ internal tooling ในบริษัท เขียนด้วย Angular.js!! (ไม่ใช่ Angular นะ คนละโลกกันเลย ฮ่า ๆๆ) แล้วเราก็พบว่า “นี่แม่งไม่ใช่ทางเลยว่ะ” เพราะเราเป็นคนสะเพร่าตอนเด็ก ๆ จะทำงานปราณีตละเมียดละไมไม่ดี ตั้งแต่เด็กก็ตกศิลปะ โตมาก็ไม่ชอบทำงานบางอย่างใน frontend เช่นกัน อย่างเรื่องของการตกแต่ง ความสวยงาม หรือแม้กระทั่งการจัด HTML element ให้อยู่ตรงกลางของหน้า เรารู้สึก “อาย” ถ้าทำงาน frontend ได้ไม่สวยไม่ดีพอ มันทำให้ย้อนกลับไปถึงความรู้สึก “อาย” ที่ตัวเองตกศิลปะเลยล่ะ เราเลยเลี่ยงงาน frontend มาโดยตลอด ในขณะเดียวกันเราก็รู้ว่าโลกความจริงแม่งโหดร้าย เราอาจจะถูกบังคับให้มาทำงาน frontend ก็ได้ เราก็เลยเรียนรู้พื้นฐานของการพัฒนา frontend ผ่านการอ่านบทความ ลองลงมือเขียน todo app ไปจนถึง app เอาไว้สุ่มอาวุธในเกมที่ชอบ ด้วย React, Angular, และ Vue แน่นอนว่าไม่เน้นความสวยงาม เน้นใช้งานเองคนเดียว ฮ่า ๆๆ
เวลาผ่านไป โอกาสในการแบ่งปันความรู้และทักษะเรื่อง frontend ก็เข้ามา จากการที่เราเติบโตขึ้นและพบว่าตัวเองกลัว “ความเสียดายว่าไม่ได้ทำ…” เรารู้ว่าถ้าเราจะคว้าโอกาสนี้ ซึ่งไม่ได้มาง่าย ๆ ถ้าไม่ได้พิสูจน์ตนเอง เราจะอาจจะรู้สึก “อาย” อีกครั้งหากเราสอนไม่ดี สอนผิด หรือจัด HTML element ให้อยู่ตรงกลางของหน้าไม่ได้
เพื่อให้อยู่ร่วมกับความรู้สึกนี้ได้แบบไม่ฝืนตัวเองมากเกินไป เราต้องปรับทัศนคติว่า “แม้เราไม่ใช่คนที่เชี่ยวชาญด้านความสวยงามของ frontend แต่เราก็สามารถแบ่งปันประสบการณ์ แนวคิด แนวทางปฏิบัติอื่น ๆ ที่เอาไปประยุกต์ในงาน frontend ได้” เพราะงาน frontend มันไม่ได้มีแค่เรื่องความสวยงาม แต่ยังมีด้าน performance, state management, building, testing และแง่มุมในการทำระบบให้พร้อมสำหรับ production grade
พอเรามีทัศนคติที่พร้อมรับโอกาสที่เข้ามา บวกกับทักษะ frontend ที่พอสะสมมาบ้างนิดหน่อย ก็ตัดสินใจตอบรับโอกาสนี้ ได้เวลามาเตรียมเนื้อหาพอสมควร ซึ่งก็ balance กับหน้าที่และความรับผิดชอบในงานที่บริษัทปัจจุบัน
เตรียมเนื้อหา
ตอนที่เตรียมเนื้อหา เราก็ได้ expectation จากผู้จัดมาคร่าว ๆ ว่าเขาอยากเห็นเนื้อหาอะไรบ้าง โดยคร่าว ๆ ก็จะมี
- Why the industry moved away from Create React App
- TypeScript for React
- React Hooks
- Next.js
- Client vs Server components
- Asynchronous & Data Fetching
- Form Management
- Testing
Outcomes ที่อยากได้
- เขียน React ด้วยมาตรฐานล่าสุดที่ใช้ในบริษัท tech ชั้นนำ
- ลด bug ด้วยการทำ testing ที่ครอบคลุม ทำให้กล้า refactor code โดยไม่กลัวพัง
- จัดโครงสร้าง project อย่างเป็นระบบ เข้าใจการจัดการ state และ side-effects
เราเริ่มด้วยการวางแผนเตรียมเนื้อหาก่อน โดยจะแบ่งเป็น 2 ส่วนก็คือ
- เนื้อหาที่ตรงไปตรงมากับ expectation จากผู้จัด
- เนื้อหาอื่น ๆ ที่เราอยากจะสอนเพื่อเข้าใจภาพรวมว่าเรียนไปทำไม
เนื้อหาที่ตรงไปตรงมากับ expectation
เนื้อหาส่วนแรกนี้เราจะเน้นที่การเปรียบเทียบระหว่างการเขียน React แบบดั้งเดิม[1] กับ React แบบโลกใหม่ ซึ่งของดั้งเดิมก็ไม่ต้องไปไหนไกลก็อะไรที่เราเคยรู้มานั่นแหละ ฮ่า ๆๆ อย่างเช่นการขึ้น project ใหม่ด้วย Create-React-App, ใช้ Class Components, state management ด้วย Redux, เขียน CSS ด้วย styled-components ส่วนโลกใหม่เราก็ไป research เพิ่มเติม ซึ่งพอมี Generative AI ก็สามารถช่วยให้งานตรงนี้ง่ายขึ้นเยอะ และการติดตามข่าวสาร software development ก็ทำให้เข้าใจ buzzword ใหม่ ๆ ของโลกใหม่ได้ง่ายขึ้น เช่นขึ้น project ใหม่ด้วย React framework อย่าง Next.js, ใช้ React Hooks เพื่อทำ state management (ทั้ง client และ server state), form management, data fetching, เขียน CSS ด้วย Tailwind เป็นต้น
หลังจาก research และปูพื้นฐานให้ตัวเองเพื่อทำความเข้าใจแล้ว เราก็ลองลงมือสร้าง project และพัฒนาโดยใช้เครื่องมือต่าง ๆ เหล่านั้นดู เพื่อความสะดวกเราก็ใช้ GenAI coding assistant อย่าง Cline และ model จะเลือก Anthropic Sonnet 1M token ในการช่วย generate code ตามด้วยเรา review และทำความเข้าใจ code เหล่านั้นอีกที ที่ต้องปูพื้นฐานก่อนเพราะเราจะรู้ว่า code ที่ generate มามันตรงกับเป้าหมายของเราไหม ถ้าไม่ตรงแปลว่า GenAI เริ่มออกทะเล วิธีการแก้ไขและป้องกันก็จะมี
- Automated testing: นอกจาก generate implementation code แล้ว อย่าลืม generate code การทดสอบควบคู่ไปด้วย (ในที่นี้จะใช้ unit test เป็น React Testing Library + integration กับ API ด้วย Mock Service Worker + E2E testing ด้วย Playwright) เพราะมันเป็นวิธีการกันไม่ให้ code ที่ generate ออกมาผิดหรือไปผิดที่ผิดทางได้เร็วและถูกมาก
- Human-in-the-loop: Code ส่วนไหนที่สำคัญในการสอน เช่น code การทดสอบ เราต้อง review เอง ถ้าเริ่มออกทะเลให้ reset checkpoint เพื่อให้กลับมาอยู่ถูกที่ถูกทางให้เร็วที่สุด
- Context engineering: กำหนด instruction และเลือกใช้ skills จาก community ให้ครอบคลุมกับเนื้อหาที่จะสอน แยก session ระหว่างการเขียน React แบบดั้งเดิม กับ React แบบโลกใหม่ ออกจากกันเพื่อป้องกันไม่ให้ context ปนกัน
- Context limit: คุม context ตั้งแต่เริ่มได้่ requirement ก็คือโจทย์ตัวอย่างไม่ต้องยากซับซ้อนเท่ากับ production grade จริง ๆ เราเน้นความเข้าใจว่าแต่ละท่าที่ใช้ในโลกใหม่มันมีความหมายยังไง มันดีกว่าของเดิมยังไงก็พอ
ปิดท้ายด้วยการนำสิ่งที่ได้เรียนรู้มาทำเป็นเนื้อหาที่ย่อยง่ายขึ้นและเหมาะสำหรับคนเรียนต่อไป ส่วน project ที่ปั้นขึ้นมาก็กลายเป็นโจทย์ที่จะใช้ใน workshop นั่นเอง
เนื้อหาอื่น ๆ
หลังจากที่เตรียมเนื้อหาส่วนแรก เราจะต้องโยงกลับมาที่ภาพรวมว่าเรียนไปทำไมเพื้อให้เนื้อหามันจะประติดประต่อเป็นเรื่องเดียวกัน รู้ว่าเรียนไปแล้วเอาไปใช้ตรงไหนเมื่อไร ถ้าคนที่ต้องทำงานเป็นทีมก็จะสามารถเริ่มคุยกับคนอื่น ๆ เพื่อลองเริ่มนำสิ่งที่เรียนมาปรับใช้ได้ หรือถ้าทำงานคนเดียวหรือใช้ GenAI ช่วย ก็จะสามารถออกแบบแนวการทำงานที่ generate code มาตรงกับเป้าหมายของเขาได้มากขึ้น เหมือนกับที่เรา generate code เพื่อทำความเข้าใจเนื้อหานั่นแหละ ดังนั้นในฐานะคนสอน คำถามที่เราจะต้องตอบกับตัวเองก่อนที่เริ่มสอนคือ
Key message เดียวที่เราต้องการจะสื่อไปถึงคนเรียนคืออะไร
ด้วยความที่ GenAI มันมาแรงมาก ๆ จนใครที่ไม่ใช้น่าจะตามโลกไม่ทันแล้ว เราคิดว่า key message ก็น่าจะล้อไปกับกระแส GenAI ได้ในแง่ที่ว่า
“มี GenAI แล้ว แต่ทำไมคุณถึงมาเรียนคอร์สนี้อยู่ล่ะ”
ในเมื่อคนเรียนก็สามารถหาความรู้จากเนื้อหาส่วนแรกได้ผ่าน GenAI หริือ internet ได้ ไปจนถึงว่าเราไม่ต้องสนใจ code ที่ generate มาหรอก ถ้าผิดเราก็ให้ GenAI แก้ไขให้ได้อยู่ดี
คำตอบของคำถามนี้คือเพราะทุกคนรู้อยู่แก่ใจว่า
การพัฒนา frontend ในองค์กรมันมีมากกว่าการ coding
มันไม่ได้มีแค่ขึ้น project, local development เสร็จแล้วก็ build ส่งต่อให้ tester ไปทดสอบ (ซึ่ง React ดั้งเดิมก็ทำได้) แต่มันมีเรื่องของแง่มุมที่ทำให้ระบบพร้อมใช้บน production เช่น performance optimisation, search engine optimisation (SEO), answer engine optimisation (AEO), error handling เป็นต้น ไปจนถึงการส่งมอบโดยรวม เช่น การพูดคุยกับ business เพื่อ requirement ที่ดี พูดคุยกับ designer เพื่อ UX/UI ที่ดี พูดคุยกับ tester เพื่อรูปแบบการทดสอบที่ไปในทางเดียวกัน, การออกแบบ path-to-production, การทดสอบจากหลากหลาย web browser และ internet connection ที่ไม่เสถียร การรองรับ user ผู้พิการผ่าน accessibility testing และการ release ไปจนถึงการ observe ระบบผ่านระบบ monitoring ต่าง ๆ
ดังนั้นเราสามารถเชื่อม technique และท่าต่าง ๆ ใน React โลกใหม่เข้ากับบริบทเหล่านี้ได้ เช่น
- ใช้ Next.js เพื่อรีด performance ของ frontend จากการแยก client-side กับ server-side rendering ออกจากกัน ช่วยแบ่งเบาภาระ client ในการ rendering
- ใช้ React Hooks เพื่อให้ logic สามารถ reuse ใน component หลาย ๆ ตัวได้ ถ้าต้องการจะแก้ก็สามารถแก้ได้เร็ว ถ้าเอาเข้ากระแส GenAI หน่อยมันก็ประหยัด token กว่าแก้ทุก component ซ้ำ ๆ กันอ่ะ
- เข้าใจ error boundaries เพื่อพูดคุยกับ business ว่าหน้า web จะ render ยังไงถ้าระบบหลังบ้านมีปัญหาโดยที่ความเชื่อมั่นของ user ที่มีต่อระบบไม่แย่ไปกว่าเดิม
พอเชื่อมกันแล้ว คนเรียนก็มีแนวโน้มที่จะเห็นภาพว่าจะเอาสิ่งที่ได้เรียนรู้ไปประยุกต์ใช้ในบริบทของตัวเขาเองได้ยังไง
การอ่านใจคนเรียน เพื่อปรับเนื้อหาหน้างาน
ก่อนเรียนเราได้มีโอกาสคุยกับผู้จัดอีกครั้ง ก็ได้ความมาเพิ่มว่าคอร์สก่อนหน้านี้คนเรียนมีพื้นฐานหลากหลาย ตั้งแต่เก่งมีพื้นฐานไปจนถึงเขียน frontend ไม่เป็นเลย เราเลยคิดว่า
ถ้าเริ่มเข้าเนื้อหา React เลยโดยคิดว่าทุกคนเข้าใจ React แล้ว คนเรียนที่ไม่มีพื้นฐานมาก่อนจะตามไม่ทัน ในขณะเดียวกันถ้าทุกคนเข้าใจ React ไม่เท่ากัน การเริ่มจากพื้นฐาน คนเรียนที่มีพื้นฐานมาก่อนจะตาลอยเพราะเบื่อ
เมื่อเป็นแบบนี้แล้วเราก็เลยเตรียมเนื้อหาปูพื้นฐานก่อน ตั้งแต่ technology ที่เกี่ยวข้องการพัฒนา frontend (HTML, CSS, JavaScript), DOM, การพัฒนา frontend แบบดิบ ๆ ไปจนถึงการกำเนิดของ library/framework และพื้นฐาน React แบบคร่าว ๆ (components, JSX/TSX, Styles, props/state, rendering, event handling) เพื่อให้ทุกคนเข้าใจ React ไปในทางเดียวกัน
ส่วนจะหยิบมาพูดลึกแค่ไหนก็ไปถามคนเรียนหน้างานเอาผ่านกิจกรรม Hopes & Fears ซึ่งจะทำให้เราเห็น expectation ของคนเรียนที่มีมมุมองต่างจากผู้จัด และจะได้เน้นเนื้อหาที่คนเรียนสนใจหรือเลือกข้ามเนื้อหาที่คนเรียนไม่ได้สนใจมากได้
ระหว่างสอนและทำ workshop เราก็จะมีกิจกรรมให้ลองทำแก้โจทย์ สิ่งที่สังเกตคือทุกคนล้วนใช้ GenAI ในการแก้โจทย์ทั้งนั้น ซึ่งเราก็ใจดีสอดไส้ spec ของระบบไว้ให้เรียบร้อย เพราะเราก็ใช้เองเหมือนกัน ฮ่า ๆๆ ซึ่งเราก็คิดว่าตัดสินใจถูกแล้วที่ไม่ได้สั่งห้ามใช้ GenAI เพียงเพราะอยากให้คนเรียนลองฝึกเขียนเอง เพราะว่าในชีวิตจริงพวกเขาก็จะใช้ GenAI ในที่สุด ในขณะเดียวกันเราก็อยากสอนว่า
คุณควรจะเข้าใจ code ที่ generate ออกมาด้วยเพื่อจะได้สังเกตว่าเมื่อไรที่ GenAI กำลังจะเริ่มออกทะเล
เราก็จะปรับกิจกรรม workshop ให้ balance การใช้ GenAI โดยที่เข้าใจด้วยว่ามัน generate อะไรออกมาให้ เช่น มีการทำ code review ของระบบ React ดั้งเดิม ไปจนถึง code review ของระบบ React โลกใหม่ที่แต่ละคนได้เขียนหรือ vibe coding ขึ้นมา และแบ่งปันความรู้ซึ่งกันและกัน โดยเน้น frame ว่าเราจะเน้นไปที่เพื่อการเรียนรู้ร่วมกัน ไม่ใช่การตำหนิหรือทำร้ายความรู้สึก เรา review code ไม่ได้ review ตัวบุคคล นอกจากนั้นก็เพิ่ม requirement ว่าต้องมีชุดการทดสอบที่ครอบคลุม เพื่อใช้เป็น harness ป้องกันไม่ให้ GenAI ออกทะเล
ผลลัพธ์
คงไม่ต้องพิมพ์อะไรกันมาก เอาเป็นว่าดูจาก sticky notes ที่คนเรียนเขา share ไว้ละกัน

ส่วนตัวคือภูมิใจกับการสอนครั้งนี้มากเพราะเป็นครั้งแรกที่เราได้มีโอกาสจัดสอนด้วยตัวเองคนเดียว ได้โอกาสในการเรียนรู้การพัฒนา frontend ผ่าน React แบบโลกใหม่ผ่านการสอนไปในตัว และขอบคุณตัวเองที่กล้าอยู่กับความรู้สึก “อาย” ในความไม่สมบูร์แบบของตัวเองจากประสบการณ์ในอดีต
[1] การที่บอกว่าเขียน React แบบดั้งเดิมไม่ได้หมายความว่าแบบนั้นมันไม่ดีไปซะทุกอย่างนะ เช่นการทำ state management โดยใช้ Redux มันก็ใช้ได้ถ้าเราต้อง manage state ที่ต้อง update แบบมีเงื่อนไขซับซ้อนหรือต้องมี side-effects ในหลาย ๆ component พร้อมกัน แต่มันจะ overkill ถ้า app เราเล็กหรือมี state logic ไม่วับซ้อนแค่นั้นเอง