Tag Archives: Continuous integration

Martin Fowler at Singapore, June 2012

เมื่อวันพฤหัสฯ ที่ผ่านมา ThoughtWorks ได้ทำการประกาศตัวว่าเปิดสาขาที่ Singapore แล้ว ด้วยการนำ Martin Fowler Chieft Architecture Scientist ผู้ที่มีชื่อเสียงมากที่สุดคนหนึี่งในด้าน Agile มาพูดให้ฟัง งานแบบนี้ส่วนตัวก็ไม่พลาดไปติดตามแน่นอน และยังได้พบพี่ๆจากไทย ทั้งพี่แป๋ม พี่จั๊วและพี่เก๋ ที่สองคนหลังเค้าบินมาเพื่องานนี้โดยเฉพาะ!!

การพูดของเค้าครั้งนี้ แบ่งออกเป็น 3 เรื่อง ซึ่งล้วนแล้วแต่เป็นเรื่องที่เค้าได้เขียนลง blog ของเค้าแล้วทั้งนั้น ใครติดตาม blog เค้าอยู่เป็นประจำคงเคยได้อ่านผ่านตามาบ้าง แต่กับการที่เค้ามาอธิบายให้ฟังก็ทำให้เข้าใจและจับประเด็นสำคัญได้ดีมากขึ้นอยู่เหมือนกัน

เริ่มด้วยเรื่อง NoSQL DATA MODELS

เค้ากำลังเขียนหนังสือที่มีชื่อว่า NoSQL Distilled อยู่ เลยได้ดึงเนื้อหาบางส่วนออกมาพูดให้ฟัง

  • เค้าเรียกการรวมกันของ NoSQL ประเภท Key-Value และ Document Store ว่า Aggregate-Oriented Database ประเด็นของมันคือการเก็บกลุ่มของข้อมูลที่ได้ทำการ denormalize แล้วนั่นเอง ทำให้ถ้าเราเข้าถึงกลุ่มของข้อมูลนั้นผ่าน key ปกติจะทำได้เร็วและถูกกว่า relational database แต่เมื่อไหร่ที่เราต้องการเข้าถึงข้อมูลใน pattern อื่นก็จะทำได้แย่กว่า relational database
  • (จากรูป) งานที่เหมาะมากๆ กับ NoSQL คือ custom fields และ non-uniform data แต่เรื่อง migration ที่หลายคนพูดว่าเป็นข้อดีหนึ่งของ NoSQL นั้น เค้าไม่เห็นด้วย เค้ามองว่าในการเก็บข้อมูลเราก็จะมีการคิดถึงรูปแบบในการจัดข้อมูลซึ่งหมายถึงมี implicit schema อยู่ดี

เรื่องต่อมาคือเรื่อง 2 Kinds of software projects

  • เค้าจัดกลุ่มการพัฒนาซอฟแวร์บนโลกนี้ออกเป็น 2 กลุ่ม คือ strategic software และ utility software
  • Strategic software (S) คือ software ที่สร้างข้อได้เปรียบในเชิงการแข่งขันทางธุรกิจ
  • Utility software (U) คือ software ที่นำมาใช้ช่วยการดำเนินธุรกิจ
  • เป้าหมายของ S คือ innovation และ speed, เป้าหมายของ U คือ ถูก
  • S ควรทำเอง, U ควรซื้อสำเร็จ
  • ความเสี่ยงของ U คือการทำพลาด, ความเสี่ยงของ S คือการไม่ทำ

เรื่องสุดท้ายคือ Continuous Integration และ Continuous Delivery

  • Source code version control ในปัจจุบันยังทำได้แค่การ merge text แต่ยังมีการ merge sematic ที่ทำไม่ได้ หากนึกตัวอย่างไม่ออกลองนึกถึงสถานการณ์ ที่เพื่อนร่วมทีมของเราเปลี่ยนการทำงานของ method ที่เราเรียกใช้อยู่ซึ่งทำให้ผลลัพธ์ของ method นั้นเปลี่ยนไปจากตอนที่เราเขียนโปรแกรมเรียกใช้มัน
  • สิ่งที่พอจะทำให้เราตรวจสอบ sematic merge ได้มีแค่ test เท่านั้น
  • พอการ merge มันสร้างความลำบากทำให้เราไม่อยาก merge กันเท่าไหร่ เลยหนีไปทำ feature branch กัน
  • แต่ feature branch ก็ยังไม่ช่วยให้การ merge มันง่ายขึ้น การแก้ปัญหานี้ที่ถูกต้อง คือควรจะ merge กันบ่อยๆ จากรูปจะเห็นว่าเค้าจำลองเหตุการณ์ของการแก้ไขที่ไม่ตรงกันของ 2 developer ด้วยลูกศร และจุดที่เราพบว่าการแก้ไขของคนสองคนขัดกันด้วยจุดแดง จะเห็นว่าถ้ารวม code กันบ่อยๆ ก็จะเจอจุดบกพร่องเร็วกว่าการแตก branch มาก
  • การรวม code กันบ่อยๆ นั่นคือแนวคิดที่เป็นหัวใจของ Continuous Integration นั่นเอง
  • ส่วน Continuous delivery คือ กระบวนการการนำซอฟแวร์จากจุดที่ dev commit ไปอยู่ในจุดที่พร้อมจะ release แบบอัตโนมัติ เหลือไว้เพียงแค่การกดปุ่ม release จากการเห็นชอบของฝ่าย business เท่านั้น
  • วิธีที่ใช้ในการทำให้เกิด Continuous delivery คือ deployment pipeline คือสร้างลำดับการรัน test หลายๆ ขั้นขึ้นมา เนื่องจาก test แต่ละระดับมีความเร็วช้าและความครอบคลุมต่างกัน จึงวางกลุ่ม test ที่รันได้เร็ว (จากการที่ตัด dependency ออก) ไว้ก่อน เพื่อให้สร้าง feedback ได้เร็วที่สุด หากผ่านชั้นที่เร็วไปได้ ก็ไปสู่ในชั้นที่ test ระหว่างส่วนมากขึ้น แต่รันได้ช้าลงต่อไป
  • ไม่ควร compile code ใหม่ระหว่างขั้น เพื่อลดความผิดพลาดในการ test จากความแตกต่างของสภาพแวดล้อมที่ใช้ในการ test
  • พี่จั๊วถามคำถามด้วยว่า ถ้าไปเจอปัญหาใน test ขั้นหลังๆ ควรทำอย่างไร เค้าก็ตอบว่าให้ไปเพิ่ม unit test ที่ครอบคลุมมากขึ้น
Advertisements

CITCON Asia 2012 at Singapore

มันย่อมาจาก Continuous Integration Testing Conference ซึ่งเริ่มตั้งแต่เมื่อวานตอนเย็น และวันนี้ทั้งวัน มีคนไทยมาร่วมงานนี้ด้วยอีก 2 คน คือ พี่ @kluak110 กับพี่ @sinapam ครับ

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

Openspace

หัวข้อโดยคร่าวๆ ก็เป็นตามนี้  http://citconf.com/wiki/index.php?title=CITCONAsia2012Sessions แต่ในระหว่างวันก็โดนผู้ร่วมงานสลับสับเปลี่ยนกันตามใจ เลยทำให้งานจริงๆ ต่างจากนี้ไปบ้าง บางหัวข้อคนพูดไม่อยากพูดแล้วเพราะเวลาชนคนที่เค้าอยากเข้าฟัง ก็ไปถอดออกจากบอร์ดเลยก็มี

Session ที่ผมเข้าฟังก็มีตามนี้ครับ

CI In A System Of Systems Environments 

หัวข้อนี้คนพูดทำอยู่ในสายเกี่ยวกับการวางระบบเน็ตเวิร์คของ Australia การทำ test ของงานเค้ามันดูยากมากเลย ทั้งต้อง test คลุมตัวอุปกรณ์ของบริษัทอื่นๆ ที่เอามาใช้ด้วย ทั้งมีอุปกรณ์เก่าที่ใช้งานอยู่แล้วอีกไม่รู้กี่พันกี่หมื่นตัว ฟังแล้วคิดไม่ออกเลยว่าจะทำยังไงให้มันมี feedback cycle ที่สั้นๆ ได้ยังไง

TDD vs BDD
หัวข้อนี้คนเริ่ม topic ตั้งใจจะนำไปคนละทางกับบทสนทนาที่เกิดขึ้นจริงในห้องเลย เค้าอยากคุยเรื่องใครใช้สไตล์การเขียน test แบบไหนใคร stub, mock, fake object แต่มันกลายไปเป็นหัวข้อที่พูดถึงเรื่องต่อไปนี้แทน

  • สไตล์การพัฒนาโปรแกรม outside-in, middle-out(?) แล้วก็ inside-out ซึ่งก็พอได้ข้อสรุปว่างานส่วนมากเหมาะกับ outside-in เพราะช่วยให้เราลดการเขียน code แล้วไม่ได้ใช้น้อยลง แต่มีงานบางอย่างที่มีคุณสมบัติว่า requirement ไม่ได้สำคัญมากเท่า technical limitation ซึ่งงานแบบนั้นก็เหมาะกับ inside-out มากกว่า
  • พบว่า ATDD, BDD, User story driven development และ Specification by Example มันคือสิ่งเดียวกัน มันคือ TDD + business requirement นั่นเอง ข้อเสียของการเกิดเหตุการแบบนี้คือ แต่ละค่ายทำ tool ของตัวเองที่สุดท้ายแล้วมันก็คือสิ่งเดียวกัน เช่น robotframework (ของค่าย ATDD) และ cucumber (ของค่าย BDD) ซึ่งทำให้เสียโอกาสในการพัฒนาไป

CI In A Lean Startup World ผู้พูดเสนอแนวคิดดังนี้

  1. Continuous Integration เป็น process เพื่อทดสอบว่าการรวมกันของ code เราสามารถทำได้
  2. Continuous Deployment เป็น process ต่อจาก CI เพื่อทดสอบว่า deployment ที่เกิดจาก code เราสามารถทำงานได้ไม่มีปัญหา
  3. Lean Startup เป็น process ต่อจาก CD เพื่อทดสอบว่า product ที่เกิดจาก code เรา user ชอบ

ซึ่งในโลกความเป็นจริง แล้วมันก็ไม่สามารถเทียบได้โดยตรงแบบนั้น มีคนนึงแสดงความเห็นว่าเพราะในขั้น Lean Starup เราทดสอบกับ user ซึ่งคือคนจริงๆ ที่เป็นสิ่งที่มี state มีการจดจำสิ่งที่เคยเกิดขี้นมาก่อน แต่ใน CI กับ CD เราทดสอบกับ test ที่เราพยายามเขียนให้ไม่มี state ผลที่ได้จาก Lean Statrup จึงไม่ได้เที่ยงตรงและ revert ได้เหมือน CI, CD แต่อย่างไรก็ตาม พบว่าการพยายามสร้างความสัมพันธ์นี้เป็นความคิดที่น่าสนใจทีเดียว

Pair Programming Done Right
session นี้ผมเข้าเพราะที่บริษัทผมทำ pair programming อยู่แล้ว และผมมีคำถามคาใจอยู่

pair programming ทำเพื่อป้องกัน bus effect (รถบัสชนคนที่รู้ code นั้นคนเดียวตาย)
คำตอบของคนที่ไม่ชอบ pair มีสองเรื่องที่ถูกตอบบ่อยมากคือ เบื่อขี้เกียจรออีกคน และอีกคนไม่รอทำอะไรไม่รู้
ผู้พูดเสนอ pattern การทำ pair programming มี 3 แบบ

  • Ping-pong A เขียน 1 test, B ทำให้ test ผ่าน และเขียนอีก 1 test ส่งกลับให้ B, … เหมาะสำหรับคู่ pair ที่เท่าเทียมกัน
  • Board and mouse คนรู้มากกว่าใช้ mouse คนรู้น้อยกว่าใช้ keyboard ใช้แก้ปัญหาคนรู้ไม่รอคนไม่รู้
  • pattern ที่สาม(ฟังชื่อภาษาอังกฤษไม่ออก) เหมือนกับการซ้อมตี Baseball โดยคนรู้เขียน test อย่างเดียว คนไม่รู้เขียน production code อย่างเดียว ใช้สำหรับให้คนรู้สามารถสร้างกรอบทางเดินให้คนไม่รู้ได้

Frameworks Dont Make Testing Easy Enough
session นี้เหมือนรวมญาติ เพราะคนที่ร่วมเป็นคนที่ทำๆ งานด้วยกันเกินกว่าครึ่งห้อง

คนเริ่มหัวข้อเค้าแสดงความเห็นว่า framework ที่เค้าได้เคยใช้ (Rails และ Android) มันรัน test ช้า ทำให้มีปัญหากับ TDD cycle เค้าเลยได้ลองคิดว่าจะพัฒนา หรือทำใหม่ควรจะต้องทำอะไร

แต่พอคุยกันไปมาพบว่าตัว Rails จริงๆ ตอนใช้แรกๆ ก็เร็วเพียงพอ แต่มันมาช้าเพราะ gem ที่ load เข้าไปเยอะๆ มากกว่า การจัดการระบบ module ที่ดีขึ้นอาจจะช่วยได้ แต่ก็จะไปขัดกับเจตนาที่ให้ feature ทั้งหลายมันออกมาแบบ out-of-the-box อย่าง magic อีก

ปิดงานด้วยการพูดรายคนว่าใครมี AHA moment อะไรในงานนี้กันบ้าง

ชอบมากครับงานนี้ ไม่เคยไป conference ไหนที่ไม่มีช่วง session ที่รู้สึกไม่อยากเข้าห้องไหนเลยมากก่อน

 

ขออภัยที่ไม่ได้ลงรูป ไม่ได้ถ่ายเยอะเท่าไหร่ และที่ถ่ายมาเบลอมาก
สามารถติดตามรูปได้จาก Facebook ของ Stanly คนจัดประจำของ Agile Singapore meetup
และจาก Facebook ของ agile66 group ที่พี่ๆ เค้าถ่ายละกัน (กด previous)

Trunk Based Development

จริงๆ แล้วเรื่องนี้เป็นส่วนหนึ่งของ Continuous Integration ที่เคยเขียนถึงไปแล้ว แต่วันนี้จะลงรายละเอียดไปอีกหน่อย

การจะทำ CI ให้ประสบความสำเร็จนั้น ทีมพัฒนาจำเป็นจะต้องมีวินัยด้วย ไม่ใช่ว่าแค่ตั้ง CI server, Jenkins(Hudson) หรือ CruiseControl ขึ้นมาแล้วจะบอกว่าตัวเองทำ CI แล้ว ระเบียบวินัยที่ว่านี้มีหลายด้าน วันนี้จะมาว่าด้วยเรื่องของ source code version control ครับ

Trunk Based Development คือ อะไร?

มันคือ สไตล์การจัดการ source code version control ที่เอื้อให้เกิดการรวม code ตั้งแต่ช่วงเริ่มต้น และตลอดการพัฒนา โดยวิธีการคือ นักพัฒนาทุกคน ไม่ว่าจะทีมใหญ่แค่ไหน อยู่ที่เดียวกัน หรืออยู่ต่างจังหวัด ต่างประเทศกันก็ตาม ทุกคนต้อง commit code เข้าที่ branch เดียวเสมอๆ (และบ่อยๆ)

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

“ไอ่ที่มี SVN branch เดียว ทุกคน commit ไปรวมกันหมด ชิบหายมานักต่อนักแล้ว มันเอาไว้ให้โปรเจ็คเล็กๆ ง่ายๆ พัฒนาคนเดียว หรือไม่่กี่คนเค้าใช้กัน”

ข้างบนนี้คือ ความคิดแวบแรกของผมที่ได้ยินคอนเซปนี้เลยครับ แต่พอได้รู้ถึงเหตุผล และผลเสียของการแตก branch ผมก็เริ่มเข้าใจมากขึ้น

  • ลองคิดถึงเวลาต้อง merge code ที่ไม่ได้ merge กันมาเป็นเวลานาน มันยากขนาดไหน ต้องใช้เวลานานขนาดไหน ส่วนตัวผมเคยถึงขั้น ไม่สามารถ merge กันได้ ต้องแยกกันไปเลยก็มี
  • เคยมั้ยที่คุณไม่กล้าแก้ refactor code ให้ดีขึ้นเพราะกลัวจะ merge กับเพื่อนแล้วมีปัญหา
  • เคยมั้ยที่เรากำลังจะทำงานๆ หนึ่ง แล้วมันต้องใช้ code ที่เพื่อนร่วมทีมของคุณทำไปแล้ว แต่ไม่ได้ merge เข้ามา หรือยัง merge เข้ามาไม่ได้
  • ฯลฯ

ปัญหาเหล่านี้หละครับ เป็นส่วนหนึ่งที่ทำให้เกิดความล่าช้า และความซับซ้อนในการพัฒนาโดยไม่จำเป็น

ตามคำกล่าวที่ว่า “if it hurts, do it more often” ถ้ามันยากนักก็ทำมันบ่อยๆ ซะ มันก็จะง่ายขึึ้นเอง ถ้าการ merge code ทำให้ชีวิตเราลำบาก ทำไมเราไม่ merge มันบ่อยๆ หละ

อยากให้ลองกันดูครับ ไม่ยากอะไร แค่ กำหนดให้นักพัฒนาทุกคนที่พัฒนาบน source code ชุดเดียวกัน อย่างน้อยคนละครั้งต่อวัน แล้วสิ่งดีๆ จะตามมา

ถ้าบริษัทที่มีนักพัฒนาเยอะระดับ Google เค้าทำได้ เราก็ต้องทำได้ครับ

 

FAQ

แล้ว ถ้า code คนอื่นมาทำทั้งโปรเจ็คพังไปหมดจะทำไงหละ?

– การป้องกันการพังด้วยการ ไม่เอา code มารวมกัน มันเป็นการแก้ปัญหาที่ไม่ตรงจุดนะครับ กรณีนี้ผมก็คงต้องแนะนำให้นักพัฒนาทุกคน มีความรับผิดชอบต่อ code ตัวเอง(อีกวินัยหนึ่งที่จำเป็นต่อ CI) ด้วยการเขียน test อย่างครอบคลุมครับ

แล้วถ้า feature ที่ทำอยู่มันทำงานร่วมกับ feature ปัจจุบันไม่ได้เลยหละ จะทำยังไง?

– เรื่องนี้ผมรู้ว่ามี 2 เทคนิคที่เอามาช่วยแก้ปัญหานี้ได้ครับ อันนึงคือ Feature toggle (Feature bit) อีกอันนึงคือ Branch by abstraction ถ้ามีโอกาส (และความอยาก) จะมาเล่า 2 เรื่องนี้ให้ฟังครับ

อย่างงี้ DVCS เท่ๆ ของเราทั้ง Git ทั้ง Mecurial ก็หมดความหมายไปเลยสิ?

– จริงๆ แล้วประเด็นของวิธีนี้ ไม่ได้กำหนดว่าห้ามสร้าง branch ครับ แต่ต้องมีวินัยนำกลับมา trunk เร็วที่สุด ตัว DVCS ยังให้ประโยชน์แก่เราในกรณีอื่นๆ อีกมากมาย ไม่ใช่แค่สร้าง branch ได้ cheap เพียงอย่างเดียวครับ DVCS ของเรายังเท่อยู่ครับ

Continuous integration คือ อะไร

เรื่องนี้ไม่ใช่เรื่องใหม่ครับ แต่ผมลอง search google ด้วย ประโยคเหมือนชื่อโพสแล้วไม่มีผลลัพธ์ดีๆ ภาษาไทยใน 2 หน้าแรกเลย ก็เลยมาเขียนให้อ่านกัน

เนื้อหาในโพสนี้ เขียนจากประสบการณ์ส่วนตัว ประกอบกับ แปลและสรุปจาก Continuous Integration ครับ

ใครอ่านตรงไหนไม่รู้เรื่องแล้วอยากให้อธิบายเพิ่มเติมก็ถามมาได้นะครับ

ปัญหา

  1. การ merge code ระหว่าง dev ยาก ใช้เวลานาน
  2. Dev พัฒนาอยู่บน code ส่วนที่ถูกคนอื่นลบหรือเลิกใช้ไปแล้ว
  3. Dev ไม่กล้าแก้ code มากนัก เพราะกลัวจะกระทบคนอื่นและกลัว bug ส่งผลให้ code เน่าง่าย
  4. เมื่อมีคนมาถามถึงความเสถียรของโปรแกรม ตอบได้แค่ว่า “น่าจะใช้งานได้”
  5. ผลจากความผิดพลาดของการ merge ถูกพบเมื่อ code ขึ้นไปอยู่บน production แล้ว
  6. Code บน dev environment ไม่สามารถ deploy บน production environment ได้ หรือได้แต่ใช้เวลานาน
  7. Regression test ใช้เวลานาน และนานขึ้นเรื่อยๆ ตามความแก่ของโปรเจ็ค
  8. Management รู้ความก้าวหน้าของโปรเจ็คได้แค่จากปากคำของ Dev
  9. เมื่อเจอ bug ในระบบเวอร์ชั่นเก่ากว่าที่พัฒนาอยู่ ใช้เวลา setup เครื่องเพื่อทดสอบ bug นาน

วิธีแก้ไข

0. Dev ทุกคนเขียน unit test และมี acceptance test คลุมฟังก์ชัน

  1. ทำงานชิ้นเล็กๆ merge บ่อยๆ ทำเสร็จชิ้นนึง merge ทันที 
  2. พัฒนาบน branch เดียวกันทุกคนในโปรเจ็ค
  3. ตรวจสอบว่า test รันผ่านก่อน commit/push ขึ้น repository กลาง
  4. มีระบบ automate สำหรับดึง source code มา build , นำลงเครื่องที่เหมือนเครื่อง production ที่สุด และรัน test ใหม่อีกรอบ ทุกครั้งที่ source code มีการเปลี่ยนแปลง แจ้งผลลัพธ์อย่างชัดเจน ทันที
  5. ทำ versioning ไฟล์ build 
  6. แก้ test ที่พังอย่างรวดเร็ว ให้ความสำคัญการแก้ test ที่พังเป็นอันดับต้นๆ

ผลลัพธ์

  1. merge code กันเครียดน้อยลง
  2. ได้ code ที่พร้อมใช้งานตลอดเวลา regression test time เข้าใกล้ 0
  3. ไม่เสียแรงเปล่าไปทำงานบนส่วนที่เลิกใช้ไปแล้ว
  4. ได้ code ที่ไม่มี bug ที่เคยแก้ไปแล้วเกิดซ้ำ
  5. พบ bug ได้เร็วขึ้น ทำให้หาสาเหตุได้ง่ายขึ้น
  6. Dev กล้าที่จะ refactor code มาขึ้น
  7. โปรแกรม version ใหม่ๆ ออกเร็วขึ้น
  8. ไม่ต้องมาเครียดในการ deploy ขึ้น production โดยเฉพาะอย่างยิ่งวันท้ายๆ กำหนด release
  9. Dev เครียดน้อยลง รู้สึกว่าทำงานแล้ว “เสร็จ” จริงๆ
  10. Management เห็นความก้าวหน้าการทำงานของ dev ในแต่ละวันด้วยผลลัพธ์การ test ที่เพิ่มขึ้นทุกวันๆ
  11. สามารถ build ระบบขึ้นจาก version ใดก็ได้อย่างรวดเร็ว

สิ่งที่จำเป็น

  1. วินัยของ Dev
  2. การตัดแบ่งงานเป็นชิ้นเล็กๆ ต้องใช้ความสามารถในด้านการเขียนโปรแกรมให้เป็น modular และ refactoring
  3. เทคนิคการเขียน test ทำให้เทสได้เร็ว ครอบคลุม
  4. การทำระบบ build ให้ทำงานได้อย่างรวดเร็ว

เพิ่มเติม

บางบริษัทไปไกลถึงขั้นหลังจาก build และ test แล้ว นำขึ้น deploy บน production เลย ตามอ่านได้จาก keyword Continuous Deployment, Continuous Delivery ครับ

ของแถม

Tools for Continuous Integration at Google Scale ด้านเทคนิคเค้าไปไกลกว่าที่ผมเขียนมามากครับ