Test Driven Development (TDD) คืออะไร?

Atikom Tancharoen
2 min readMay 16, 2017

--

ก่อนที่เราจะมาทำความรู้จักกับ TDD ว่ามันคืออะไร…เรามาดูรูปข้างล่างนี้กันก่อนดีกว่า

วิธีการวัดคุณภาพ Software ที่ดีที่สุด คือ การนับว่ามีคำอุทานหลุดออกมาจากปาก Developer จำนวนเท่าไรต่อนาที

เรื่องนี้มันเป็นเรื่องจริงมากๆ ที่บ่อยครั้งเหล่า Developer มักจะพูดคำอุทานออกมาดังๆ เพราะต้องเจอกับโค้ดที่ห่วย และมักมีความรู้สึกแบบนี้กับมันในทุกๆครั้ง(WTF) ซึ่งคุณสมบัติของการเขียนโค้ดที่ดีมันก็คือการเขียนอย่างไรให้มันเรียบง่ายที่สุด ซึ่งความเรียบง่ายนี่แหละมันทำยาก!!!

ยกตัวอย่างในกรณีของบ้านก็เช่นกัน ตอนใหม่ๆมันก็ดูดี ทนทาน และแข็งแรง แต่พอเริ่มมีรอยร้าวของกำแพง เจ้าของบ้านกลับไม่ได้ใส่ใจหรือดูแลมัน ซึ่งไม่นานมันก็ค่อยๆมีส่วนอื่นของบ้านเสียหาย และทรุดโทรมลงไปเรื่อยๆ จนในที่สุดก็กลายเป็นเหมือนกับบ้านร้าง ซึ่งถ้าจะซ่อมแซมก็คงซ่อมไม่ไหว…มันตลกตรง Software ก็เป็นแบบนั้นเหมือนกัน Developer หลายคนถูกมอบหมายหน้าที่ให้ดูแลระบบที่เราไม่ได้เป็นคนเขียนมันขึ้นมา ซึ่งในโค้ดชุดนั้นก็อาจจะถูกเขียนมาดีบ้างหรือแย่บ้าง พอมี requirement ใหม่ๆเข้ามา แทนที่จะ refactor code เพื่อที่จะซ่อมแซมมัน แต่ก็เลือกที่จะปะผุพอให้มันใช้งานได้ เพื่อให้มันผ่านๆไป มันเลยกลายเป็นความใส่ใจในงานใหม่ๆมากกว่างานที่ต้องไปยุ่งกับโค้ดเก่าๆ พอเราทำแบบนั้นงานที่เราทำมันก็กลายเป็นเหมือนสัตว์ประหลาดที่เราสร้างมันขึ้นมา และส่งต่อไปให้คนดูแลคนต่อไป (legacy code)

Legacy code is code without tests.

เราจะแก้ปัญหาของการปะผุเหล่านี้ได้อย่างไร?

เราสามารถใช้หลักการของการทำ Test Driven Development(TDD) ในการแก้ปัญหาเหล่านั้นได้ ซึ่งมันมีหลักการง่ายๆอยู่ประมาณ 3 ขั้นตอน

The development lifecycle

เริ่มต้นด้วยการเขียน Failing test…
เราจะยังไม่มี production code ซึ่งเราจะเริ่มจากการเขียน test ก่อน เพื่อพิสูจน์ให้มัน fail ตาม test ที่เราคิดไว้ว่ามันต้อง fail ซึ่งการเขียน test เราไม่จำเป็นที่จะต้องดักในทุกกรณี เพียงแต่เราเขียนให้มันพอเพียง และเพียงพอกับชิ้นงานในแต่ละชิ้นของเราก็พอ

เขียน Production code…
ขั้นตอนนี้เราจะเริ่มเขียน production code ซึ่งจะต้องทำให้ส่วนที่เราเขียน test ไว้ผ่านทั้งหมด โดยที่เราไม่จำเป็นที่จะต้องเขียน code ให้มันสวยหรูหรือดีเด่อะไรมากมาย ขอแค่ให้ test มันผ่านเท่านั้นก่อน

จัดการ Refactor code…
พอมาถึงขั้นตอนสุดท้ายก็จะง่าย เพราะโค้ดที่เราเขียนไว้ก่อนหน้านั้นเพื่อที่ให้มันรัน test ผ่าน ซึ่งมันจะเป็นโค้ดที่สั้นและง่ายพอที่เราจะนำเอาโค้ดตรงส่วนนั้นมาทำการจัดเรียงใหม่ ลดความซ้ำซ้อนลง หรือปรับ performance ของแอป หรือแม้แต่ปรับแต่ง UI

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

TDD is a software development technique in which automated tests are written iteratively alongside the production code.

TDD มีข้อดีอย่างไร?

ทำให้เราเขียนโค้ดที่จำเป็นเท่านั้น…
เราจะเห็นว่าหลักการเขียนโค้ดของ TDD แค่ต้องการให้เราเขียนเพื่อให้รัน test ผ่าน และถ้าต้องการเพิ่ม feature หรืองานใหม่เข้าไป เราก็จะต้องเริ่มจากการเขียน test ก่อนเสมอ

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

ง่ายต่อการ Refactor Code…
การเขียน test ก็เปรียบเสมือนกับเรามี document อยู่ในตัวระบบ ซึ่งถ้าเราต้องการที่จะ refactor code ตรงส่วนไหน ก็สามารถดูได้จาก test ที่สร้างไว้ ซึ่งจะทำให้เราเข้าใจระบบได้อย่างถ่องแท้มากขึ้น

เพิ่ม Test Coverage สูงขึ้น…
ซึ่งเรามั่นใจได้ว่า test ที่เราเขียนนั้นมันครอบคลุมกรณีใดบ้าง และไม่ครอบคลุมกรณีใดบ้าง

Debug ง่ายแบบสุดๆ…
เวลาที่เรารัน test ไม่ผ่าน เราจะสามารถรู้ได้ทันทีว่าส่วนไหนที่มันไม่ผ่าน โดยที่เราไม่ต้องมาเสียเวลากับการนั่งไล่โค้ดทั้งหมดเพื่อหาจุดบกพร่อง

ทำงานตาม Requirement…
หัวใจของการทำ TDD อีกอย่างหนึ่ง คือ การให้ความสำคัญกับ requirement ของชิ้นงานเป็นพิเศษ ซึ่งจะทำให้การเขียนโค้ดของเรามีจุดยืนที่ชัดเจน เพราะถ้าเราเขียนโค้ดไม่ตรงตาม spec ที่กำหนด ก็จะรัน test ไม่ผ่าน

แล้วข้อเสียของ TDD ละมีบ้างไหม?

ในช่วงแรกๆของการทำ TDD จะค่อนข้างช้า เนื่องจากเรายังไม่ชินกับความคิดที่ต้องคิดว่า “จะทำอะไร?…แล้วแก้ปัญหามันอย่างไร?…และจะเขียนมันอย่างไร?” ในบางครั้งเราอาจจะต้องใช้เวลาเพิ่มมากขึ้นกับงานที่เคยทำโดยใช้เวลาเพียงไม่นาน และบ่อยครั้งที่เราไม่เข้าใจปัญหาและเขียน test ทั้งๆที่ไม่เข้าใจ ส่งผลให้มันแทบไม่ได้ช่วยอะไรเราเลย แถมอาจจะส่งผลกับ production code ให้ผิดตามไปด้วยซะอีก…

สรุป…การทำงานแบบ TDD คือ การทำงานที่ต้องเริ่มจากการเขียน Specification ก่อนการเขียนโค้ดเสมอ แล้วเราค่อยมาโค้ดตาม spec ที่วางไว้ให้ผ่านก็ถือว่าจบ คิดง่ายๆการทำงานถ้าเราไม่ถาม requirement ของลูกค้า แล้วเราจะรู้ได้อย่างไรว่าเราควรทำงานอะไรส่งให้ลูกค้า….เหมือนกันกับ TDD ถ้าเราไม่กำหนด spec แล้วเราจะรู้ได้อย่างไรว่าโค้ดจริงๆที่เราควรเขียนต้องเขียนอะไร? แล้วมันเพียงพอต่อความต้องการของลูกค้าแล้วหรือยัง? …

--

--