Friday, October 2, 2015

Recap สรุปจาก Practical unit testing (GDC 2014)

ครับ จาก Anti-pattern ทั้ง 4 ตัวที่เขียนไป บล็อกนี้เราจะมาทบทวนดูกันอีกทีว่าการเขียน Unit test ที่ดีควรปฏิบัติ

Respect unit test source code as much as production source code

ก็คือให้เคารพโค้ดใน  unit test เช่นเดียวกันกับโค้ดใน production นะครับ

และอย่าลืมยึดหลัก Good unit test นั่นคือ Readable, Maintainable และ Trustworthy


Write once, read many
พึงระลึกไว้อยู่เสมอว่าโค้ดมันถูกอ่านมากกว่าเขียน


Only one explicit assumption.
 หรือให้มี assertion แค่อันเดียวหรือเป้าหมายเดียวครับ

Minimize implicit assumptions
พยายามลด Implicit assumptions หรือ integration test ใน unit test ลงให้เหลือน้อยที่สุด


หมดแล้วจ้า ยังไงลองเข้าไปดูวีดีโออีกทีนะครับ มีหลายอย่างที่ผมไม่ได้หยิบมาเขียน อาจจะได้อะไรเพิ่มเติมครับ
นอกจากนี้ในส่วนของ description ใน youtube ยังมี link ไปยังหนังสือต่างๆที่แนะนำให้อ่านกันด้วยนะครับ เกี่ยวกับการเขียน test มีประโยชน์มากๆ



สวัสดีครับ

สรุปจาก Practical unit testing (GDC 2014): Wide anti-pattern

มาถึง anti-pattern สุดท้ายกันแล้วครับก็คือ Wide anti-pattern

ก็คือเมื่อเวลาที่เราไปแก้ไขโค้ดแก้บั๊กสักตัวนึงแล้วลองรัน Unit test ดูแล้วก็พบว่า Error บานอีกเช่นเคย

ที่นี้มาดูโค้ดกันหน่อย ดูดีจะเห็นว่า test นี้กำลังทดสองโมดูลที่เชื่อ DraftBehavior แต่ Assertion ดันไปอยู่ที่คลาส BehaviorSystem ซึ่งตัวคลาส BehaviorSystem นั้นก็มี  unit test ของมันอยู่แล้ว ดังนั้นการที่เรามาเรียกใช้คลาสอื่นๆใน unit test นั้นจะถือว่าเป็น implicit assumption ก็คือ ใน test นี้ เราไม่ได้ทดสอบแค่คลาส DraftBehavior เท่านั้น แต่ BehaviorSystem นั้นถูกทดสอบไปด้วย
ดังนั้น test นี้จึงไม่ใช้ Unit test อีกต่อไปละครับ ต้องเรียกว่า Integration test แทน

ซึ่งเราอาจจะสรุปได้ว่า
"Test ที่มี Implicit assumptions มากกว่า 1 อัน ไม่นับว่าเป็น Unit test"


ไม่ได้บอกว่า Integration test ไม่ดีนะครับ แต่ต้องทำให้ถูกที่ ถูกทาง ถูกจังหวะของมัน ไม่อย่างนั้นมันก็จะมาขวางทางเราแบบนี้แหละครับ ซึ่งเกี่ยวกับ Integration test นั้น เดี่ยวจะมาเล่าอีกทีครับ

มาดูกันต่อว่าจะแก้ปัญหานี้อย่างไรดี

ตอนที่เรื่มเขียน test นั้น มันอาจจะมี logic บางอย่างที่ในคลาส BehaviorSystem ซึ่งต้องทำการ setup ให้ถูกต้องเสียก่อนถึงจะให้ผลลัพท์ที่ถูกต้องได้

รู้สึกเหมือนกำลัง implement logic นี้สองที่เลยนะครับ ทั้งในโค้ดจริง ทั้ง test เลย

ทางแก้ที่แนะนำก้คือให้หาสิ่งที่เป็น "รอยต่อ" ระหว่างสองคลาสนี้ แล้วนำเทคนิค Test double และ Inversion of control มาใช้ครับ ในตัวอย่างนี้ก็คือ จริงๆแล้ว DraftBehavior.updateImpl() นั้น ต้องการ Heatmap จาก BehaviorSystem


พอเจอจุดที่เป็นรอยต่อแล้วเราก็ทำการสร้าง MockHeatmap ขึ้นมาครับ กำหนดให้มันเหมือนกับตัวที่คลาส BehaviorSystem จะส่งให้เวลาเรียก DraftBehavior.updatImpl()

ที่นี้ ก็ไม่จำเป็นต้องมีการเรียกใช้ BehaviorSystem ใน unit test ของ DraftBehavior แล้วครับ

สำหรับวิธีการในการหารอยต่อ สำหรับมือใหม่อาจจะหายากสักหน่อย แนะนำให้ลองอ่านหนังสือ Working effectively with legacy code ดูครับ

สรุปอีกที่ Wide anti-pattern ก็คือการที่ unit test มันมีการไปเรียกคนอื่นที่ไม่ใช่สิ่งที่เราสนใจใน unit test อันนี้ ซึ่งทำให้เราตกอยู่ในความเสี่ยง มีโอกาสสูงมากที่เราแก้บั๊กหรือเพิ่มฟีเจอร์ใหม่ๆเข้าไปแล้วจำทำให้ unit test ของเราพังครับ

เดี๋ยวบล็อกหน้ามา Recap ทั้งหมดกันอีกทีนะครับ



Wednesday, September 30, 2015

สรุปจาก Practical unit testing(GDC 2014): DEEP anti-pattern

สวัสดีครับ บล็อกนี้เรามาต่อกันที่ anti-pattern ตัวที่ 3 ก็คือ DEEP anti-pattern

ปัญหาคือเวลามี test ที่ไม่ผ่านแล้ว ดูที่ result แล้วมันดูไม่ออกว่ามันพังอะไร

ส่วนใหญ่ที่มีปัญหานี้เกิดจากการที่ test นั้นมันมี  assertion หลายๆอัน ซึ่งละเมิดหลักการเขียน unit test ที่ควรจะมี explicit assertion เพียงอันเดียว


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

ทางแก้ก็คือให้แยะ test case ออกมาให้ชัดเจนไปเลยครับ


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

Tuesday, September 29, 2015

สรุปจาก Practical unit testing(GDC 2014): WET anti-pattern

ต่อจากบล็อกที่แล้วนะครับ มาดู anti pattern ลำดับต่อมากัน

WET anti-pattern

มันคืออะไร ลองไปค้นในกู้กิ้ลดูก็เจอ wikipedia อันนี้ครับ


ก็ประมาณว่า WET เนี่ยมันจะย่อมาจาก Write Everything Twice หรือ We Enjoy Typing ก็ได้
แปลลวกๆก็คือ การที่เราชอบพิมอะไรเยอะๆ หลายๆครั้งนั่นเอง (ก็อปวางก็เข้าข่ายนะครับ อิอิ)

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


สาเหตุก็มากจากเจ้า WET นี่เองครับ ลองดูจากตัวอย่างที่เค้ายกมา จะเห็นว่า ใน test มันมีอะไรซ้ำๆกันเยอะเลย

ก็คือใน test  ของเราไม่ได้ยึดหลัก DRY(Don’t Repeat Yourself) เลยนะ!


ดังนั้นจึงควรแก้ไขโดยการ extract  มันออกมาเป็น helper function ซะ


ตรง Assertion ก็เช่นกันควรทำให้มันสื่อสารให้ชัดเจนว่าเราต้องการทดสอบอะไร เพื่อให้ test ของเรามันแก้ไขดูแลรักษาได้ง่าย แนะนำให้สร้าง Custom assert ขึ้นมาเลยครับ


แต่จุดที่ควรจะปล่อยเอาไว้คือ ในส่วนที่เป็น Act ต้องคงไว้ เพราะมันคือสาระสำคัญของ test ของเราครับ



สรุปอีกที่ WET anti-pattern  ก็คือการที่เราปล่อยให้มีโค้ดที่ซ้ำๆกันในเทส แล้วละเลยไม่ได้จัดการอะไรกับโค้ดซ้ำๆเหล่านั้นเลย ซึ่งเราอาจจะทำได้อย่างดีในโค้ดหลัก แต่ไม่ได้ทำในส่วนของ test นำมาซึ่งปัญหาในการแก้ไขในระยะยาว ดังนั้น ถ้าจะเขียน unit test แล้ว ก็ต้องดูแลมันไปพร้อมๆกันทั้งหมดนะครับ ไม่งั้นมันจะกลับมาหลอกหลอนคุณแน่นอน

บล็อกหน้ามาต่อกันที่ DEEP anti pattern ครับ 

สรุปจาก Pratical unit testing(GDC 2014): Opaque anti-pattern.

สวัสดีครับ พอดีเปิดไปเจอวีดีโอน่าสนใจเข้าอันนึงเกี่ยวแนวทางการเขียน unit test จากงาน Game dev conference เมื่อปี 2014 เลยเอามาสรุปเก็บไว้ครับ


ในวีดีโอนั้นจะพูดถึง Anti pattern ในการเขียน unit test 4 แบบด้วยกัน วันนี้เราจะมาเริ่มที่แบบแรกกันก่อน

Opaque anti-pattern

ลองไปเปิดดิกดู Opaque นั้นก็แปลว่า ทึบ, อับแสง, ไม่โปร่งใส่ แล้วมันเกี่ยวอะไรกับการเขียนเทส ลองมาดูกัน

1.Hard to see HOW.

คือโค้ดที่ดูยากว่ามันทำงานอย่างไร มันทำให้ยากต่อการทำความเข้าใจ ดูแลยาก แก้ไขยาก

2.Magic literals

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



3.Informative consistent test name.

ก็คือชื่อ test ที่ไม่ได้สื่อว่า test นั้นจะทดสอบอะไร คาดหวังอะไร ซึ่งในวีดีโอนั้นได้แนะนำรูปแบบการตั้งชื่อ test ตามรูป

4.Arrange-Act-Assert.

test ที่ไม่ได้แบ่งให้เห็นชัดเจนระหว่างสามขั้นตอนนี้ ดังนั้นก็ควรจะแบ่งให้ชัดเจนนะครับ

จบแล้วครับ เดี๋ยวมาต่อตอนหน้า กับ WET anti pattern 



ลองกดดูวีดีโอด้วยนะครับ

Tuesday, May 26, 2015

Estimation จุดเริ่มต้นเส้นทาง Agile ของผม

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

นั่นคือเรื่อง Estimation หรือแปลเป็นไทยก็คือการ ประเมิน

ผมมีปัญหากับการประเมินมากๆ รู้สึกแย่สุดๆเวลาที่ต้องประเมินงานสักงานหนึ่ง ต้อบมาตอบคำถามว่า งานนี้ต้องใช้เวลาเท่าไหร่ หรือ บั๊กนี้ต้องใช้เวลาเท่าไหร่ในการแก้ WTF! ผมจะไปตอบได้ยังไง

มีผู้ใหญ่ท่านหนึ่งบอกผมว่าให้ทำบ่อยๆ เดี๋ยวจะประเมินแม่นขึ้นเรื่อยๆเอง

แต่ผมว่า งานแต่ละงาน มันมีรายละเอียดไม่เหมือนกันนะ ผมนึกไม่ออกเลยว่าเราจะประเมินแบบนี้แม่นขึ้นได้ยังไง

เพราะฉะนั้น สิ่งที่ทำได้ก็มีเพียงการเดาเท่านั้นแหละครับ ก็เลือกตัวเลขขึ้นมาสักตัวแล้วก็ลงเวลาไป

ทีนี้ก็จะมีคำถามต่อมาอีกว่า เฮ้ยตัวเลขนี้มาได้ยังไง เยอะไปมั้ย ฯลฯ ต้องมานั่งต่อรองกันอีก เป็นเรื่องที่ผมเหนื่อยหน่ายมาก

ผมจึงเริ่มออกตามหาว่าโลกภายนอกเขาทำกันยังไงนะ หลักการที่ถูกต้องมันคืออะไร ก็เลยได้เจอคลิปวีดีโอในเว็บ Youtube เข้าอันหนึ่ง (ผมหาเท่าไหร่ก็หาไม่เจอ เนื่องจากมันนานมากๆแล้ว เลยไม่สามารถหามาแปะตรงนี้ได้ ขอโทษด้วยครับ -/\-) เป็นการแนะนำ Session ของงานสัมมนางานไหนสักงานหนึ่งนี่แหละ เมื่อประมาณปี 2011-2012
ในคลิปนั้นเป็นลุงหัวเกรียนๆคนหนึ่งออกมาขายของ แกเล่าให้ฟังว่า เวลาเราประเมินว่างานงานหนึ่งมันใหญ่ขนาดไหนนี่เราทำยังไง เราก็กะๆเอาใช้มั้ยครับ แต่เราไม่มีทางรู้ได้หรอกว่ามันใหญ่หรือเล็กจริงๆ

ลองเอาขวดน้ำขวดหนึ่งมาวาง แล้วลองกะดูสิว่าขวดนี้มันใหญ่หรือเล็ก ทำไม่ได้ใช้มั้ยล่ะ

ทีนี้ มันจะดีกว่ามั้ยถ้าเรามีขวดน้ำที่ใหญ่กว่ามาวางคู่กันให้เทียบได้ง่ายๆ อันนี้เป็นการประเมินแบบ Relative เป็นเทคนิคการEstimateอันหนึ่งที่ใช้ใน Agile ครับ

ผมนี่อึ้งไปเลยครับ โคตรจะ make sense มันมีวิธีแบบนี้ในโลกด้วยเหรอวะเนี่ย

หลังจากดูจบ ผมก็ไม่รอช้ารีบหาข้อมูลทันทีว่าตาลุงหัวเกรียนนี่คือใครกัน แล้วก็ได้เข้าร่วมชั้นเรียน Spartan ได้รู้จักกับเหล่าเกรียนส์ SPRINT3R และนั่นก็คือจุดเริ่มต้นเส้นทาง Agile  ของผมครับ

ป.ล.ผมยังตามหาวีดีโอนี้อยู่นะ ใครเจอรบกวนแจ้งเบาะแสด้วย -/\-

Sunday, May 17, 2015

อย่าเพิ่งรีบเก็บโต๊ะตอนกำลังกิน

สวัสดีครับ วันนี้มาฟังพี่ปุ๋ย เจ้าของ somkiat.cc แบ่งปันเรื่องการเขียนบล็อก

มีสิ่งที่ดีเก็บกลับมาใช้ได้หลายอย่าง แต่ที่อยากนำมาแบ่งปันในบทความนี้คือเรื่องวิธีการเขียน

พี่ปุ๋ยแนะนำว่า เขียนให้เสร็จไปก่อนแล้วค่อยกลับมาดูเพื่อแก้ไขมันทีหลัง

สาเหตุสำคัญเลยที่เวลาเรากำลังพยายามเขียนบล็อกแล้วล้มเหลวคือ "เขียนไปแล้วแก้ไป"

พิมพ์ไปสองสามตัว แล้วก็ย้อนกลับมาดู เอ๊ะ มันดูดีมั้ยนะ แก้ตรงนี้หน่อยดีกว่า ประโยคนี้จะโดนคนด่ามั้ย เฮ้ยอันนี้พิมพ์ผิด อ้าวอ่านไม่รู้เรื่อง ฯลฯ  ส่วนใหญ่แล้วจะกลัวไปเองด้วยนะ แล้วก็พิมพ์ๆแก้ๆมันอยู่อย่างนั้น ถ้าโชคดีก็เข็นจนเสร็จได้

แต่ส่วนใหญ่แล้ว ผมจะเลิกเขียน แล้วก็ปล่อยให้มันอยู่สถานะ draft ไปทั้งอย่างนั้น

แน่นอนว่าไอ้ draft พวกเนี้ย เราไม่เคยเอามาเขียนต่อจนมันเสร็จเลย!

ขโมยรูปมาจาก facebook ของพี่ปุ๋ย https://www.facebook.com/photo.php?fbid=10153321436038588&set=a.424501298587.197700.590338587&type=1&permPage=1


เรื่อง draft นี่พี่ปุ๋ยแกแนะนำให้ลบทิ้งไปให้หมดครับ เพราะถ้าคุณทิ้งไว้นาน ก็คงลืมไปหมดแล้วล่ะ ว่าจะเขียนต่อยังไง

ที่ไอ้คำแนะนำที่ว่าให้เขียนๆไปก่อนเนี่ย ก็มีอยู่ใน Online course ของ Coursera เหมือนกันครับ ในชั้่นเรียน Learning how to learn ซึ่งก็มีนักเขียนมือโปรมาแชร์เกี่ยวกับวีธีการเขียนหนังสือเหมือนกัน คำแนะนำก็ประมาณนี้เลย คือ

"Don't clean table while you are dining."

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

คำแนะนำนี้สามารถนำไปปรับใช้กับการเขียนโค้ดได้เหมือนกันนะครับ

ขอยกขั้นตอนของ TDD มาแปะ มีอยู่ว่า


  • Make it work.
  • Make it right.
  • Make it fast.


การเขียนให้เสร็จไปก่อนค่อยกลับมาแก้เนี่ย ก็คือ Make it work หรือสรุปอีกทีก็คือการทีเราเลือกแก้ทีละปัญหานั่นเองครับ

ตรงนี้มีคำอธิบายเพิ่ม +Chokchai Phatharamalai เคยเล่าให้ฟัง ก็คือตอนที่เราเขียนกับตอนที่เราแก้เนี่ย มันใช้สมองคนละซีกกันครับ ตอนเขียนทีแรก เราใช้สมองด้านเหตุผล แต่ตอนที่แก้ไขหรือตกแต่ง ใส่รูป ฯลฯ เราใช้ด้านอารมณ์ ซึ่งตรงนี้สมองของเราจะมีจังหวะของมันครับ เรื่องพวกนี้มีอยู๋ในชั้นเรียน Learning how to learn เช่นกัน

ผมว่าแนวคิดนี้นำไปปรับใช้ได้กับหลายๆอย่างเลยนะครับไม่ใช่แค่การเขียน ลองดูครับผม