Tag Archives: TDD

สอน TDD, Rails ผ่าน Remote Pair Programming

ผมจำไม่ได้แล้วว่าผมแปะประกาศรับคนที่สนใจ TDD, Ruby, Rails มา pair ด้วยกันไว้ที่แถบด้านขวาของบล็อกและใน profile ของผมตั้งแต่เมื่อไหร่ น่าจะซักครึ่งปีได้ละมั้ง ตลอดเวลาที่ผ่านมาไม่เคยมีใครติดต่อมาเลยจนกระทั่งเมื่อ 3 อาทิตย์ก่อน มีผู้ขยันและกล้าหาญติดต่อมาคนแรก น้องวินปี 1 ลาดกระบังฯ ติดต่อมาว่าอยากจะศึกษา TDD เรานัดตอนหัวค่ำของวันนึงใช้ Google Hangout คุยกัน

ก่อนหน้านี้เคย remote pair ที่ไม่ใช่ตอนทำงานอยู่บ้างกับพี่รูฟ แต่ครั้งนี้จะเป็นครั้งแรกที่จะ remote pair กับคนที่ไม่เคยเขียน TDD มาเลย ช่วงนั้นเห็นพี่รูฟและหลายๆ คนเล่นโจทย์ Fizzbuzz กัน ก็เลยเอาโจทย์นี้แหละ

วันนั้นเราใช้ tmux/vim กัน โดยน้อง ssh เข้ามาที่เครื่องผม นี่คือโค้ดที่ได้จากวันนั้น

Continue reading

Advertisements

My view of TDD

ได้โอกาสกล่าวถึง practice ที่ผมชอบที่สุด และใช้บ่อยที่สุดในชีวิตทำงานช่วงนี้ TDD (Test-drive development)

เค้าว่ากันว่า TDD เป็น practice ของคนที่ไม่เก่ง คนที่มักจะทำอะไรผิดพลาด ถ้าคุณมีความสามารถมากพอ ที่จะเขียน code ออกมารวดเดียวใช้งานได้ คุณอาจจะมองว่า TDD เป็นกระบวนการขัดขวาง flow ในการทำงานของคุณ แต่ผมมักจะผิดพลาดครับ

ตอนนี้ผมติดมันมาก อาการของการลงแดงคือ ถ้าต้องไปเขียนอะไรที่ไม่ได้เขียน test ไว้ก่อน แทบจะทุกๆงานผมจะผิดจุดนั้นจุดนี้ เสมอๆ และมักจะระแวง ไม่ค่อยมั่นใจว่าสิ่งที่เราทำ ทำงานได้ดี

TDD คือ อะไร มีขั้นตอนตามตำราอย่างไร ผมขอไม่กล่าวถึง แนะนำให้ติดตาม series ของพี่ @roofimon ทาง code-66 เองละกัน

ส่วน blog นี้ผมจะขอกล่าวถึง motivation ของ TDD ในมุมมองของผม และเล่าถึง TDD ที่ผมทำอยู่ทุกๆ วันเป็นอย่างไร

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

แนะนำว่าถ้าจะลอง TDD ควรศึกษามาก่อนระดับหนึ่ง พอจะเริ่มใช้ให้ใช้ให้เต็ม stream เริ่มกับ project ใหม่ของท่านตั้งแต่เริ่มน่าจะสะดวกที่สุด เพราะการทำ TDD ครึ่งๆ กลางๆ มีความเป็นไปได้สูงมากที่ท่านจะได้รับประสบการณ์ที่ไม่ดีกับไป

“ผมคิดว่าใช้ TDD แล้วได้อะไร”

  • Focus ปัญหาที่ต้องการได้ง่ายขึ้น ก่อนจะลงมือเขียนโปรแกรมอะไร เราจำเป็นต้องคิดก่อนว่าเราจะเขียนทำไม การเขียน test ก่อน เทียบเท่ากับการจดสิ่งที่เราต้องทำออกมาก่อนเริ่มลงมือทำนั่นเอง
  • รู้ว่าโปรแกรมที่เขียน ถูกหรือผิดอย่างรวดเร็ว ความสำคัญของเรื่องนี้ เกี่ยวกับเรื่อง high feedback ที่ผมเขียนไว้ครับ
  • Loosely coupling software ถ้าท่านเขียน unit test อย่างถูกวิธีท่านจะได้ โปรแกรมที่ไม่มีความผูกพันธ์ระหว่าง unit (class, component) สูงเกินไปนัก (เพราะถ้าสูงแสดงว่าท่านไม่ได้เขียน unit test แล้ว) ซึ่งเป็นผลให้เวลาท่านแก้อะไรกับส่วนไหน ก็จะกระทบกับส่วนอื่นๆ ไม่มากนัก
  • ป้องกัน overengineer และ premature optimization โปรแกรมเมอร์อย่างเราๆ มักมองข้าม shot เห็นปัญหาข้างหน้าที่จะเกิดขึ้น 3 ชั้นได้ แต่ความจริงคือ สำหรับโปรแกรมเมอร์ที่มีประสบการณ์ไม่เพียงพอ มันมักจะผิด การทำอะไรในสิ่งที่ไม่ได้ใช้ ยิ่งถ้าเป็นส่วนที่ใช้พลังงานไปเยอะ จะทำให้เราเซ็งและเสียกำลังใจไปมาก
  • ความมั่นใจว่า software ยังทำงานได้ และรับรู้ถึงปัญหาในส่วนของโปรแกรมที่เคยทำงานได้แล้วมันพังได้อย่างรวดเร็ว ด้วย test ที่เราเขียนไว้ก่อนจะเริ่มลงมือ code ถ้าเขียน test after เราอาจจะเขียนไม่ครอบคลุม ขี้เกียจเขียน
  • กล้าที่จะแก้ไขโปรแกรม requirement มักเปลี่ยน, วิธีที่ดีมักไม่มาในครั้งแรก, ความมั่นใจในการจะแก้ไข code ในมุมมองของผม เป็นสิ่งที่จำเป็นมากต่อการพัฒนา software ขนาดใหญ่และใช้เวลานาน
  • มีตัวอย่างการรัน code สำหรับคนอื่นที่มาดูโปรแกรมของเรา จาก test นั่นเอง (ถ้าไปใช้ BDD ก็จะได้ excutable specs มาอีกต่างหาก)
  • ลดภาระของสมอง จากหลายๆ เหตุผลด้านบน ทำให้ท่านย้ายหลายสิ่งที่เดิมทีเคยทำด้วยสมอง มาไว้ที่ test

“ผมทำ TDD อย่างไร”

  1. เขียน Acceptance test (black box, user view point to whole component) ของ function ที่กำลังจะทำ
  2. เขียน unit test (white box, isolating) จากจุดที่ทำให้ acceptance test ไม่ผ่าน
  3. เขียน code ให้ test ผ่าน
  4. วนกลับไปทำ 2-3 เพิ่มจนกว่า 1 จะผ่าน แล้วก็เขียน 1 อันต่อไป
  5. ผม refactoring เรื่อยๆ ไม่ค่อยได้ทำตาม practice เท่าไหร่ อาจจะเป็นเพราะใช้ TDD มาซักระยะ trick มันอยู่ที่ พยายามอย่าทำอะไรค้างเอาไว้ ไม่ว่าจะแก้อะไรต้องรีบกลับมาทำให้ test รันผ่านไว้เสมอ แล้วจะดีเอง
  6. เวลาเจอ bug อะไร ทั้งเจอเอง หรือมีคนอื่นเจอ ควรจะมี test ไม่ว่าจะเป็น acceptance หรือ unit คลุม bug ตรงส่วนนั้นไว้เสมอ ก่อนจะลงมือแก้ เพื่อที่มันจะไม่เกิดซ้ำ

“ปัญหาของ TDD”

ปัญหาสำคัญเลยของ TDD คือ test maintainance นอกจากจะเสียเวลาไปเขียนแล้ว พอเราแก้อะไร  test เรายังพังอีก ก็ต้องแก้กันไป ใช้เทคนิคต่างๆ ช่วยให้ pain น้อยลง แต่ก็อยากให้เห็นข้อดีจุดหนึ่งว่า test ที่พัง เป็น reminder ให้แก่เราได้ว่าสิ่งที่เราแก้ไปจะต้องครอบคลุมเรื่องอะไรบ้าง เพราะฉะนั้นต้องพยายามอย่าเขียน test ซ้ำซ้อน ในจุดเดิมๆ ให้มากนัก เพราะเสียพลังงาน และเวลาครับ