android-legacy
ระหว่างเตรียมเอกสารสำหรับการแบ่งปันเรื่อง Automated testing for Android app
เกิดคำถามที่น่าสนใจว่า
เราจะจัดการและรับมือกับ Legacy code ของ Android app อย่างไรดี ?
เนื่องจากหลาย ๆ คนน่าจะกำลังเผชิญชะตากรรมนี้อยู่

สำหรับ Android developer ลองให้ความเห็นสิว่า จะทำอย่างไรดี ?

ในการพัฒนาระบบงานต่าง ๆ นั้น

เราเคยแก้ไข code ของระบบงานเดิมให้ดีขึ้นไหม ?
ส่วนใหญ่ตอบได้เลยว่า ไม่
เราจะทำใหม่ก็ต่อเมื่อขึ้นระบบงานใหม่เท่านั้น
ดังนั้น ถ้าคุณมาพัฒนาระบบเดิมต่อ
จะพบว่า เราเกือบไม่สามารถพัฒนาต่อได้เลย
ไม่สามารถ extend code ต่าง ๆ ได้เลย
ทำได้แค่ตัดแปะ หรือ copy and paste code เดิมมาทำ
หรือบางครั้งนำมาจาก internet อีก !!

ดังนั้นถ้าเพิ่มคนเข้ามาช่วยทำงาน มันน่าจะดีนะ
แต่ผลที่ตามมามักตรงกันข้ามเสมอ
นั่นคือภาระที่ต้องอุ้ม ที่ต้องสอนกันอีก !!

และมักเป็นแบบนี้มาอย่างเสมอต้นเสมอปลาย ไม่เคยบิดพลิ้ว
เพราะว่า มันคือธรรมชาติที่ทำกันเป็นปกติ

แต่ผมมั่นใจว่า มันเป็นสิ่งที่ผิดปกติอย่างมาก !!

บางคนบอกว่า เนื่องจากไม่มี Unit test ไงล่ะ ?

หรือมี Unit test น้อยเกินไปไม่เพียงพอ
ดังนั้นจึงต้องเขียน Unit test เพิ่มเข้าไปทั้งหมด

คำถามคือ
คุณรู้ไหมว่า การเขียน Unit test เข้าไปใน Legacy code มันเป็นเรื่องที่ยากลำบากมาก ๆ ?
ดังนั้นอย่าไปเขียนเลย
ส่งต่อไปให้ทีม QA/Tester เป็นคนทดสอบเถอะนะ !!

คำถามคือ เราไม่ได้แก้ไขที่ต้นเหตุกันเลยใช่ไหมนะ ?
ดังนั้น เรามาแก้ไขปัญหาที่ต้นเหตุกันดีไหม ?

ขอแนะนำขั้นตอนดังต่อไปนี้

1. แนะนำแนวคิดของ Continuous Integration (CI)
ให้สมาชิกในทีมรู้และเข้าใจ
และทำการสร้าง CI Server
เพื่อนำมาใช้ build, test และ packaging ระบบงานแบบอัตโนมัติ

2. ทำการ configuration ของ Andrid project ใน Android Studio
เพื่อให้พร้อมสำหรับการนำแนวคิดของ
Test-First และ Test-Driven Development (TDD) มาใช้ในการพัฒนาระบบงาน
เช่น Unit test ด้วย JUnit 4 และ UI test ด้วย Espresso เป็นต้น

3. ทำการเขียน Unit test เล็ก ๆ สำหรับ Legacy code หรือ code เก่า
จากนั้นลองทำการทดสอบ
และนำขึ้นไปทำงานบน CI Server

4. ทำการสอน พาทำ และ แสดงตัวอย่างการเขียน Unit test ให้ทีม
เพื่อทำให้ทุกคนมีความรู้ความเข้าใจเกี่ยวกับ Unit test
และการทำงานของ CI Server
ที่สำคัญคือ ให้เห็นประโยชน์ของสิ่งที่กำลังจะทำ

5. ทำการเพิ่ม Code coverage เข้าไปในระบบงาน
จากนั้นให้ทีมกำหนดเป้าหมายของ Code coverage
ตัวอย่างเช่น 5-10% ก่อน เพื่อเสริมสร้างกำลังใจ

6. เพิ่ม Espresso หรือ UI test เข้ามา
เพื่อเพิ่มมิติของการทดสอบเข้าไป
เนื่องจาก Unit test ไม่ได้บอกว่า App จะสามารถทำงานได้นะ !!
แต่เขียนเท่าที่จำเป็นเท่านั้น
เนื่องจากใช้เวลาในการทดสอบนานนั่นเอง
และนำขึ้นไปทำงานบน CI Server

7. ทำการเขียน Unit test เฉพาะ feature ใหม่ ๆ หรือ Bug เท่านั้น
Code ใหม่ ๆ ก็ให้เขียน Unit test คลุมซะ
ยิ่งใช้แนวคิดของ Test-Driven Development (TDD) ไปเลยยิ่งดี

แต่ถ้าต้องทำงานร่วมกับ code ชุดเดิม
ก็ให้เริ่มนำแนวคิด Test double มาใช้งาน
เช่นการ Mock และ Stub เป็นต้น
เพื่อแยก code ระหว่างชุดเก่าและชุดใหม่

โดยรวมแล้วคือ ของใหม่อย่าให้เพิ่ม ของเก่าก็ค่อย ๆ ลดลงไป
แล้วชีวิตจะดีขึ้นเรื่อย ๆ

8. พยายามแยก code เก่าออกมาจากระบบงานให้ได้มากที่สุด
ตัวอย่างเช่นแยกออกมาเป็น library และ interface เป็นต้น
เพื่อลดการแก้ไข code เก่า
นั่นคือ ลดผลกระทบจากการเปลี่ยนแปลงนั่นเอง

9. พยายามลบ code ที่ไม่ได้ใช้งานออกไป !!
ปล. เราจะรู้ได้อย่างไรล่ะ ?

10. ทำการเขียน Unit test ใน code ที่แยกออกมา และ Refactor code
นั่นคือการปรับปรุง code เก่า ๆ
เพื่อความมั่นใจ จำเป็นจะต้องเขียน Unit test ให้ครอบคลุม
หรือให้มีค่า Code coverage ประมาณ 70-80% ขึ้นไป

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

กฎเหล็ก !!
อย่าแก้ไข code เก่า เมื่อทำการเพิ่ม feature ใหม่ โดยเด็ดขาด (Open/Closed Principle)
ให้พยายามแยก code เก่าออกมาจาก code ใหม่
ตัวอย่างเช่น การสร้าง interface มากั้นการทำงาน เป็นต้น
แต่ถ้าต้องแก้ไขจริง ๆ ให้เขียน Unit test คลุมซะ

จากนั้นให้ทำการ Refactor code เก่าซะ
ซึ่งจำเป็นต้องมี Code coverage ที่สูงมาก ๆ นะ
เพื่อทำให้คุณ และ ทีมมั่นใจต่อการแก้ไข code นั่นเอง

สำหรับ Android developer ลองให้ความเห็นสิว่า จะทำอย่างไรดี ?