Quantcast
Channel: cc :: somkiat
Viewing all articles
Browse latest Browse all 1997

[แปล] ว่าด้วยเรื่องของการ Reactoring React App ตอนที่ 2

$
0
0

ต่อจากตอนที่ 1 อธิบายเรื่องของการพัฒนาระบบและเขียนการชุดสอบสำหรับ React app ในตอนที่ 2 จะมาอธิบายเรื่อง การปรับปรุงโครงสร้าง code ให้อยู่ในรูปแบบ ELM Architecture ซึ่งมีส่วนการทำงานดังนี้
  • View
  • Model
  • Update
จากนั้นลงมือปรับปรุง code ทีละส่วน แน่นอนว่า ต้องมีชุดการทดสอบด้วยเสมอ ดังนั้นมาเริ่มกันเลย

ทำความเข้าใจเกี่ยวกับ ELM Architecture กันก่อน

ประกอบไปด้วย 3 ส่วนหลัก
  1. View คือส่วนที่นำ model มาแสดงผลนั่นเอง
  2. Model คือส่วนหลักของระบบ รวมทั้งการจัดการ state ต่าง ๆ หรือข้อมูลนั่นเอง
  3. Update คือส่วนการทำหน้าที่เปลี่ยนแปลงสถานะต่าง ๆ ของ model แต่แทนที่จะเปลี่ยนแปลงตรง ๆ ก็ทำการสร้างของใหม่ออกมา ซึ่งลดผลกระทบต่าง ๆ ที่จะเกิดขึ้น
อ่านไปอ่านมาก็คล้าย ๆ กับ Redux นะ แต่เป้าหมายของบทความนี้ ไม่ต้องการติดตั้ง library อะไรเพิ่มเติม ต้องการเขียนด้วย pure JavaScript เท่านั้น แน่นอนว่า การทำงานยังคงต้องเหมือนเดิม นั่นคือ ชุดการทดสอบที่เขียนด้วย Enzyme ใน Part 1 ยังคงต้องผ่านนะ มาเริ่มปรับปรุงโครงสร้าง หรือ Reactor code กันเถอะ

ขั้นตอนที่ 1 เรื่องของ Action และ State

สิ่งที่ต้องคิดถึงคือ state และ action ที่เกิดขึ้นใน app ของเรา มาดู state ของ app กันก่อน ซึ่งประกอบไปด้วย
  • init คือสถานะเริ่มต้นของ app นั่นคือ counter มีค่าเป็น 0 เสมอ
  • update คือการ update ค่าต่าง ๆ ใน model ตาม Action
เริ่มด้วยการเขียนชุดการทดสอบของ State กัน ประกอบไปด้วย 2 test cases คือ
  • init สำหรับตรวจสอบค่าเริ่มต้นของ counter ต้องเป็น 0
  • update สำหรับตรวจสอบสถานะ
มาดูชุดการทดสอบกันหน่อย (state.spec.js) [gist id="ea4e26042b3d73dfb097b2e1d0d90dcc" file="state.spec.js"] ทำการเขียน code ง่าย ๆ (state.js) สิ่งที่น่าสนใจคือ spread operator (...) สำหรับการส่งทั้ง object กลับมา [gist id="ea4e26042b3d73dfb097b2e1d0d90dcc" file="state.js"] จากนั้นมาดู Action ที่เกิดขึ้นใน app หน่อยสิว่ามีอะไรบ้าง ?
  • INCREMENT action สำหรับการเพิ่มค่า
  • DECREMENT action สำหรับการลดค่า
โดย action ต่าง ๆ จะถูกประกาศไว้ในไฟล์ actions.js ดังนี้ [gist id="ea4e26042b3d73dfb097b2e1d0d90dcc" file="actions.js"] ตอนนี้เรามาคิดกันหน่อยสิว่า แต่ละ Action ส่งผลต่อ state อย่างไรบ้าง ?
  • INCREMENT เพิ่มค่าขึ้นมา 1
  • DECREMENT ลดค่าลงมา 1
สามารถเขียนเขียนชุดการทดสอบใน state.spec.js ได้ดังนี้ [gist id="ea4e26042b3d73dfb097b2e1d0d90dcc" file="state.spec_v2.js"] จากนั้นทำการเขียน code ง่าย ๆ (state.js) ด้วยการใช้ swich-case ปกตินั่นเอง [gist id="ea4e26042b3d73dfb097b2e1d0d90dcc" file="state_v2.js"] สิ่งที่ห้ามลืมคือ นำ state ไป integrate เข้ากับ React component ด้วยนะ นั่นคือต้องเปลี่ยนแปลงไฟล์ Counter.js หรือ Counter component ด้วย สามารถเขียน code ได้ดังนี้
  • ทำการ initial ค่าของ State ด้วย State.init()
  • ทำการ update ค่าต่าง ๆ ด้วย Action INCREMENT และ DECREMENT
[gist id="ea4e26042b3d73dfb097b2e1d0d90dcc" file="Counter.js"]
หลังจากการเปลี่ยนแปลงแล้ว ผลที่ตามมาคือ ชุดการทดสอบยังต้องผ่านเช่นเดิม !! Unit tests ผ่านหมด Integration tests ผ่านหมด ก็ไว้ใจได้ในระดับหนึ่งแล้วนะ

ขั้นตอนที่ 2 เรื่องของ Lifecycle และ View

เมื่อเราทำการแยก State และการ Update ตามแต่ละ action ออกไปจาก component แล้ว (State และ Action) สิ่งที่ยังเหลือคือ การทดสอบในระดับ component โดยในตอนนี้เราทำการรวมทุกอย่างไว้ใน component เดียวคือ Counter Component (counter.js) ทั้งส่วนการประมวลผลและการแสดงผล ดังนั้นเราต้องทำการแยกทั้งสองส่วนออกจากกัน โดยส่วนหลักเราจะเรียกว่า Container component หรือ Lifecycle component ทำหน้าที่รับ action จากผู้ใช้งาน และรวม component ต่าง ๆ เข้าไว้ด้วยกัน และอีกส่วนเรียกว่า View component หรือ Dumb component ซึ่งทำหน้าที่แสดงผลตามข้อมูล หรือ state หรือ model ที่ส่งเข้ามาเท่านั้น มาแยกส่วนการแสดงผลออกมาดีกว่า !! โดยส่วนการแสดงผลหรือ View component ประกอบไปด้วย
  • การแสดงปุ่มบวก และ ปุ่มลบ
  • การแสดงข้อมูล counter
  • การรับ action มาทำงาน
โดยจะส่งข้อมูลผ่าน props มายัง component นี้ทั้งหมด สามารถเขียนได้ดังนี้ [gist id="ea4e26042b3d73dfb097b2e1d0d90dcc" file="View.js"] ต่อมาก็ต้องเขียนชุดการทดสอบด้วย Enzyme ดังนี้ สังเกตุไหมว่า ชุดการทดสอบน้อยลง เนื่องจากเราทดสอบเพียง state ที่เปลี่ยนและการแสดงผลตามข้อมูลที่กำหนดเท่านั้น [gist id="ea4e26042b3d73dfb097b2e1d0d90dcc" file="View.spec.js"] เมื่อทุกอย่างผ่านไปด้วยดีแบบนี้ ก็ได้เวลาแก้ไข Counter component หรือไฟล์ Counter.js เพื่อให้ใช้งาน View component ดังนั้น Container component คือ Counter.js ส่วน Dump component คือ View.js ทำการแก้ไขได้ดังนี้ [gist id="ea4e26042b3d73dfb097b2e1d0d90dcc" file="Counter_v2.js"] จากนั้นชุดการทดสอบก็ต้องเปลี่ยนไปเช่นกัน เนื่องจากใน Counter component จะมีเพียง View component เท่านั้น ซึ่งแก้ไขได้ดังนี้ [gist id="ea4e26042b3d73dfb097b2e1d0d90dcc" file="Counter_v2.spec.js"]
แน่นอนว่าชุดการทดสอบทั้งหมดต้องผ่าน ถือเป็นอันจบขั้นตอนการปรับปรุง code ของ React app ให้อยู่ในรูปแบบของ ELM Architecture

โดยสรุปแล้ว ถ้าใครอ่านมาถึงตรงนี้

จะเห็นได้ว่าในทุกส่วนการทำงาน จะมีชุดการทดสอบครอบคลุมทั้งหมด ทำให้เรามีความมั่นใจในการแก้ไขและปรับปรุง code ให้ดียิ่งขึ้น นี่คือหัวใจของการพัฒนาระบบงานเลย ส่วนเรื่องของโครงสร้างหรือ architecture ของ code นั้นเป็นเรื่องที่ตามมา เนื่องจากโครงสร้างที่ทดสอบได้ง่าย ก็ทำให้เราแยกส่วนการทำงานตามหน้าที่รับผิดชอบได้ง่าย แต่ข้อเสียที่ตามมาคือ จำนวนไฟล์ที่เยอะขึ้น เกิดการกระจายของ code ซึ่งทำให้ยากต่อการเรียนรู้และทำความเข้าใจ
ดังนั้นเลือกโครงสร้างให้เหมาะกับงานและทีมด้วยนะครับ
โดย source code อยู่ที่ Github :: Up1 :: Learn React to ELM ขอให้สนุกกับการเขียน code และ test นะครับ

Viewing all articles
Browse latest Browse all 1997

Trending Articles