มีโอกาสได้ไปพูด และ แบ่งปันเรื่อง Transformation Priority Premise(TPP)
ในงาน #CodeMania01 ของกลุ่มสมาคมโปรแกรมเมอร์ไทย
โดยสิ่งที่พูดไปใน session นั้นอาจจะสั้นไปหน่อย
แต่สิ่งที่ต้องการ คือ ทำให้เข้าใจว่ามันมาจากไหน
ต่อจากนั้น ถ้าทุกๆ คน ตั้งคำถามกับมัน แล้วลองลงมือทำ
ก็ถือว่า ผมได้ทำสำเร็จตามเป้าแล้ว

ในการสรุปครั้งนี้ จะอธิบายลงรายละเอียดของ TPP  แต่ละขั้นตอน
โดยการเขียนนั้นจะใช้แนวคิด TDD (Test-Driven Development)

ก่อนอื่นทำความรู้จักกับ TPP หน่อย

TPP นั้นถูกสร้างขึ้นมาจากคุณ Robert C. Martin หรือ Uncle Bob
ซึ่งเขียนอธิบายรายละเอียดไว้ที่นี่ The Transformation Priority Premise 

มีใจความสำคัญดังนี้
TPP เป็นรูปแบบหนึ่งของวิธีการเขียนโปรแกรม
ซึ่งช่วยทำให้การพัฒนาตามแนวคิด TDD นั้นง่ายขึ้น และ มีประสิทธิภาพดีขึ้น
โดยคำว่า ประสิทธิภาพนั่น คือ developer สามารถทำความเข้าใจได้ง่าย
นั่นคือ ความซับซ้อนจะลดลงไป

ในการเขียนโปรแกรมนั้น จะพบว่า code จะเกิดการ transformation

หรือการเปลี่ยนรูปจากสถานะหนึ่งไปยังสถานะหนึ่งเสมอ
โดยหนึ่งรูปแบบของการ transform คือ การ Refactoring code นั่นเอง

การ Refactoring นั้นคือขั้นตอนการเปลี่ยนโครงสร้างของ code ให้ดีขึ้น
โดยไม่ทำการแก้ไขพฤติกรรมของ code

ตัวอย่างเช่น
การ refactoring code นั้นมักจะทำเมื่อ developer พบเห็นสิ่งที่เรียกว่า code smell
เช่น duplication code, ชื่อไม่สื่อ และ method ที่ยาวๆ เป็นต้น

ส่วนการ Transformation นั้นจะแตกต่างจาก Refactoring คือ
การ Transformation เป็นการเปลี่ยนแปลงพฤติกรรมภายในของ code
และขั้นตอนการ transformation มักจะเป็นขั้นตอนที่เรียบง่าย
ปัญหา คือ เรียบง่ายมันเป็นอย่างไรล่ะ ?

โดยรวมแล้ว การ Transformation จะเกิดขึ้น
เพื่อต้องการทำให้ test ที่มันแดง หรือ fail นั้น ผ่านนั่นเอง

แล้ว TPP ล่ะ ?

ในการ Transformation ที่บอกว่าต้องมีขั้นตอนที่เรียบง่ายนั้น
ทางคุณ Robert C. Martin ได้สรุปลำดับของการ Transformation ไว้ให้
ซึ่งถ้าคุณสร้าง code ตามลำดับที่สูงๆ และมีการเรียงลำดับ test ดีๆ แล้ว
จะส่งผลทำให้ code ที่คุณเขียนขึ้นมา ไม่ไปเจอทางตัน เช่น ต้องเขียนใหม่
รวมทั้ง มันจะช่วยให้คุณใช้เวลาในรอบของ TDD น้อยมากๆ

รูปแบบของการ Transformation ทำการเรียงจากสิ่งที่เรียบง่ายสุดๆ ไปยังความซับซ้อน เป็นดังนี้
Screen Shot 2557-11-01 at 7.53.16 PM

ดูแล้วน่าจะงงๆ
ผมจึงแปลงรูปนิดหน่อย พร้อมทั้งตัวอย่าง น่าจะทำให้เข้าใจง่ายขึ้น ดังรูป

Screen Shot 2557-11-01 at 7.53.59 PM

ปัญหาที่ใช้ในการพูดครั้งนี้คือ FizzBuzz

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

เริ่มง่ายๆ ด้วยการเขียน  Test ตามนี้
Screen Shot 2557-11-01 at 7.55.31 PM

เริ่มเขียน code กันดีกว่า

Test case ที่ 1  ::  1 => 1

ในการเขียน code เริ่มต้น เพื่อแก้ไขปัญหาแรก จะมีการ transformation คือ no code -> null ดังนี้

แน่นอนว่ามันไม่ผ่าน ดังนั้นเข้าสู่สถานะ RED

จากนั้นทำการแก้ไข code ให้มันผ่าน
ด้วยการ transformation คือ null -> simple constant ดังนี้

และมันผ่านด้วยสิ ถึงเราจะโกง หรือ hard code ไว้ก็ตาม

Test case ที่ 2  ::  2 => 2
ใน test case นี้จะพบว่า มีเงื่อนไขเดียวกับ test case ที่ 1
ดังนั้น สามารถเขียน test case ได้ดังนี้

ถามว่า เราต้องทำอย่างไรให้ test ผ่านล่ะ ?

รูปแบบการ transformation ที่สามารถใช้ก็คือ  constant -> variable ดังนี้

ใน test case นี้เป็นการขจัดพวก hard code ออกไปจาก code

Test case ที่ 3 ::  3 => Fizz
จะทำการสร้าง test case ขึ้นมาดังนี้

เราสามารถแก้ไข code เพื่อให้ test case นี้ผ่าน ด้วยวิธีการที่ง่ายๆ คือ

unconditional -> conditional
นั่นคือ การใช้ if นั่นเอง

จาก code นั้น มันทำให้การทดสอบผ่านจริงๆ
แต่เห็นไหมว่า developer คนนี้ทำการ hard code ไว้อีกแล้ว
ดังนั้น เราจะทำการขจัด hard code ไปได้อย่างไร ?
คำตอบคือ เพิ่ม test case ใหม่เข้าไปสิ

Test case ที่ 4 ::  6 => Fizz
จะทำการสร้าง test case ขึ้นมาดังนี้

แน่นอนว่า test case ต้องทำงานไม่ผ่าน ตามที่เราคาดหวัง

ดังนั้นทำการแก้ไข code ดังนี้

เพียงเท่านี้ก็ขจัด hard code ไปได้ล่ะ

Test case ที่ 5 ::  5 => Buzz
ต่อไปทำการเพิ่ม test case ต่อไป เกี่ยวกับ Buzz บ้างล่ะ
เพราะว่า เราน่าจะสบายใจจาก Fizz แล้วนะ

ทำการเพิ่ม test case ใหม่ดังนี้

ผมคาดหวังว่า developer ทุกๆ คนคงไม่ hard code อีกนะ
และก็เชื่อว่า สิ่งที่ใช่คือ การสร้าง if-else ขึ้นมา
นั่นคือการ transformation ในข้อ 14 คือ case ดังนี้

และผมก็เชื่อว่าใน test case ต่อๆ ไป คือ FizzBuzz
คุณก็จะใช้การ transformation แบบที่ 14 ต่อไป
ทำให้เกิด code ประมาณนี้

มาถึงตรงนี้คุณมองเห็นอะไรบ้าง
เห็นไหมว่า ปกติเรามักจะใช้งานการ transformation ที่ 14 เยอะมากๆ
ซึ่งเราก็นำไปใช้ในงานจริงๆ  และมักจะเกิดภาพประมาณนี้ขึ้นมาใน code
มันคือ ความซับซ้อนของระบบงานล้วนๆ
Screen Shot 2557-11-01 at 8.17.04 PM

ดังนั้น กลับมาคิดใหม่ด้วยแนวคิดของ TPP
มีวิธีการไหน ที่มันอยู่ลำดับสูงกว่า 14 บ้าง ที่เราสามารถนำมาใช้งานได้ ?
โดยผมจะย้ายกลับไปที่ code นี้

ให้เวลาคิด 5 นาที ………
ถ้าคิดไม่ออก ผมแนะนำดังนี้ ( มันมีวิธีการอื่นๆ อีกนะครับ )

ลองใช้การ transformation จาก constant -> variable ก่อนไหม

ต่อจากนั้นเมื่อเพิ่ม test case :: 5 => Buzz เข้ามา
เราลองใช้ transformation   variable -> array ดูสิ

ตัวอย่างผมทำให้เห็นว่า มันเกิด duplication code แล้วนะ
เราสามารถ refactoring code ด้วยการนำ loop มาใช้ได้

เมื่อเราทำการเพิ่ม test case 15 -> FizzBuzz แล้ว
จะพบว่า เพียงแค่เพิ่มค่าใน array เท่านั้น ง่ายดีไหม ?
หรือถ้าทำการเพิ่มเงื่อนไหขใหม่ๆ เข้าไปก็ทำได้ง่าย
ดังนี้

คุณคิดไหมว่า code มันจะออกมาในรูปแบบนี้ได้ ??

จากแนวทางที่ผมแนะนำนั้น นำเราไปสู่อะไรบ้าง ?

แต่ละส่วนของ code มีหน้าที่การทำงานอย่างเดียว
นั่นคือการเคารพใน SRP (Single Responsibility Principle)

และเราสามารถเพิ่มเงื่อนไขต่างๆ เข้าไป โดยไม่ต้องแก้ไข code ส่วนหลัก
นั่นคือ เราเคารพใน OCP (Open/Close Principle)

เราได้รู้ว่า ถ้าเราเรื่องวิธีการ transformation อันดับสูงๆ แล้ว

  • จะทำให้เราได้ code ที่เรียบง่าย
  • จะทำให้เราได้ code ที่สามารถดูแลรักษาได้ง่าย
  • นั่นคือได้ code ที่ดีกว่า และเป็นประโยชน์ต่อ developer มากขึ้น
  • ไม่ใช่เขียน code ให้ computer เข้าใจอย่างเดียว

Slide ของการแบ่งปันครั้งนี้อยู่ที่ 

ขอขอบคุณทางผู้จัดงานที่ให้โอกาสผมไปแบ่งปันครับ
รวมทั้งคนที่เข้ามารับฟังครับ
แล้วเจอกันในครั้งหน้าครับ