Test Driven Development (TDD) by

30
Mar
2

ผมไปฟังพี่ @roofimon ในวัน Bug Day มา เลยเอามาแชร์ต่อ เนื่องจากปัญหาการ Develop งานแบบเก่าอาจเกิดปัญหาดังต่อไปนี้

  • ฝั่ง Programmer เขียน code มาแล้วส่งมาให้ Tester ปรากฏว่า Bug ตรึม Tester ก็โวยวายใส่ Programmer
  • Tester รายงานว่ามี Bug อะไรบ้างกลับไปให้ Programmer แล้วปรากฏว่า Programmer แก้ bug ตัวใหม่เสร็จ Bug ตัวเก่ากลับปรากฏขึ้นมาซ้ำทั้งๆ ที่แก้ไปแล้ว
  • เมื่อ Bug เกิดขึ้นหนึ่งครั้ง หาต้นตอของ Bug ยาก ไม่รู้เริ่มผิดตั้งแต่ตรงไหน ต้องมาพิมพ์ print ไล่ code ทีละส่วน
  • “เครื่องผมไม่เห็น bug เลย ทำไมเครื่องคุณ bug ล่ะ Test ยังไงเนี่ย”
  • “เมื่อวานยังไม่ Bug เลย ทำไมวันนี้มันพังตอน present ให้หัวหน้าดูได้(วะ)เนี่ย”
  • เมื่อเกิดปัญหาเช่น performance หรือต้องมีการแก้ไข Code ส่วน Core หลักที่ใช้งานทุกๆ ที่ จะไม่สามารถมั่นใจได้เลยว่าแก้ไปแล้ว Code เก่าที่อื่นจะ Bug หรือไม่
  • อื่นๆ อีกมากมาย

Test Driven Development (ต่อไปนี้ขอเรียก TDD) จะเข้ามาช่วยแก้ปัญหา หรือบรรเทาปัญหาเหล่านี้ลงได้ ซึ่งต้องมีการเขียน Unit Test (การทดสอบการทำงานของ Code ด้วย Code ทำให้สามารถสั่งรันแบบ automatic ได้) โดยมีหลักการดังนี้

  1. บังคับเขียน Unit Test ก่อนลงมือ Code จริง โดยพูดง่ายๆ ว่า Test = Requirement โดย Programmer ต้องเป็นผู้ลงมือเอง คนเดียวกับคนที่เขียน Code นั่นแหละ
  2. การจะเขียน Test ก่อนลงมือ Code ได้จำเป็นต้องรู้โครงสร้าง code มาก่อนแล้วคร่าวๆ โดยเฉพาะ Input และ Output ที่ต้องการ ส่งผลให้เกิดการวางแผนล่วงหน้าก่อนการเขียน Code
  3. ถ้าเขียน Test ไม่ได้ หรือเขียน Test ยาก แสดงว่า Code ของคุณยังไม่สละสลวยพอต่อการ Test (คำกล่าวจากท่าน dean4j) หรือพูดง่ายๆ ว่า Code คุณห่วยนั่นเอง! ต้องแก้ที่ Code ไม่ใช่ที่ Test
  4. การเขียน Test หลักๆ แล้วต้องมีมาก-น้อยแค่ไหนก็ขึ้นอยู่กับ Requirement ของลูกค้านั่นแหละ อย่าไปคิดแทนลูกค้า! เพราะเค้าอาจไม่ได้เห็นดีด้วยกับสิ่งที่เราเพิ่มเข้าไปเองทีหลัง
  5. เมื่อเขียน Test เสร็จแล้วค่อยลงมือ Code ตามปกติ เมื่อเขียนเสร็จก็สั่งรัน Test ได้เลยว่าผิด-ถูกอย่างไร
  6. เขียน Test เป็น Moduleๆ ก่อน และต้องเขียน Test ระหว่าง Module ที่มีการทำงานข้ามกันไปมาแยกกันด้วย เพราะเมื่อเกิดปัญหาจะได้รู้ว่า Bug ที่ Module ไหน หรือ Bug ตอนระหว่างจะคุยกันระหว่าง Module
  7. จะมี CI เป็น server ที่ set environment ไว้สำหรับ test แล้วคอยดึง code ไป test ทุกๆ วันให้แบบอัตโนมัติ เพื่อทดสอบว่า Code ที่เขียนขึ้นใหม่ไม่กระทบของเก่า โดย Programmer ไม่จำเป็นต้องสั่งเองให้เหนื่อย

บางคนอาจสงสัยว่า ทำไมเขียน Test ทีหลังไม่ได้ ทำไมต้องเขียนก่อน หรือให้ Programmer คนอื่นเขียน test ตามที่หลังได้ไหม อันนี้จากประสบการณ์ส่วนตัวของผมเอง จะมีข้อเสียดังนี้

  1. ถ้ามี Programmer คนอื่นมาเขียน Test ที่ตัวเองไม่ได้เป็นคน Code เอง ก็จะไม่อาจรู้ได้ว่า Code ส่วนไหนมีความสำคัญมากน้อยเพียงใด ที่สำคัญ Programmer ที่เป็นคน Code สามารถทิ้งขยะก้อนโตที่อ่านยากๆ ฝากเอาไว้อย่างไม่ใยดีได้อย่างง่ายดาย
  2. ถ้าเป็น Code ตัวเอง แต่มาเขียน Test ทีหลัง ปัญหาที่เกิดก็ง่ายมากครับ “ก็มันเสร็จแล้วทำไมต้องเขียน Test อีก” พูดง่ายๆ ว่าขี้เกียจนั่นเองครับ 55 และถ้าต้องเขียน code ที่ไม่ได้ Design เผื่อสำหรับ Test แต่แรกนี่ก็เป็นความยากระดับมหาโหดเลยทีเดียว
  3. บางครั้งการเขียน Code Programmer มักจะเผื่อโน่นนี่ที่ไม่ได้ใช้เอาไว้หลากหลายมาก เมื่อเขียน Test และต้องเขียนให้ได้ Coverage 100% ก็จะยิ่งขี้เกียจหนัก เช่นมี if สัก 10 ทีก็ไม่ไหวแล้ว ถ้าเขียน Test ก่อน ด้วยความขี้เกียจของ Programmer เองจะทำให้มี Test เฉพาะที่จำเป็นเอง และ Code ส่วนที่ไม่ค่อยจำเป็นจะไม่ถูกเขียนขึ้นตั้งแต่แรก ประมาณว่า “ถ้ามันไม่ได้ใช้แล้วเขียนเผื่อไว้ทำไมให้เหนื่อย”
  4. หากเขียน Test ทีหลัง และ Code นั้นเป็น Code ที่ถูกสร้างขึ้นมานานแล้ว Programmer แม้จะเป็นคนเขียนเองก็ตาม จะเกิดอาการ “ลืม” ได้ง่ายมากๆ ครับ พอลืมก็ต้องมานั่งอ่านทำความเข้าใจ Code อีกรอบ เสียเวลามากๆ เลยทีเดียว

ทีนี้เรามาสรุปข้อดีว่าถ้ามี Unit Test ที่เขียนก่อนแล้วจะมีผลดีอย่างไรบ้าง

  1. แม้ว่าจะต้องเสีย Overhead เรื่องเวลาไปก่อนกับการเขียน Test แต่เมื่อมีการกลับมาแก้ภายหลังแล้วจะสามารถแก้ได้อย่าง “มั่นใจว่าจะไม่ Bug” มากขึ้นมากเลยละครับ เพราะมีตัว Test ที่สั่ง run ปุ๊บก็รู้เลยว่ากระทบ Code เก่าหรือไม่ ทำให้ประหยัดเวลาในการ Test เรื่องเดิมๆ ของ Tester ไปได้มากด้วย ลดงาน Tester ได้เยอะครับ
  2. สามารถระบุตำแหน่งที่เกิด Bug ขึ้นได้อย่างง่ายดายด้วย Test ที่เขียนไว้ การใช้เวลาในการหา Bug จะลดลงเป็นอย่างมาก
  3. เมื่อเกิดการเปลี่ยน Environment การใช้งานขึ้น เช่นย้ายไปรันที่เครื่องอื่น แค่สั่งรัน Test ก็จะรู้ต้นตอของปัญหาได้ไม่ยากเลย ลดปัญหาเถียงกันไปเถียงกันมาว่าใครผิดระหว่าง Tester และ Programmer ลงได้มาก
  4. ถ้ามีการแก้ไข code แม้เพียงเล็กน้อยในสถานการณ์กระชั้นชิดเช่นการ present ให้หัวหน้าดู แก้เสร็จก็รัน Test ได้เลย ก็จะลดความเสี่ยงหน้าแตกต่อหน้าหัวหน้าได้มาก
  5. เมื่อมีการใช้งานไปสักระยะ และมีความจำเป็นต้องแก้ไข Code ส่วน Core หรือต้องมีการปรับปรุง performance ก็สามารถมั่นใจได้ว่าแก้ไขไปแล้ว performance ดีขึ้นโดยไม่ใช่ว่าทำให้ bug เพิ่มขึ้นตาม
  6. Code ที่ออกมามีคุณภาพสูง อ่านง่าย เพราะไม่งั้นเขียน Test ไม่ได้ เมื่อมีการส่งต่อ Code ให้คนอื่นทำต่อก็จะเกิดปัญหาน้อยลง
  7. เมื่อ Programmer คนอื่นต้องการศึกษาวิธีการใช้งาน module ใดๆ ว่าต้องส่งค่า Input อย่างไรเข้าไป และจะได้ Output อย่างไรออกมาก็สามารถดูจาก Test ที่เขียนไว้ได้เลย สามารถ Copy ตัวอย่าง Code จาก Test มาปรับแก้ได้ทันที ดีกว่าอ่าน Manual ตัวหนังสือเยอะๆ เสียอีก :)

สรุปว่าเมื่อ Programmer เขียน Test แล้ว Code ก็จะอ่านง่ายขึ้น Bug จะน้อยลง Tester จะงานน้อยลง Programmer แก้ Bug ได้เร็วขึ้น Tester ก็จะด่า Programmer น้อยลง ลดความขัดแย้งระหว่าง Programmer-Tester และ Programmer-Programmer(ที่ทำงานร่วมกัน) ลงได้มาก และองค์กรจะสงบสุข ยอดขายพุ่งกระฉูด และโลกก็จะสงบสุข สวัสดีครับ :)

Enjoy this article?

Consider subscribing to our RSS feed!

2 ความเห็น

  1. Kennes
    23:43 on May 19th, 2011

    ชอบตรงโลกก็จะสงบสุข นี่แหละครับ ฮ่าๆๆ
    ตอนนี้กำลังจะหัดใช้ TDD มาพัฒนางานโปรเจคใหม่ๆน่ะครับ
    ชอบมากๆเรื่อง Methodology , Practice อะไรพวกนี้น่ะครับ
    ขอบคุณสำหรับบทความครับ ^_^

ใส่ความเห็น

RSS feed for comments on this post

 เราชนะรอบ 4 | ยืมเงิน 3000 ด่วน | แอพกู้เงิน | แอพเงินด่วน | สินเชื่อออนไลน์อนุมัติทันที | Site Map | กู้เงินก้อน | กระเป๋าตัง | thisshop และ ยืมเงินฉุกเฉิน 5000 ด่วน