App versioning กำหนดอย่างไร และมีกี่แบบ ?

Yuttana Kungwon
Jitta Engineering
Published in
3 min readSep 28, 2022
Photo by Scott Rodgerson on Unsplash

คงปฏิเสธไม่ได้ว่าหมายเลขเวอร์ชั่นบนซอฟแวร์ต่าง ๆ นั้นใกล้ชิดกับชีวิตประจำวันของเรามาโดยตลอด ยกตัวอย่างเช่นเวอร์ชั่นของระบบปฏิบัติการต่าง ๆ ที่เราใช้งานกัน อาทิเช่น Android 13 / iOS 16 ที่เรามักได้ยินกันจนคุ้นหู และคนทั่วไปก็เข้าใจไปในทิศทางเดียวกัน ว่ามันคือหมายเลขของการปรับปรุง ปรับเปลี่ยน และไม่ใช่เฉพาะ Software engineer เท่านั้นที่เข้าใจ

ในโลกของการพัฒนาซอฟแวร์นั้น หมายเลขเวอร์ชั่นมีความจำเป็นมากในการทำงาน เพราะหลาย ๆ ทีมที่ทำงานร่วมกัน ไม่ว่าจะเป็นทีม Engineer, QA, Product, CX ต้องใช้ความสามารถของเวอร์ชั่นมาอ้างอิงสิ่งต่าง ๆ พวกเขาใช้หมายเลขเหล่านี้มาอ้างอิงการวางแผนและเตรียมการ release, การ track stability, ประสานงานเพื่อสนับสนุนผู้ใช้ และอื่น ๆ

ดังนั้นการกำหนดเวอร์ชั่นของซอฟแวร์นั้นเป็นสิ่งที่สำคัญมาก แต่เคยมีคำถามมั้ยครับ ว่ามาตราฐานในการกำหนดหมายเลขต่าง ๆ เหล่านี้มันมีที่มาที่ไปอย่างไร หรือพวกเราตี๊ต่าง กันขึ้นมาเองว่า

“Release หน้าเป็นเวอร์ชั่น 2.0.0 ก็แล้วกัน แก้โค๊ดไปเยอะเลย”

หรือ

“เวอร์ชั่นนี้ผมขอเป็นเวอร์ชั่น 1.9.1 นะ แก้บั๊คนิดหน่อยเอง”

…ซึ่งนั่นมันคือการใช้ความรู้สึกมาพิจารณา ฟังดูแล้วมันก็ไม่ผิดนัก แต่มันมีวิธีที่ถูกต้องมากกว่านี้มั้ย ชัดเจนกว่านี้มั้ย ที่จะช่วยให้เราตัดสินใจว่าจะกำหนดเวอร์ชั่นของแอปฯ อย่างไร

ทำไมถึงต้องกำหนดเวอร์ชั่นให้เป็นมาตราฐาน

  • ช่วยสื่อสาร และปรับปรุง development workflow ให้ดีขึ้น
    กว่าจะได้มาในแต่ละ release แอปฯ ต้องถูกจัดการด้วยคนหลายฝ่าย ไม่ว่าจะเป็น Engineer, QA, Product, CX ซึ่งพวกเราจะต้องสื่อสารด้วยเลขเวอร์ชั่นเสมอ
    การกำหนดหมายเลขเวอร์ชั่นให้เป็นมาตราฐาน จะช่วยลดข้อผิดพลาดได้มาก โดยเฉพาะช่วง release cycle ที่เป็นช่วงเวลาสำคัญ เช่น ใช้อ้างอิงในการรายงานปัญหาต่าง ๆ จากการทดสอบ (ticket) ซึ่งการที่เรามีวิธีมาตราฐานในการกำหนดเวอร์ชั่น จะช่วย improve development workflow ให้ดีขึ้นอีกขั้น
  • ช่วยให้ debug ปัญหาได้ง่ายขึ้น
    หากเรามีการกำหนดเวอร์ชั่นที่ดี เราจะสามารถตรวจสอบย้อนหลังเพื่อ debug ปัญหาได้โดยง่าย เช่น มีรายงานว่าพบ app crashed ใน เวอร์ชั่น 2.0.0 (ก่อนหน้านี้คือ 1.9.1) นั่นทำให้เราสามารถตรวจสอบการเปลี่ยนแปลงระหว่างเวอร์ชั่นได้ง่าย
  • Improve release pipeline (CI/CD)
    ในบางงาน การกำหนดเวอร์ชั่นที่มีมาตราฐาน มันก็ไปช่วยปรับปรุง workflow หรือ release pipeline ได้ด้วยเช่นกัน เพราะเราสามารถอ้างอิงหมายเลขเวอร์ชั่นเพื่อ trigger การทำงานของ automated workflow ของเราได้ อย่างที่ jitta ทำอยู่

เมื่อพอเข้าใจ benefits ของการกำหนดเวอร์ชั่นแล้ว เรามาลองดูกันว่า โดยทั่วไปแล้ว เรามีมาตราฐานในการกำหนดเวอร์ชั่นกี่แบบกันนะ

Semantic Versioning (SamVer)

Semantic Versioning — วิธีกำหนดเวอร์ชั่นยอดฮิต สุดคลาสสิค และมั่นใจว่าหลาย ๆ คนจะได้พบกับการกำหนดหมายเลขเวอร์ชั่นในรูปแบบนี้ โดย SamVer standard จะกำหนดและแบ่งการปรับปรุงด้วยหลักทศนิยมสามตำแหน่ง เช่น 1.0.1 และจะมี pattern แบบนี้ <major>.<minor>.<patch>

สำหรับบนแอปฯ แล้ว แต่ละหลัก จะกำหนดการเปลี่ยนแปลงที่แตกต่างกัน คือ

Major version — จะเพิ่มเวอร์ชั่นหลักนี้ เมื่อมีการเพิ่มฟีเจอร์ใหม่ เปลี่ยนแปลง UX/UI และรูปแบบการใช้งานอย่างมาก กระทบกับผู้ใช้ส่วนใหญ่ (ยกเครื่อง renovate กันประมาณนั้น)

Minor version — จะเพิ่มเวอร์ชั่นหลักนี้ เมื่อมีการเพิ่มฟีเจอร์ใหม่ แต่ไม่ยุ่งกับ core concept หรือ fundamentals ของ product

Patch / Hotfix version — จะเพิ่มเวอร์ชั่นหลักนี้ เมื่อมีการปรับปรุงแก้ไขข้อบกพร่องต่าง ๆ ของแอปฯ

Calendar Versioning (CalVer)

Calendar Versioning — เป็นอีกรูปแบบหนึ่งของ SamVer นับว่าเป็นอีกสายพันธ์ในการกำหนดมาตราฐานของเวอร์ชั่นก็ได้ ซึ่ง CalVer จะเน้นใช้เวลาในการกำหนดเวอร์ชั่น แทนการปรับปรุงเปลี่ยนแปลง content เพื่อปรับเวอร์ชั่น

เพื่อให้เข้าใจง่าย ๆ CalVer จะใช้วิธีแสดงวันที่ในการ release เป็นเลขเวอร์ชั่น เช่น v2022.9.26 หมายถึง release เมื่อวันที่ 26 เดือน 9 ปี 2022 หรืออีกแบบที่เห็นกันบ่อยในโลกของ mobile app คือการ combine กันระหว่างเวลาและหมายเลขบิลต์ เช่น 2022.2.1 หมายถึง แอปฯ รุ่นที่ 2 ของปี 2022 ด้วย build version 1

ความแตกต่างระหว่าง CalVer กับ SamVer คือ ความแตกต่างด้วยเวลาของการ release กับการเชื่อมโยงโค๊ดในการเปลี่ยนแปลงบางอย่าง

ในโลกของ mobile app การกำหนดเวอร์ชั่นด้วยวิธี CalVer ก็เป็นวิธีที่นิยม และใช้ผสม ๆ กันระหว่าง SamVer และ CalVer ถ้าแอปฯ นั้นมีการร่วมมือกันด้วยทีมขนาดใหญ่ และในทุก ๆ ทีมก็มีการ release feature กันอย่างต่อเนื่อง โดยไม่ได้มีลำดับในการรอ release (release-cycle) เช่น มีทีมที่คอย operate release train หรือบริหารจัดการ feature flag เพราะรถไฟไม่เคยรอเรา และ feature flag ต่าง ๆ พร้อมเปิดปิดได้เสมอ การตัดสินใจใช้ SamVer อาจทำให้สูญเสียความรวดเร็วในการ release ออกไปเลย หรืออย่างแย่ คือทำให้ทุกอย่าง stuck ไปเลยก็ได้ จะเห็นได้ว่า SamVer จะไม่สำคัญอีกต่อไป ถ้าเราใช้รูปแบบการ release แบบนี้ เพราะทีมมองเห็นผลลัพท์ของเวอร์ชั่นที่อ้างอิงด้วยเวลาเป็นหลัก

ผมมีตัวอย่างเล็กน้อยมาให้ดู บนโลกแห่งความจริง ที่เห็นชัดที่สุดน่าจะเป็น Spotify ที่ใช้การกำหนดเวอร์ชั่นด้วยมาตราฐานนี้

Spotify — จะใช้วิธีเพิ่มเวอร์ชั่นแพตช์ทุก ๆ อาทิตย์ และจะเปลี่ยน minor เมื่อครบ 99

Spotify Version History

Version Extensions

นอกจากการกำหนดเวอร์ชั่นหลักแล้ว ยังมีการกำหนดเวอร์ชั่น ในเวอร์ชั่นอีก โดยเฉพาะ mobile app ซึ่งมีความพิเศษเพราะมีการ release ที่บ่อยครั้ง เช่นการปรับปรุง build เพื่อเป็นตัวเลือกในการ release แต่ไม่ได้เปลี่ยนแปลงเวอร์ชั่นหลัก (release candidate)

บางที version extensions อาจไม่สำคัญสำหรับผู้ใช้ แต่จะสำคัญกับทีมพัฒนาเป็นอย่างมาก บนมาตราฐานของ SamVer และ CalVer นั้น อนุญาตให้เพิ่ม “extensions” ต่อท้ายเวอร์ชั่นหลักของเราได้ ซึ่งมันจะช่วยให้เราสามารถแยกแยะได้ง่ายขึ้นด้วยสิ่งนี้ ซึ่งการเติม extensions ในเวอร์ชั่นนั้น มีหลายวิธีด้วยกัน เช่น

Build Number (บางทีเรียกว่า Build Revision)

ใช้กันมากที่สุด โดยเฉพาะแอปฯ ที่มีการ build บ่อยครั้ง หรือบางทีม build ทุกคืน ทีละหลาย ๆ ครั้ง ซึ่งการเติม extention ในลักษณะนี้ไม่มีการกำหนดตายตัวว่าต้องเป็นเลขอะไร โดยปกติ Xcode จะใช้วิธีการ increase build number ให้เรา โดยส่วนตัวแล้ว jitta เอง เราจะใช้ timestamp เป็นตัวกำหนด เช่น v4.5.6(1664370200)

Commit Hash

เป็นอีกวิธีที่น่าสนใจ เพราะสามารถ debug ได้ง่าย ด้วย commit hash ที่ระบุใน extension โดยตรงเลย (v1.5.4.de98909f) แต่เราแค่จะไม่รู้ว่า build นี้สดใหม่ขนาดไหน ต้องไปตามเองเอง

Flag
การใช้ flag เป็น extension version (เช่น -alpha, -beta, -pre-release) ก็เป็นอีกวิธีหนึ่ง แต่จะแตกต่างจากวิธีข้างต้น เพราะวิธีนี้จะสื่อสารถึงความ stable ของแอปฯ มากกว่ามุมมองของการพัฒนา

แล้วควรใช้แบบไหน ?

มาถึงส่วนสุดท้ายนี้ การเลือกใช้ให้ถูกวัตถุประสงค์นั้น ขึ้นอยู่กับบริบทของการ release และ development life-cycle ของเราด้วย

โดยทั่วไปแล้ว หากมี release cycle ที่ชัดเจน milestones ชัด การเลือกใช้ SamVer ก็เป็นสิ่งที่ดี และมีความชัดเจนมากในแง่ของการสื่อสารและการ release ในแต่ละ version

อีกนัยหนึ่ง หากมีทีมพัฒนาที่ใหญ่ และปล่อยฟีเจอร์ตลอดเวลา มี team operate release train ใช้ featue flag เป็นสำคัญ ซึ่งมักจะเจอปัญหา “feature bump” กันอยู่บ่อย ๆ การเลือกใช้การกำหนดเวอร์ชั่นแบบ CalVer ก็จะดีกว่า ของใครของมัน แต่มากันคนละเวลา

สุดท้ายนี้ หวังว่าสิ่งนี้จะมีประโยชน์กับผู้ที่อยู่ในสายงาน development และช่วยส่งเสริมให้ทีมสื่อสารกันได้ดีมากขึ้น เพื่อร่วมกันพัฒนาซอฟแวร์ที่ให้มีประสิทธิภาพมากขึ้นครับ

--

--