First day of TDD

ผมตั้งใจไว้ว่าจะเขียน Swift Tutorial มาตั้งแต่ปีที่แล้ว จบถึงบัดนี้ก็ยังไม่ได้ออก ตอนที่ 1 สักที ด้วยเหตุผลหลายประการ เล่าไปมันก็เหมือนการแก้ตัวน้ำขุ่นๆมากกว่า  แต่ก็นั่นแหละเอาเป็นว่าที่ผมไม่ได้เขียนออกมาสักตอนเนี่ย นั่นก็เพราะสาเหตุที่สำคัญ 2 อย่างคือ

  • รู้สึกว่าตัวเองยังไม่เก่ง และมีความรู้แตกฉานมากพอ
  • เอาเวลาไปศึกษาเรื่องอื่นเพิ่มเติมเยอะ

ประการแรกคือ รู้สึกยังไม่เก่ง .. หลายคนอาจจะถามว่า เห้ย แบบผมนี่ยังไม่เก่งอีกเหรอ … ใช่ครับผมบอกตรงๆ ยังไม่เก่งมากพอ อ้าวถ้าเก่งไม่มากพอ แล้วคอร์ส Swift ที่เปิดสอนไปละ สอนได้ยังไง ? ก็ตอบง่ายๆครับว่า คือหลังจากที่ผมสอนจบไป ผมรู้สึกว่า ไอ้ที่สอนๆไปเนี่ย มันยังไม่ดีพอ .. หลายๆอย่างผมยังไม่สามารถอธิบายให้คนที่มาเรียนมองเห็นภาพชัดเจนได้ .. ผมก็มาถามตัวเองว่า แล้วทำไมเป็นอย่างนั้น .. มันก็ได้คำตอบว่า เพราะเรายังไม่เก่งพอ .. ก็แค่นั้นเองครับ ดังเช่นที่ ไอสไตน์ได้บอกว่า

“ถ้าคุณไม่สามารถอธิบายสิ่งใดอย่างง่ายๆได้ แสดงว่าคุณยังไม่เข้าใจสิ่งนั้นดีพอ” — Albert Einstein

คำว่า “เก่ง” มันก็ตีความหมายต่างกัน สำหรับคุณ ผมอาจจะเก่ง .. แต่สำหรับผมแล้วกลับประเมินว่าตัวเองยังไม่เก่งมากพอ .. ก็เลยคิดว่า เราต้องฝึกอีกสักพักให้แน่ใจก่อน แล้วค่อยไปสอนคนอื่นน่าจะดีกว่า. แต่รับรองได้ว่า อีกไม่นานครับ ผมจะเขียน Swift ให้อ่านแน่นอน

ประการที่สองคือ เอาเวลาไปศึกษาเรื่องอื่น .. เรื่องที่ผมกำลังศึกษาอยู่ตอนนี้ก็คือ Test Driven Development หรือ TDD นั่นเอง .. ถ้าใครไม่เคยได้ยิน TDD ก็จะขออธิบายง่ายๆก็คือ เป็นกระบวนการ ในการพัฒนาโปรแกรม รูปแบบหนึ่ง ที่จะต้องเขียนโค้ดสำหรับการทดสอบ หรือ unit test ขึ้นมาก่อน .. หืมมม อะไรนะ เขียน test ก่อนเขียนโค้ด ?.. ฟังดูมันอาจจะโคตรประหลาดและขัดกับความรู้สึก หลายคนอาจจะยังสงสัยว่า มันทำได้จริงๆเหรอ จะทำได้ยังไง ที่จะเขียน test ขึ้นมาก่อนเขียน code .. เชื่อผมเถอะ ว่ามันทำได้ .. ตอนแรกๆ ผมก็คิดแบบนี้แหละว่า .. บ้าป่าวว่า ใครจะเขียน unit test ก่อนที่จะเขียน code

ทำได้ครับ ด้วยหลักการง่ายๆคือ  Red, Green , Refactor

Red

อันดับแรกคือ Red หรือ สีแดง มันมาจากการที่เราให้ unit test ทำงาน แล้วผลลัพธ์ที่ได้แจ้งว่า การทดสอบนี้ไม่ผ่าน โดยทั่วๆไป IDE อย่าง XCode , Eclipse หรือ Visual Studio ก็จะใช้สีแดงเพื่อแจ้งเตือน  ในกระบวนการนี้จะประกอบไปด้วย สองขั้นตอนคือ อย่างแรกคิดก่อนว่า โปรแกรมที่เรากำลังจะเขียนนั้น ทำอะไรได้บ้าง และในขั้นตอนที่สองก็เขียน unit test เช่น สมมติว่า จะเขียนฟังก์ชั่น add ไว้สำหรับบวกเลข ก็เขียน unit test ก่อนเลยว่าเมื่อเรียกฟังก์ชั่น add( 2, 3 ) นั้น ค่าที่ได้ต้องเท่ากับ 5 โดยที่ยังไม่ต้องไปเขียนฟังก์ชั่น add เลย เมื่อเขียน unit test เสร็จแล้วจากนั้นก็ทดสอบเลย

ซึ่งแน่นอนว่า มันต้อง fail

ใช่ถูกต้อง มันต้อง fail สิ เพราะเรายังไม่ได้เขียนโค้ด add สักบรรทัดเลยนี่ถูกไหม ?

.. อ้าว แล้วจะเขียนให้มัน fail ทำไม ?

Green

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

Refactor

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

แล้วไม่ต้องเขียนลวกๆ ได้ไหม ?

จริงๆแล้ว เราไม่จำเป็นต้องเขียน แบบลวกๆทุกครั้งนะครับ ซึ่งถ้าเราเขียนโค้ดดี ทำงานได้ถูกต้องอยู่แล้ว ก็ไม่จำเป็นต้อง refactor

แต่อย่างไรก็ตาม อย่างที่ได้บอกว่า ในบางครั้ง มันจำเป็นที่จะต้องเขียน “ลวกๆ” หรือมีแค่โครงสร้าง หลวมๆ เพื่อให้ unit test ทำงานได้ก่อน มันจึงจำเป็นต้อง refactor

ฟังดูแล้วอาจจะยังไม่เห็นภาพ แต่ไม่เป็นไร ในบทนี้ผมแค่เกริ่นนำไปก่อน ไว้วันหลัง เราจะเริ่มทดลองเขียน TDD กัน จะได้มองภาพออกว่า มันทำงานได้ยังไง ทำได้จริงๆเหรอที่เขียน unit test ก่อนเขียนโปรแกรม

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

คือจริงๆที่บอกว่าไม่รู้ก็เพราะว่า ยังไม่ได้เอา TDD ไปใช้กับโปรเจคจริงๆจังๆ .. แต่ที่บอกได้แน่ๆคือ หลังจากที่เริ่มเขียน TDD ผมเสียเวลาไปกับการ debug โปรแกรมน้อยลงนะ และโดยส่วนตัวผมคิดว่าเวลาส่วนมากของโปรแกรมเมอร์ เสียไปกับการ debug ไม่ใช่การเขียนเขียนโค้ดนะ .. ดังนั้น สิ่งที่จะได้จาการเขียน TDD ก็คือโปรแกรม มีคุณภาพมากขึ้น และเราก็เสียเวลาในการ debug น้อยลงด้วยจริงไหม ?

ผมก็หวังว่า TDD มันจะเป็นอย่างนั้น .. แต่อีกไม่นานหรอกครับ เชื่อว่า ผมจะตอบทุกๆคนได้แน่นอว่า มันเจ๋งอย่างที่ว่าจริงๆ หรือเปล่า เพราะผมก็เพิ่งจะหัดเขียน TDD แบบจริงจัง