เจออะไรใน PWA Online Hackathon

Tanawat Tassana
Coding Cat
Published in
3 min readJun 25, 2017

ผมสมัครเข้าไปเล่นใน PWA Online Hackathon กับเขาด้วย เป้าหมายของผมคืออยากลองทดสอบเครื่องไม้เครื่องมือที่ตัวเองสนใจ ว่าเมื่อต้องเอามาทำของให้ใช้ได้จริงๆในเวลาจำกัดมันจะทำได้มั้ย มันจะดีอย่างที่คิดไว้หรือเปล่า บทความนี้เขียนสดๆตอนที่เหลือเวลาแข่งอีก ๑ ชั่วโมงกว่าๆ แต่ด้วยความที่ไม่ได้ตั้งใจจะเอารางวัลอะไรอยู่แล้ว บวกกับของที่อยากทำก็ทำไปเสร็จแล้ว ก็เลยเอาสิ่งที่เจอมาเขียนเลยดีกว่า กำลังร้อนๆจะได้ไม่ตกหล่น

เป้าหมาย

ผมเป็นคนที่สนใจเรื่อง Architecture ของระบบที่ผมทำมาก งานหน้าบ้านในปัจจุบันมันซับซ้อนมากกว่าแค่เรื่องความสวยงาม ถ้าเราออกแบบและประกอบของต่างๆขึ้นมาไม่ดีพอ เราจะเจอปัญหาในการดูแลระยะยาว การแข่ง Hackathon ที่มีข้อจำกัดเรื่องเวลาจะช่วยเร่งปัญหานี้ให้มาเจอเราเร็วขึ้นอีกเมื่อเพิ่มฟีเจอร์เข้าไปเรื่อยๆ เป้าหมายของผมจึงเป็นการทดสอบ Architecture & Tools ที่ผมจะใช้ว่ามันจะดีแค่ไหน

twopages

แอพที่ผมทำชื่อ twopages เป็นแอพที่เอาไว้บันทึกว่าวันนี้เราอ่านหนังสืออย่างน้อยสองหน้าแล้วหรือยัง แล้วอ่านเล่มไหนไปกี่หน้าบ้าง ฟีเจอร์ไม่มีอะไรมาก บันทึกของแต่ละวันได้ ดู history ได้ ถ้า sign in ข้อมูลก็จะถูกเก็บไว้ที่ Firebase ทำให้ไปเปิดที่เครื่องอื่นได้

หน้าตาตอนจบ

ใครสนใจว่าอ่านหนังสือวันละสองหน้าดียังไง เชิญอ่านที่ลิงค์นี้ครับ ผมชวนทุกคนมาอ่านหนังสือกัน

Tools

ผมใช้ React เป็น View Renderer สำหรับแอพนี้ สร้างด้วย create-react-app มันก็เสก Progressive Web App ออกมาให้เลย ด้วยการติด service worker มาให้อัตโนมัติ (ซึ่งก็มีทั้งคนเห็นด้วยและไม่เห็นด้วย ยังเถียงกันไม่จบ แต่ลดงานผมไปเยอะสำหรับการแข่งครั้งนี้)

ผมใช้ Redux สำหรับจัดการ global state แต่ผมไม่ชอบที่ state ทุกสิ่งอย่างต้องไปอยู่บน single container ทั้งหมด ผมจึงหยิบเอา Recompose มาใช้สำหรับจัดการกับ local state ของ component (จริงๆจุดขายของ recompose คือ Higher-order component ที่ช่วยให้เราสามารถเติมความสามารถให้ component ได้ง่าย และ reuse ความสามารถได้ แต่ครั้งนี้ผมเอามาใช้จัดการ local state และสร้าง props, handlers ที่จำเป็นสำหรับ component เป็นหลัก)

ดังนั้นแอพนี้จะมี state สองแบบคือ

  • System state (user คนปัจจุบัน, ข้อมูลการอ่านหนังสือ, Active route…) ถูกจัดการด้วย Redux
  • Local state (ค่าของ input แต่ละตัว, ค่าที่ใช้ในการซ่อน/แสดงบางส่วน…) ถูกจัดการด้วย Recompose

การใช้ Recompose แทนที่จะเขียนเป็น state ของตัว component ไปเลยนั้นทำให้ component จะยังเป็น stateless อยู่ ซึ่งง่ายต่อการทำ unit test (แต่ครั้งนี้ผมไม่ได้เขียนเทสนะ) และเอาไปใช้ที่อื่น (React component ทั้งหมดที่ผมเขียนในแอพนี้เป็น stateless)

ผมใช้ Router5 สำหรับทำ routing ผมเลือก Router5 เพราะมันไม่ทำอะไรให้ผมเลยนอกจากจัดการเรื่อง routing! มันไม่มายุ่งกับการ render ไม่มายุ่งกับ state ของระบบ แล้วให้เราเป็นคนจัดการเองว่าเมื่อไหร่เราอยากทำอะไร ซึ่งผมโอเคกว่า ข้อเสียคือต้องมาเขียน logic เองว่าตอนย้ายไป route นี้ต้องทำอะไรบ้าง แต่ผมรู้สึกดีกว่าที่ได้ control ตรงนี้เองทั้งหมด

ผมใช้ Redux-saga สำหรับจัดการ control flow ของระบบ ซึ่งผมเจอว่าเจ้านี่กลายเป็นพระเอกของงานเลย

ผมใช้ Styled-components กับ Polished ร่วมกับ Bulma ในการจัดการเรื่อง styling ของ components

ผมใช้ Ramdajs เป็น utility

Project Structure

ผมวางโครงสร้างตามแนวทางของ Ducks ที่จะแยก state (ของที่เกี่ยวข้องกับ Redux) กับ View (ของที่เกี่ยวข้องกับการแสดงผล) ออกจากกัน สามารถอ่านแนวคิดนี้ได้ที่นี่ครับ

หน้าตามันจะออกมาประมาณนี้

Project structure ของ twopages

ผลที่ได้

ผมพอใจกับเครื่องไม้เครื่องมือ, โครงสร้าง และวิธีเขียนโค้ดครั้งนี้มากๆนะ สิ่งที่ผมอยากพูดถึงเป็นพิเศษมีสองอย่างคือ Redux-saga และ Lens

Redux-saga

สิ่งที่ผมคิดว่า Redux-saga มอบให้ผู้ใช้และมันสำคัญมากคือ ความสามารถในการควบคุม “ลำดับ” การทำงานหรือที่เราเรียกว่า control flow นั่นเอง

เมื่อเราใช้ Redux จัดการกับ state นั่นหมายความว่าสิ่งที่จะเป็นตัวกำหนดความเคลื่อนไหวของระบบก็คือ Action แต่ Action ทั้งหลายนั้นจะเกิดขึ้นเมื่อไหร่จากที่ไหนก็ได้ การควบคุมลำดับการทำงานและการเกิดขึ้นของ Action จึงเป็นโจทย์ที่คนใช้ Redux ทุกคนต้องแก้อยู่แล้ว

ซึ่ง Redux-saga ใช้ความสามารถของ JavaScript Generator ทำให้เราสามารถจัดการกระแสของ Action ได้อย่างเป็นธรรมชาติมากๆ เมื่อการจัดการกับ Action ทำได้ง่าย เราก็จะสามารถเขียนโค้ดทั้งหมดให้อยู่ในรูปแบบของ Action-driven ทุกอย่างคือ Action และผลลัพธ์ของ Action

อ่านแล้วงงใช่ไหม ผมอ่านของตัวเองก็งง ฮ่าๆๆ เอาเป็นว่าแนะนำให้ลองครับ

Lens

Lens เป็น concept ของ Functional programming สามารถมองง่ายๆเป็นเหมือนช่องสำหรับเข้าถึงข้อมูลที่เราสนใจ ผมว่าอันนี้ดูโค้ดจะง่ายกว่า

เวลาเขียน JS เรามักจะสร้าง Object ที่ซับซ้อนขึ้นมาอย่างตั้งใจและไม่ตั้งใจ การเข้าถึงด้วย . แบบธรรมดานั้นมีโอกาสสร้าง bug ในระยะยาวเมื่อเกิดการเปลี่ยนแปลงขึ้น แต่ lens จะช่วยให้วิธีการเข้าถึงข้อมูลคงที่เสมอ ผมเจอว่า lens เซฟเวลาผมไปเยอะมากระหว่างทำ ผมไม่ต้องกังวลที่จะย้ายของหรือแก้โครงสร้างของข้อมูลเลย

นี่เป็นประโยชน์แบบพื้นฐานของ lens เลยนะ ยังไม่รวมไปถึงพวก composition ที่ผมไม่ได้ใช้ในแอพนี้

Architecture ที่ดีจะทำให้เกิดความรู้สึกว่ายิ่งเพิ่มของยิ่งง่าย

มีอยู่สี่ห้าครั้งที่ผมได้ความรู้สึกนี้จากงานครั้งนี้ Redux-saga ช่วยให้เราสาน flow ของ Action ไว้ง่าย การเติม feature ใหม่ลงไปจึงเป็นความรู้สึกที่เหมือนกับเราเลือกหยอด Action ลงไปให้ถูกที่ใน flow ที่มีอยู่ ซึ่งพอหยอดถูกปุ๊บ ทุกอย่างก็จะทำงานถูกเลย ผมรู้สึกได้เลยว่าฟีเจอร์หลังๆที่ทำใช้เวลาลดลงเรื่อยๆ ในขณะที่โครงสร้างแบบ Ducks ทำให้ผมหาของเจอง่ายๆ คาดหวังได้ว่าอะไรจะอยู่ตรงไหนไม่ปนกัน ข้อเสียก็คงจะเป็นจำนวนไฟล์ที่ต้องสร้างแล้วก็ความลึกของ directory นี่แหละ แต่ของที่ได้มาก็รู้สึกว่าคุ้มดี

สรุปคือสนุกมากครับ ได้อะไรเยอะเลย(ถึงแม้จะไม่ค่อยเกี่ยวกับ Progressive Web App) ขอบคุณผู้จัดทุกท่านครับ

--

--