อย่าลืม share ให้มนุษย์ Android คนอื่นด้วยหละ 😎

Table of contents
เนื่องจากเราใช้เวลาเตรียมงานกันเป็นอาทิตย์เพื่อให้งานออกมาสนุก และได้ความรู้ครบ เราเลยเอาการขึ้นโครง MVP จริงๆจากโปรเจคใหญ่ๆที่เราทำกัน มาย่อให้เป็นแอปเล็กๆหนึ่งตัว เพื่อให้คนที่สนใจ MVP สามารถ clone project ไปศึกษาต่อกันได้เลย
ส่วนทางฝั่ง iOS จะขึ้นโครงแบบ MVVM และเป็นแอปเดียวกันด้วย เพื่อให้คนอ่านจะได้รู้ความแตกต่างระหว่าง iOS กับ Android ว่าขึ้นโครงต่างกันอย่างไร

อันนี้เป็นภาพตอนเตรียมงานครับ เราต้องซ้อมกันจริงจังมาก เราถึงจะสามารถทำแอปหนึ่งตัวในเวลาที่จำกัดได้ภายในงาน ซึ่งทั้งหมดต้องผ่านการฝึก การคิด brain strom เรียงลำดับการพูดการเขียนโค๊ดไว้หมดแล้ว เป็นที่มาว่าทาง android และ ios ใช้เวลาเตรียมงานกันเป็นอาทิตย์ๆ นั่ง research กันยกใหญ่เลยว่าควรพูดเรื่องอะไรบ้างที่จำเป็นในงานจนออกมาเป็นงาน Nextzy CNX Meetup #3 : Mobile Code Fighting
และนี่คือ link Github ตัวเต็มๆครับผม
วันนี้เราเลยจะมาแชร์ความรู้จากการใช้งานจริงๆกันครับผม
ตอนเราเขียน android แรกๆคงหนีไม่พ้น MVC : Model View Controller กันเนาะ

จากภาพ view ในที่นี้คือ Android component ต่างๆ เช่น activity/fragment ซึ่งเป็นส่วนของ Android framework ทั้งหมด ในส่วน controller ก็เขียน logic ให้ไป update view กับ model ในส่วน model ก็เช่นเดียวกันเขียน logic ให้ไป update view กับ controller จะเห็นว่าเส้นมันวิ่งเต็มไปหมด
เพราะฉะนั้นเวลาเขียน MVC เราจึงนิยมนำ controller ไปใส่ไว้ใน activity/fragment เลยเพื่อความรวดเร็วในการเขียน และความสะดวกในการเรียกใช้ เหมาะสำหรับโปรเจคขนาดเล็กหรือระยะเวลาสั้นๆ

คำถามคือถ้าเราต้องการจะเขียน Test ต้องทำอย่างไรให้สะดวก?
Robolectric ก็อาจจะเป็นคำตอบที่ดีเพราะสามารถ Mock android framework อย่างพวก Activity/Fragment ได้แต่เราเคยใช้และเจอปัญหาเลยหยุดใช้ไป และอีกหนึ่ง concept ที่ไม่ควรทำซักเท่าไหร่คือการ เอาโค๊ดส่วนที่เป็น pure JAVA (ข้อเรียกสั้นๆว่า POJO) ไปยัดใน Android framework ซึ่งจริงๆแล้วเราสามารถแยกได้ และนำมาเขียนเป็น JUnitTest ได้เลยโดยไม่ต้องไปพึ่ง Robolectric อีกต่อไป 😇
เพราะในโลกการทำงานจริงกับโปรเจคใหญ่ๆจะถูกแบ่งออกเป็นหลายๆ phase มากซึ่งก่อนจะข้ามไปทำอีก phase การเขียน test ทั้งหมดควรเสร็จหรือเสร็จมากที่สุดเท่าที่เป็นไปได้ มิเช่นนั้นจะไม่มีอะไรรับประกันว่าถ้าเราเขียนโค๊ดใน phase ถัดๆไปมันจะไม่กระทบ phase เก่าๆที่เราเคยเขียน

การขึ้นโครงแบบ MVP: Model View Presenter เลยตอบโจทย์เรื่องการ Test มากกว่า เพราะเราแยกโค๊ดส่วนของ Android framework ออกจาก pure JAVA ออกเป็น layer อย่างชัดเจน และทำให้โค๊ดเราเป็นระบบมากขึ้นด้วย

จากรูป view จะเป็นส่วนของ android framework เช่นเดิมแต่จะไม่มีการสั่ง update model ตรงๆเหมือน MVC อีกต่อไปทุกอย่างจะต้องผ่าน presenter หมด
ซึ่ง presenter จะเป็นเหมือนคนกลางที่คุยระหว่าง view กับ model ให้และจะเป็นโค๊ด POJO ทั้งหมดด้วย เพื่อเราจะได้เขียน JUnitTest ได้ง่าย คลาวนี้โค๊ดจะอยู่เป็นที่เป็นทางมากขึ้น โค๊ดส่วนไหนที่เป็น POJO logic ก็โยนมาให้ presenter เป็นคนดูแลไป
สรุป MVP จึงเป็นโครงสร้างที่เกิดมาเพื่อ Test มากๆ และทำให้โค๊ดเราแบ่งเป็น layer อย่างชัดเจนคือ Android framework กับ POJO แต่ก็แลกมาด้วยการเขียนโค๊ดที่มากกว่าและเยอะกว่าเดิม และใช้เวลานานกว่าในการเขียนกว่าถ้าเทียบกับ MVC ครับ แต่เป็นเรื่องที่เรายอมรับได้เพื่อโปรเจคใหญ่ๆหรือแอปที่ต้องการการดูแลในระยะยาว
ปล. แต่เราก็มีวิธีช่วยให้มันเร็วขึ้นนะ ด้วยการทำ Base class กับ Template ไว้ copy วางนั่นเอง 😎
การขึ้นโครงแบบ MVP ต้องต่างจาก MVC แน่นอนอยู่แล้ว

ย้อนกลับมาดูหลักการของการคุยกันระหว่าง class-to-class เราจะคุยกันผ่านสิ่งที่เรียกว่า interface เพราะฉะนั้น view กับ presenter จะไม่คุยกันตรงๆ พูดง่ายๆคือเราจะไม่ทำการ new presenter ตรงๆใน activity/fragment แต่จะใช้ interface แทน
และเพื่อไม่ให้โค๊ดซ้ำๆเราจำเป็นต้องสร้าง base class เพื่อให้ class ลูกที่จะทำเป็น mvp extend ไปใช้งานได้เลยทันที


จากโค๊ด base class ข้างบนเราพยายามทำให้ onCreate( ) ให้เป็น “One Single responsibility” ด้วย คือ 1 method 1 หน้าที่เท่านั้น เพราะแต่ก่อนเราจะชอบยัดทุกอย่างไว้ใน method นี้ซึ่งไม่ควรซักเท่าไหร่ โดยเราต้องซอยย่อย method ออกไปตามหน้าที่ต่างๆเช่น bindView( ) ก็มีหน้าที่แค่ bind view อย่างเดียวเท่านั้นเป็นต้น
และจะสังเกตเห็นว่ามี method createPresenter( ) ที่ return ค่าเป็น interface ของตัว presenter ตาม concept ที่เราเคยพูดไว้คือเราจะคุยกันผ่าน interface เท่านั้น
แค่นี้ base class ก็เป็นอันพร้อมใช้งาน
EXTRA: การมองโค๊ดเป็น layer เป็นอีกหนึ่งเรื่องที่สำคัญมาก ถ้าเราต้องการทำโปรเจกใหญ่ๆ หรือโปกเจกที่ต้องการดูแลในระยะยาว มันยืดหยุ่นในการเพิ่ม/ลดโค๊ดต่างๆ ซึ่งในที่นี้เราทำเป็น base layer ไว้ 1 ชั้นเพื่อให้ class ลูก extend ไปใช้งาน
ถ้าให้เห็นภาพมากขึ้นสามารถเข้าไปดู BaseMvpListAdapter.java กับ LoadmoreAdapter.java ได้เนื่องจากบาง adapter บางตัวต้องสามารถทำ loadmore ได้ เราจึงแยก loadmore ไว้เป็น layer ชั้นที่ 2 ไปเลย
เพราะขนาดตัว android framework เองยังเขียนโค๊ดเป็น layer เลยครับ

เมื่อ base class ทุกอย่างทำเสร็จเราก็มาสร้าง template เตรียมไว้ตามนี้

วิธีใช้ง่ายมาก คือ copy → paste → เปลี่ยนชื่อ
เช่น จะสร้างหน้า MainActivity ก็แค่ copy → paste → เปลี่ยนชื่อ เป็น MainActivity, MainInterface, MainPresenter เป็นต้น แค่นี้ก็ได้ MVP มา 1 หน้าสบายๆ แล้วค่อยลงมือโค๊ดต่อไป
EXTRA: เราสามารถใช้ JavaPoet library เข้ามาช่วย generate .java ได้ด้วยยิ่งสะดวกไปอีก
งั้นเรามาลองดูตัวอย่างง่ายๆของ MVP กันซัก 1 method

จากโค๊ดข้างบนตรงไปตรงมาคือ เราจะทำการ disable ปุ่ม confirm order ถ้าไม่มี ProductItem อยู่ใน cartAdapter ซึ่งเราเห็นว่าเป็น method ที่ค่อนข้างสำคัญ เพราะถ้าไม่มี ProductItem เราไม่ควรกดปุ่ม confrim order เพื่อข้ามไปหน้าอื่นได้ วิธีแก้ที่เซฟที่สุดเราจะแยก logic ส่วนนี้ออกไปไว้ใน presenter เพื่อเขียน test

pull method ที่แดงๆขึ้น interface และย้าย method ต่างๆให้เรียบร้อยแล้วเราจะได้ MVP ออกมาอย่างสวยงาม

เราขอยกตัวอย่างกันแค่ class เดียวก็น่าจะเห็นภาพกัน

ในตัวอย่างนี้เราขอเลือก BeerProductFragmentPresenter มาเป็นตัวอย่าง CUT: class under test กันครับ

และนี่คือเหตุผลว่าทำเราต้องคุยกันผ่าน interface เพื่อให้เวลาเขียน test สามารถ mock view ได้ง่าย
@Mock
BeerProductFragmentInterface.View mockView;
ส่วน tools ที่ใช้ mock class ต่างๆเราใช้ PowerMock ที่ mock ได้ทุกส่ิงอย่างบนโลก JAVA และใช้ Hamcrest เพื่อใช่ให้เราอ่าน test เข้าใจมากขึ้นด้วย
ซึ่ง class นี้อยู่ในระดับของ UnitTest ที่สนใจแค่ระดับ method เท่านั้นจะสังเกตุเห็นว่าเราจะ test ทุก method ที่ BeerProductFragmentPresenter มีทั้งหมด ว่ามีผลลัพธ์หรือมีการเรียก method ตามที่เราต้องการหรือไม่
ส่วนในระดับ Integration testing และต้วอย่าง test อื่นๆสามารถเข้าไปดูตัวอย่างใน Github ได้เลย
EXTRA: มอง Test ให้เป็น Layer ช่วยเพิ่มคุณภาพให้ Product เราอย่างไร
ส่วนนี้เราแถมให้ครับ เห็นคนในงานถามมาเยอะว่าตอนโค๊ดสดใช้ library อะไรช่วยตามนี้เลยครับ ส่วนที่ highlight จะเป็นที่ใช้ตอนโค๊ดสด ส่วนอันอื่นก็สำคัญ
EXTRA: Super plugin
วันนี้ไว้แค่นี้ก่อนครับเจอกัน blog หน้าาา

อย่าลืม share ให้มนุษย์ Android คนอื่นด้วยหละ 😎
KNOWLEDGE


Nonthawit
CEO | Engineer | Designer
เข้าใจการทำ Selector แบบ Ripple effect


Nonthawit
CEO | Engineer | Designer
20 สิ่ง ที่ได้หลังจากเป็น Android developer ที่ Nextzy 3 เดือน
บทความนี้แชร์ประสบการณ์ 3 เดือนแรกของการทำงานเป็น Android Developer ที่ Nextzy ครอบคลุมทั้งด้าน technical เช่น MVP architecture, Android Lifecycle, ProGuard, Git workflow และการเขียน Unit Test รวมถึงด้าน soft skill อย่างการสื่อสารกับทีม, การแชร์ความรู้, และการเขียนโค้ดให้ readable และยืดหยุ่น นอกจากนี้ยังสะท้อนวัฒนธรรมองค์กรที่เน้นทีมเวิร์ค การ review โค้ด และบรรยากาศการทำงานที่สนุกสนาน ซึ่งล้วนช่วยลด learning curve และพัฒนาทักษะได้เร็วกว่าการเรียนรู้คนเดียว
![[Tip/Trick] วิธีติดต่อกับ WebView ผ่าน JavascriptInterface มันเท่มาก](https://image.nextzy.tech/1_Aleix_TFC_7yz_Qh_Q_Sx_GV_Rqxw_a29e28219a.png)

Nonthawit
CEO | Engineer | Designer
[Tip/Trick] วิธีติดต่อกับ WebView ผ่าน JavascriptInterface มันเท่มาก