Refactoring

posted on 30 Jul 2008 16:56 by wonam in softdev

เท่าที่ผมอ่านมา กิจกรรมอย่างหนึ่งซึ่งสำคัญมากสำหรับนักพัฒนาแนวปราดเปรียว (พริ้ว) ก็คือการ refactor

การ refactor คืออะไร?

ถ้าจะถือนิยามตาม Martin Fowler (คนเขียนหนังสือชื่อ Refactoring ในหนังสือ classic เล่มดังกล่าว Fowler ได้รวบรวมวิธีการ refactor เอาไว้) การ refactor ก็คือ

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

ยกตัวอย่างของการ refactor ที่ง่ายที่สุดและเห็นภาพที่สุดก็คือการเปลี่ยนชื่อตัวแปรหรือเปลี่ยนชื่อเมท็อด นอกจากนี้ยังมีเช่น การแยกเมท็อด (Extract Method)  เป็นต้น  (สำหรับรายการของเทคนิคการ refactor ลองดูได้จากเว็บ refactoring และในบทความในวิกิพีเดียมีกล่าวถึงเทคนิคการ refactor ไว้บ้างเช่นกัน)

ภาษาและเครื่องมือในการ refactor

ในทุก ๆ การสนทนา (และโต้เถียง) เกี่ยวกับภาษาเชิงสถิตย์ (เช่น Java) กับภาษาเชิงพลวัติ (เช่น Ruby, Python) หัวข้อหนึ่งที่วิ่งเข้ามาคือประเด็นที่ว่าการ refactor สำคัญมาก และจะทำได้สะดวกถ้ามีเครื่องมือ ดังนั้นผู้โต้แย้งฝ่ายภาษาเชิงสถิตย์จึงสรุปว่า ภาษาเชิงสถิตย์ที่ (ในขณะนี้) มีเครื่องมือในการ refactor ที่ดีกว่า ย่อมทำให้ประสิทธิภาพในการพัฒนาดีกว่าภาษาเชิงพลวัติ ที่ตอนแรกแม้จะพัฒนาได้รวดเร็ว แต่เนื่องจากทำ refactor ไม่ค่อยได้ ทำให้ประสิทธิภาพตกลง

แล้วเครื่องมือในการทำ refactor ช่วยอะไรได้บ้าง?  ปกติผมใช้ emacs แล้วก็ไม่เคยลองหาว่ามันมีเครื่องมืออะไรหรือเปล่า เท่าที่ผ่าน ๆ มาก็ refactor ด้วยมือมั่ว ๆ เอา

เมื่อพักก่อนผมเองเพิ่งใช้ Eclipse อย่างผิวเผิน เท่าที่เห็นก็มีการเปลี่ยนชื่อเมท็อด การเปลี่ยนชื่อตัวแปร (ลอง search ดู --เอกสารอาจเก่าไปหน่อย-- เห็นมีการจับตัวแปร local ไปเป็น instance variable อะไรพวกนี้ด้วย)   ที่เห็นใน Visual Studio มีการสลับตำแหน่งของ argument และการ extract method   ใน NetBeans ก็มีโมดูลสำหรับ refactor ที่ดูแล้วทำได้หลายอย่างเหมือนกัน

แม้ว่าเครื่องมือในการทำ refactor แรก ๆ เริ่มจาก IDE ของ Smalltalk ซึ่งเป็นภาษาเชิงพลวัติ แต่พัฒนาการของเครื่องมือหรือความสามารถของเครื่องมือบนภาษาเหล่านี้ (เท่าที่ผมอ่าน ๆ ดู) เหมือนจะสู้เครื่องมือบนภาษาเชิงสถิตย์ไม่ได้... สาเหตุที่ผมลองเดา ๆ ก็คงเพราะว่าภาษาเชิงพลวัติจึงทำ refactor ได้ยากกว่า

ทำไมล่ะ?  ลองดูตัวอย่าง (คลาสสิก) จากภาษา Ruby ในบล็อก (ของคนที่อยู่ฝั่ง static type) ที่โต้เถียงเกี่ยวกับการ refactor กับภาษา dynamic นะครับ

อย่างไรก็ตามตอนนี้มีความพยายามที่จะแปลหนังสือ refactor ของ Fowler ออกเป็นเวอร์ชัน Ruby

ที่สุดก็คือ ไม่ว่าจะค่ายใดก็ตามไม่มีใครปฏิเสธความสำคัญของการ refactor

Unit test และการ refactor

ผมคิดว่าความสำคัญของการ refactor ยิ่งทำให้การทำ unit test ไม่ว่าจะเขียนทีหลัง หรือว่าจะทำแบบ Test-driven development ยิ่งสำคัญเข้าไปใหญ่

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

Refactor กับ Plan-based development?

สิ่งที่ผมสงสัยอยู่มาก แล้วก็ยังหาคำตอบให้ตัวเองไม่ได้สักที (ลองค้น ๆ ดูในเว็บก็ยังไม่ได้อะไรเป็นชิ้นเป็นอัน) ก็คือทางนักพัฒนาแนว plan-based ที่ต้องทำ UML design อย่างละเอียดก่อน code จะใช้การ refactor มาก-น้อยแค่ไหน  และความสำคัญของเครื่องมือหรือเทคนิคการ refactor ต่อนักพัฒนาที่ยึดแนวทางนี้เป็นอย่างไร  ผมลองค้น ๆ ดูในหนังสือของ Booch มีกล่าวถึงการ refactor ไว้บ้างว่าเป็นแนวปฏิบัติของพวกใช้กระบวนการแนวพริ้ว แต่ไม่ได้เน้นอะไรมาก

ผมเห็นว่ามีการทำ refactor UML model (ดูเอกสาร) นี่อาจจะเป็นการทำ refactor หลัก ๆ ของฝั่ง plan-based หรือเปล่าผมก็ไม่ค่อยแน่ใจ

แต่ทางฝั่งพริ้วมีเสนอให้ใช้ UML ในการ refactor ด้วย (ดูเอกสาร)

ทิ้งท้าย

ผมคิดว่าสิ่งที่อันตรายที่สุดของการเขียนโปรแกรมที่มีคุณภาพก็คือความคิดที่ว่า "ถ้ามันทำงานได้อยู่แล้วก็อย่าไปแตะมัน"

สำหรับคนที่ใช้เครื่องมือพวกนี้อยู่ (หรือทำมืออยู่) มีความเห็นอะไรหรืออะไรแนะนำ รบกวนด้วยนะครับ ;)

Comment

Comment:

Tweet

Joe เรื่องช่วงชีวิตของซอฟต์แวร์นี่ก็น่าสนใจ :)

#7 By wonam on 2008-08-01 23:28

"ผมคิดว่าสิ่งที่อันตรายที่สุดของการเขียนโปรแกรมที่มีคุณภาพก็คือความคิดที่ว่า ...ถ้ามันทำงานได้อยู่แล้วก็อย่าไปแตะมัน"

ผมว่าบางทีก็ต้องมองว่าโปรแกรมมันอยู่ในจุดไหนของชีวิตมันด้วยนะครับ ถ้าโปรแกรมอยู่ระหว่างการพัฒนา การปรับปรุงมันก็ต้องดู trade-off กับเรื่องเวลาเหมือนที่ คคห. 1 กับ 3 ว่าไว้

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

#6 By Joe (203.159.36.12) on 2008-08-01 20:31

ขอบคุณสำหรับทุก comment ครับ

xnanoob, plynoi: จริงครับ ขืนศิลป์ไม่ดูเวร่ำเวลาคงแย่

veer: อืม โครงของ javascript นี่ยิ่งพิศดารเข้าไปอีกนี่นา แค่ผมพยายามเข้าใจเรื่อง class/prototype มันนี่ก็แทบแย่แล้ว

deans4j: ขอบคุณสำหรับประสบการณ์ครับ หนังสือที่แนะนำมาน่าอ่านมาก (เป็น series ของ martin folwer ซะด้วย (มั้ง))

#5 By wonam on 2008-08-01 01:17

ช่วยเสริมครับ

ภาษา static ได้เปรียบภาษา dynamic เรื่อง compiler ลำพังสามารถ parse หา AST (Abstract syntax tree) ที่ทำได้ละเอียดกว่าครับ ผลพลอยเลยทำให้ IDE ฉลาดง่ายกว่า

เพราะฉะนั้นฝั่ง dynamic เลยต้องไปพึ่งการเขียน test case ที่แน่นหนากว่าแทนเพื่อที่จะ refactoring ด้วยมือแล้วไม่กลัวของเก่ามันพัง

ถ้าสนใจ refactoring + design pattern ผมขอแนะนำหนังสือเล่มนี้ครับ refactoring to pattern

http://www.industriallogic.com/xp/refactoring/

เป็นหนังสือที่สอนเรื่อง Testing, Refactoring, Design Pattern ไปในตัว ช่วยได้มากในทางปฏิบัติเลยครับ

ประสบการณ์ส่วนตัวสอนผมให้รู้ว่า Testing + refactoring เป็นของคู่กัน ทำให้เราเขียน code ได้สวยขึ้น ฉลาดขึ้น เป็นหนึ่งในกิจกรรมที่ช่วยพัฒนาทักษะการเขียนโปรแกรมให้สูงขึ้นได้อย่างมีนัยสำคัญ และที่สำคัญมันสนุกด้วย big smile

#4 By deans4j (124.120.128.24) on 2008-07-31 18:06

เคยอ่าน Refactoring สักที่
เค้าบอกว่า "ผมคิดว่าสิ่งที่อันตรายที่สุดของการเขียนโปรแกรมที่มีคุณภาพก็คือความคิดที่ว่า ...ถ้ามันทำงานได้อยู่แล้วก็อย่าไปแตะมัน" ต้องดูเวลาด้วย
ถ้าจะ deadline อยู่รอมร่ออย่า Refactoring หรือแก้ส่วนที่ทำงานได้ถูกต้องอยู่แล้ว ค่อยมาแก้เฟสถัดไปเป็นลำดับแรก

#3 By plynoi แว่วศรี on 2008-07-30 22:17

อยากได้ของ javascript อะครับ confused smile. เดี๋ยวนี้เขียนไปเขียนมามีแต่ javascript sad smile

#2 By veer on 2008-07-30 21:36

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

.. วันก่อนโน้นไปตัดผมตอนสองทุ่มกว่า คนในร้านนั่งรอคิวอยู่ 4-5 คิว สังเกตช่างตัดผมเค้ายังจะบรรจงเล็ม ตกแต่งผมของคนแรกอยู่นั้นแระ เล็มไปเล็มมา เหมือนจะไม่ได้สังเกตว่า กูรออยู่นะ คิวมันยาวนะพี่...

กลับมาคิดถึงตัวเองแล้วเศร้าเหี้ยอะครับ อ.

#1 By xnanoob on 2008-07-30 18:36