Build & Deployment Automation เรื่องสำคัญที่หลายคนมองข้าม

ก่อนจะเข้าเรื่อง ผมว่าผมเคยบ่นเรื่องของวิธีการ build และ run โปรดักท์ตัวนึงของบริษัทผมใช่ไหมครับ ? ข่าวดีคือมันกำลังจะถูกแทนที่ด้วยตัวใหม่กว่า ...

ข่าวร้ายคือ ... คู่มือการ build และ run เจ้าตัวใหม่เนี่ย หนา 75 หน้า ...

ครับ 75 หน้าครับ งานนี้ไม่ใช่เสร็จภายในสองชั่วโมงครับ บางคนทำสองอาทิตย์ยังไม่เสร็จเลยครับ ...

Build และ Deployment Automation

จากประสพการณ์ส่วนตัว (ตามข้างบนเลยครับ) ผมพบว่าหลาย ๆ คนมักจะมองข้ามความสำคัญของ Build Automation และ Deployment Automation ทุกคนจะคิดแค่ว่า ก็มีคู่มือให้แล้วก็เอาไปใช้สิ บางคนไม่รู้แม้กระทั่งว่ามันมีเจ้านี่อยู่บนโลกของเราด้วยซ้ำครับ

ว่าแต่มันคืออะไรล่ะ ?

Build Automation คือระบบการบิลด์ซอฟต์แวร์อัตโนมัติ (ตามชื่อเลย) คือเป็นเหมือนเครื่องมือที่ช่วยใช้ในการบิลด์ ทำให้เราไม่จำเป็นต้องจำคำสั่งซับซ้อน หรือต้องทำตามขั้นตอนที่ระบุเอาไว้ในคู่มือ แค่สั่งให้มันทำงานตามสคริปท์หรือไฟล์ที่เราสร้างขึ้น มันก็จะทำการทำตามขั้นตอนที่กำหนดเอาไว้ จากโค๊ดให้ออกมาเป็นซอฟต์แวร์นั่นเอง

หรืออย่างน้อย ๆ ก็ช่วยให้กระบวนการบิลด์มันทำงานง่ายขึ้นเท่านั้นเอง

ตัวอย่างคลาสสิคที่สุดน่าจะมาจากฝั่ง Linux ที่เราสามารถที่จะสร้างตัวซอฟต์แวร์ดได้หลังจากที่แตกไฟล์โค๊ดออกมาแล้ว ด้วยคำสั่งข้างล่าง ...

./configure
make

สำหรับ Deployment Automation ก็คล้าย ๆ กัน เพียงแต่เป็นขั้นตอนการติดตั้งละ ถ้าผมยกตัวอย่าง Linux ข้างบน หลังจากที่บิลด์เสร็จเรียบร้อย เราสามารถใช้คำสั่ง

make install

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

ส่วนลึก ๆ แล้วมันทำอะไรบ้างก็ขึ้นอยู่กับสคริปท์ที่เราเขียนไว้เท่านั้นเอง

ความสำคัญ

ทีนี้แล้วทำไมผมถึงมองว่ามันสำคัญ คืออย่างงี้ครับ สมมติว่าผมมีโปรเจคที่เขียนด้วยภาษา C++ ซึ่งการที่จะรันมันได้เนี่ยผมก็ต้องคอมไพล์มันก่อน เวลาคอมไพล์ก็ต้องใช้คำสั่งอย่าง ...

g++ -o ZipPicView MainFrame.cpp ImageViewerPanel.cpp FileEntry.cpp ZipEntry.cpp -lzip -lwxwidgets -lpng -lz -ltiff -llzma -ljpeg 

ยาว และ ยาก ... คือมีโอกาสที่ผมจะพิมพ์ผิดสูงมาก ว่าไหมครับ นี่คือทั้งโปรเจคมีอยู่สิบไฟล์ ถ้าไปเจอโปรเจคที่มีไฟล์เป็นหมื่นก็พิมพ์กันมือหงิกครับ วิธีที่ง่ายที่สุดในตอนนี้ก็คือเขียน shell script หรือ batch file เพื่อที่จะได้ไม่ต้องพิมพ์ยาว ๆ บ่อย ๆ แต่ก็จะยังมีปัญหาเรื่องของการดูแลรักษา ถ้าเกิดว่าใช้บรรทัดเดียวแบบข้างบน พอมีไฟล์เยอะ ๆ เข้าก็มึน มันจะเละไปหมดครับ เราก็ต้องค่อย ๆ เพิ่มตัวแปรเข้ามา ตรงไหนเป็นชื่อผลลัพท์ ตรงไหนเป็นแฟลก ตรงไหนเป็นชื่อไฟล์ เยอะแยะตาแป๊ะไก่

และเมื่อโปรเจคซับซ้อนถึงจุดนึงเราจะเจอว่ามันต้องทำหลาย ๆ ขั้นตอน อย่างอันนี้ผมต้องสร้างตัว resource file (.rc) เข้าไปเพื่อให้แสดงผลบนวินโดวส์ได้สวยงามยิ่งขึ้น ในขณะที่บน Linux นั้นจะต้องไม่ใช้ไฟล์นี้ เราก็ต้องสร้างสคริปท์ที่ซับซ็อนขึ้นไปอีก

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

ส่วนตัวผมพบว่าแม้กระทั่งการใช้ IDE ช่วย บางโปรเจคเราจะเจอขั้นตอนบางอย่างที่ IDE ช่วยไม่ได้ อย่างการก็อปปี้ resource file ให้ไปอยู่ในสถานที่ที่ถูกต้อง หรือการสร้างไฟล์คอนฟิก อะไรแบบนี้

พอมันความลำบากซับซ้อนมากมาย เราก็จะเจอปัญหาหลายอย่าง อย่างเราจะเจอคนที่ ...

  1. setup ครั้งเดียว ใช้มันไปเรื่อย ๆ ไม่เคยดูว่ามันความเปลี่ยนแปลงอะไรหรือเปล่า
  2. บางคนถึงขั้นไม่เคยอัพเดตโค๊ดเลย เพราะกลัวเซ็ตอัพพัง
  3. บางคนไม่ยุ่งกับโปรดักท์ตัวนี้อีกเลย เพราะเซ็ตยาก ทำยังไงก็รันไม่ได้ สุดท้ายก็ได้แต่โบ้ยให้คนอื่นทำ
  4. คนที่เซ็ตบ่อย ๆ ก็จะเจอปัญหา ใช้ได้บ้างไม่ได้บ้าง ทำซ้ำ ๆ มันต้องมีผิดสักครั้งสองครั้งบ้างแหละ

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

ส่วนตัวผมแนะนำว่า สำหรับโปรเจคใหม่ ให้เริ่มต้นจาก Build Automation และ Deployment Automation ก่อน ตั้งเป้าไว้ก่อนเลยว่าจะบิลด์อย่างไร จะดีพลอยอย่างไร แล้วค่อย ๆ เขียนโค๊ดให้อยู่ในกรอบที่ระบบจะรองรับได้ อย่าสร้างโค๊ดก่อนแล้วมาเขียน automation script ตามหลัง เสียเวลาครับ และมันจะทำให้เราไม่อยากเขียนอีกต่างหาก (ก็มันใช้ได้แล้วจะทำไปทำไม)

การตั้งเป้าหมายไว้ก่อนตั้งแต่แรกจะช่วยให้เรามีทิศทางเวลาที่เราจำเป็นจะต้องเพิ่มกลไกอะไรบ้างอย่างเข้าไปในโปรเจค สมมติว่า ซอฟต์แวร์เราต้องรองรับ client หลาย ๆ เจ้า โดยทุกเจ้ามี skin ของตัวเอง เราก็จะรู้ละว่าควรจะออกแบบระบบการโหลด resource อย่างไรให้อยู่ในกรอบที่กำหนดไว้แต่แรกว่าถึงตอน deploy แล้วจะอ่านไฟล์พวกนี้อย่างไร จะต้องทำอะไรบ้าง อะไรแบบนี้

ผมขอสรุปไว้เลยละกันนะว่า ระบบ build และ deployment automation นั้นมีส่วนสำคัญในการเพิ่มประสิทธิภาพในการพัฒนาโปรเจค โดยเป็นการทำให้ทีมงานโฟกัสอยู่กับตัวงานจริง ๆ อย่างการเขียนโค๊ด การทำรีซอรส์ การทดสอบ ไม่ใช่เรื่องเสียเวลาอย่างการบิลด์และการดีพลอย

ถ้าคุณกำลังจะเริ่มโปรเจคใหม่ ลองเริ่มจากการหา build automation ที่เหมาะสมกับโปรเจคมาลองก่อน

ถ้าคุณมีโปรเจคแต่ยังไม่ได้ใช้ build automation ก็ลองหาทางเอามาใช้สักระบบนึงนะครับ

ระบบที่ผมใช้ (และแนะนำ)

โปรเจค ZipPicViewWx ของผม ซึ่งเขียนด้วยภาษา C++นั้นใช้ CMake ครับ ตัวนี้ไม่ได้เป็นตัวบิลด์โปรแกรม แต่เป็นตัวกลางสำหรับสร้างไฟล์ที่ใช้ในการบิลด์อีกทีหนึ่ง ตัวมันรองรับทั้ง Makefiles และ Visual Studio solution มีความสามารถสูงและยืดหยุ่น สามารถเขียนตัวสคริปท์ที่ซับซ้อนได้สบาย ๆ ของผมจะใช้กับ MSYS2 นะครับ (สำหรับผม Visual Studio มันวุ่นวายชีวิตไปหน่อยครับ เอาง่าย ๆ แบบนี้ดีกว่า)

2015-11-13 03_44_41-~_ZipPicViewWx-build64

หลังจากนั้นก็สั่ง make ไป ... เราก็จะได้ตัวแอพลิเคชันสมใจอยากละครับ (warning ข้างล่างเป็นบั๊กของ wxWidget ครับ ปรกติผมมองว่า warning เป็น error ประเภทนึงอยู่แล้ว ไม่ปล่อยให้เหลือแบบนี้ แต่ว่าอันนี้ช่วยไม่ได้จริง ๆ)

2015-11-13 03_50_16-~_ZipPicViewWx-build64

ความเท่ห์ของมันอีกอย่างคือมันมาพร้อมกับซอฟต์แวร์อีกตัวที่ช่วยเรื่อง deployment ด้วย เรียกว่า CPack คือมันจะเป็นตัวสร้างตัวติดตั้งครับ แค่เรียกใช้โปรแกรมนี้มันก็จะสร้างตัวติดตั้งให้เลย

2015-11-13 03_52_33-~_ZipPicViewWx-build64

ผมใช้ Zip file บ้าน ๆ เพราะไม่ค่อยอยากให้ติดตั้งลงไปในระบบครับ

2015-11-13 03_53_31-C__msys64_home_Wutipong_ZipPicViewWx-build64_ZipPicView-DEV.0.0-win64.zip_ZipPic

รันแล้วเป็นแบบนี้ครับ :-)

2015-11-13 04_00_33-ZipPicView

ระบบที่ผมใช้ (และแนะนำ) #2

ข้างบนเป็นโปรเจคที่ผมเขียนด้วย C++ ก็เลยใช้ CMake ครับ ส่วนตัวผมใช้อีกตัวหนึ่งสำหรับ Java นั่นคือ Gradle

Gradle เป็นระบบ Build Automation ที่ค่อนข้างสมบูรณ์ในตัวมันเอง เราสามารถที่จะสั่งให้มันคอมไพล์โค๊ด สร้าง jar file (หรือ war file ในกรณีของ Web App) แล้ว Deploy เข้าไปในระบบได้เลยในคำสั่งเดียว (เท่ห์มาก !) ตัวมันเองยืดหยุ่นมาก เพราะว่าตัวสคริปท์ที่ใช้เป็นภาษา Groovy ที่ทำงานบน JVM จึงสามารถใช้คำสั่งทุกอย่างที่ Java 2SE มีให้คุณใช้เลยทีเดียว (ทำได้ทุกอย่างเท่าที่จะนึกออก) แค่เขียน Task ไปเรียกใช้งานเท่านั้นเอง

อันนี้ผมไม่มีตัวอย่างเพราะว่ามันอยู่อีกเครื่อง แต่ถ้าให้เล่าก็คือ ไอ้โปรดักท์ข้างบน (ที่บอกว่าโดนโละแล้วน่ะครับ) ผมใช้ task เดิม ๆ ที่ gradle ให้มา อย่าง เช่น

gradle JettyRun 

ซึ่งจะรัน Web Application ที่เราดึงโค๊ดลงใน Jetty ซึ่งเป็น Servlet Container ได้เลยโดยไม่ต้องติดตั้ง Tomcat

อีกตัวอย่างหนึ่งคือ task ที่ผมเขียนเองชื่อว่า buildResource โดยหลัก ๆ เป็นการเตรียมพวก resource file (ไฟล์รูปภาพ ไฟล์ xml และอื่น ๆ ) ก็แค่เรียก

gradle buildResource

จุดแข็งอีกอย่างของ gradle คือ task dependency ก็คือว่า ผมสามารถตั้งได้ว่า task B จะใช้ output จาก task A ดังนั้นต้องรัน A ก่อน อะไรแบบนี้ อย่างกรณีของ JettyRun นั้นผมเซ็ตให้มัน depend บน buildResource พอผมสั่งปุ๊บมันจะ buildResource ก่อน อะไรแบบนี้ครับ

อีกจุดหนึ่งที่น่าสนใจก็คือ dependency management กล่าวคือเราสามารถระบุในตัว build script ได้ว่าโปรแกรมเรามี dependency อะไรบ้าง ซึ่งเราก็ระบุแค่ direct dependency อย่างเดียวก็พอ พวก transitive ไม่ต้อง gradle จะไปดึงเอา library ที่ใช้จาก repository อย่าง maven central มาให้เอง พร้อมทั้ง transitive dependency ทั้งหมดที่จำเป็นต้องใช้ สมมติอย่างของผมใช้ slf4j ก็ระบุไปว่าใช้ตัวนี้นะ gradle จะไปดึง slf4j พร้อม dependency อื่น ๆ อย่าง log4j มาให้ด้วยนั่นเอง อะไรแบบนี้

อ้อ แล้วก็ ถ้าเกิดเรามี Tomcat หรือ Wildfire เราสามารถรัน task เพื่อที่จะ deploy ขึ้นไปได้เลยเหมือนกัน

เรียกได้ว่าสะดวกสุด ๆ ทำได้แทบทุกอย่างจากปลายนิ้วเลยทีเดียว

ที่สำคัญคือ task dependency นั้นทำให้เราไม่จำเป็นจะต้องรันที่ละ task ตามลำดับ ระบบจะเป็นคนจัดการตรงนี้เอง สะดวกสุด ๆ ครับ

แต่ gradle เองก็มีข้อจำกัดเหมือนกันครับ คือถ้าเรามี architecture ของระบบที่ซับซ้อนมาก ๆ อย่าง web app เราต้องใช้ database server หลาย ๆ ตัว (อย่าเพิ่งขำครับผมเพิ่งเจอกับตัว) และใช้แชร์กันไม่ได้ เพราะดันเก็บคอนฟิก เนี่ย gradle เองก็อาจจะไม่ตอบโจทย์ซะทีเดียว

เราอาจจะต้องใช้ application container อย่าง Docker ช่วย ผมเองกำลังศึกษาอยู่ครับ ไว้จะมาเล่าให้ฟังวันหลังนะ

Wutipong Wongsakuldej

Programmer, interested in frontend applications, music and multimedia.

Latest posts by Wutipong Wongsakuldej (see all)

Leave a Reply

Your email address will not be published. Required fields are marked *