-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
80db6a7
commit 88c2882
Showing
2 changed files
with
93 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# Code Refactoring | ||
ทุกคนพยายามเขียนโค้ดที่ดี และไม่มีโปรแกรมเมอร์คนไหนที่ตั้งใจเขียนโค้ดที่ไม่ดีซึ่งส่งผลเสียต่อโปรเจกต์โดยไม่จำเป็น แต่บางครั้งเราก็เพิ่มโค้ดที่ไม่ดีเข้าระบบทั้งโดยตั้งใจและไม่ตั้งใจ | ||
|
||
คำถาม: เมื่อไหร่เราจะพูดได้ว่าระบบของเราจำเป็นต้องได้รับการ Refactor? | ||
คำตอบ: เมื่อมี Technical Debt ในระบบมากเกินไป | ||
|
||
#### Technical Debt คืออะไร? | ||
Technical Debt เปรียบเหมือนการกู้เงินจากธนาคารที่ทำให้คุณสามารถซื้อของได้เร็วขึ้น **แต่** คุณต้องจ่ายดอกเบี้ยทีหลัง | ||
|
||
การเขียนโค้ดก็เช่นเดียวกัน คุณสามารถเร่งพัฒนาระบบได้โดยการข้าม Best Practices บางอย่างไปก่อน การทำแบบนั้นทำให้คุณส่งงานได้เร็วขึ้น แต่โค้ดที่ไม่ทำตาม Best Practices ย่อมมี "ดอกเบี้ย" ที่ต้องจ่าย | ||
โดย "ดอกเบี้ย" ในที่นี้คือทรัพยากรที่ต้องใช้เพิ่มขึ้นในการทำงานหรือจัดการกับโค้ดที่ไม่เป็นไปตาม Best Practices เหล่านั้น | ||
คุณจะเพิ่มฟีเจอร์ใหม่ แก้ไขปัญหา หรือดูแลรักษาระบบได้ช้าลงเรื่อยๆ | ||
ผลกระทบทางธุรกิจก็อาจเกิดขึ้น เช่น ความพอใจของลูกค้าลดลง | ||
สุดท้ายคุณจะไม่สามารถทนกับการจ่าย "ดอกเบี้ย" ที่สูงขนาดนั้นได้ และต้องยอม "จ่ายหนี้" ด้วยการเขียนระบบใหม่ทั้งหมดหรือทำการ Refactor ครั้งใหญ่ | ||
|
||
#### สาเหตุของ Technical Debt | ||
Technical Debt เกิดได้จากหลายสาเหตุ เช่น | ||
+ Business Pressure: เมื่อมีเวลาจำกัด คุณอาจเลือกใช้ solution ที่ทำได้เร็วแต่ไม่เป็นไปตาม best practices | ||
+ Lack of understanding of technical debt consequences: ความไม่เข้าใจผลกระทบของ technical debt ทำให้ไม่เห็นความสำคัญที่จะจัดสรรเวลาให้ทีมจัดการ tech debt อย่างเหมาะสม | ||
+ Failing to combat component coherence: โครงสร้างโค้ดที่เชื่อมโยงกันอย่างแน่นแฟ้นทำให้การเปลี่ยนแปลงในส่วนหนึ่งของโปรเจกต์อาจส่งผลกระทบต่อส่วนอื่นๆ จึงมีการหลีกเลี่ยงที่จะแตะโค้ดส่วนนั้นไปโดยปริยาย | ||
+ Lack of tests: หากไม่มีการทดสอบรองรับ การเปลี่ยนแปลงเล็กๆ ก็อาจทำให้เกิดบั๊กใหญ่ในระบบได้ คนเลยหลีกเลี่ยงที่จะแตะโค้ดที่ขาด tests | ||
+ Lack of documentation: การขาดเอกสารอธิบาย logic ทำให้การปรับปรุงระบบหรือการนำคนใหม่เข้าทีมยากขึ้น และอาจทำให้การพัฒนาชะงักหากบุคลากรสำคัญออกจากโปรเจกต์ | ||
+ Lack of interaction between team members: การสื่อสารไม่ดีในทีมทำให้คนในทีมมีข้อมูลที่ไม่ตรงกัน | ||
+ Long-term simultaneous development in several branches: ทำให้สะสม technical debt และเพิ่มมากขึ้นเมื่อทำการรวมโค้ด | ||
+ Delayed refactoring: ยิ่งเลื่อนการ Refactor ออกไป โค้ดยิ่งล้าสมัยและแก้ไขยากขึ้นเรื่อยๆ | ||
+ Incompetence: นักพัฒนาอาจไม่รู้วิธีหรือไม่เชี่ยวชาญในการเขียนโค้ดที่มีคุณภาพ | ||
|
||
## วิธีการทำ Code Refactoring | ||
หลักการทำ Refactoring ควรทำเป็นการเปลี่ยนแปลงเล็กๆ เรื่อยๆ ซึ่งแต่ละครั้งทำให้โค้ดดีขึ้นเล็กน้อยแต่ยังคงทำงานได้ตามปกติ | ||
|
||
โดยขั้นตอนการทำ code refactoring มีดังนี้ | ||
|
||
### 1. ตรวจหา Code Smells | ||
มี code smells หลายแบบที่สามารถพบได้บ่อยๆเช่น | ||
|
||
**1.1 Bloaters:** โค้ด เมธอด หรือคลาสที่ใหญ่จนเกินไป จนจัดการได้ยาก | ||
+ Long Method: เมธอดที่มีโค้ดมากเกินไป โดยปกติเมธอดที่ยาวเกินกว่า **10** บรรทัดควรถูกตั้งคำถามแล้วว่าควรถูกแยกออกหรือไม่ | ||
+ Large Class: คลาสที่มีฟิลด์หรือเมธอดมากเกินไป | ||
+ Primitive Obsession: การใช้ฟิลด์ primitive แทนการสร้างคลาสที่เหมาะสม | ||
+ Long Parameter List: เมธอดที่มีพารามิเตอร์มากกว่า **3-4** ตัว | ||
+ Data Clumps: กลุ่มของตัวแปรที่ใช้ร่วมกันในหลายส่วนของโค้ดควรถูกแยกออกมาเป็นคลาส | ||
|
||
**1.2 Object-Orientation Abusers:** การใช้ OOP ไม่ถูกต้อง | ||
+ Alternative Classes with Different Interfaces: คลาสสองคลาสที่ทำหน้าที่เหมือนกันแต่ใช้ interface ที่ต่างกัน | ||
+ Refused Bequest: Subclass ใช้แค่บางส่วนของเมธอดหรือฟิลด์ที่สืบทอดมาจากคลาสหลัก | ||
+ Switch Statements: มีการใช้ switch statement หรือ if statements ที่ซับซ้อนเกินไป | ||
+ Temporary Field: ฟิลด์ชั่วคราวที่ใช้งานเฉพาะในบางสถานการณ์ และไม่มีประโยชน์ในสถานการณ์อื่นๆ | ||
|
||
**1.3 Change Preventers:** โค้ดที่ทำให้คุณเมื่อคุณต้องไปแก้ไขในหลายๆ ส่วนพร้อมกันเมื่อต้องทำการเปลี่ยนแปลงจุดเดียว | ||
+ Divergent Change: ต้องเปลี่ยนแปลงหลายๆ เมธอดที่ไม่เกี่ยวข้องกันเมื่อทำการเปลี่ยนแปลงคลาส | ||
+ Shotgun Surgery: ต้องทำการเปลี่ยนแปลงเล็กๆ ในหลายๆ คลาสพร้อมกัน | ||
+ Parallel Inheritance Hierarchies: การสร้าง subclass ใหม่จะต้องสร้าง subclass อื่นๆ เพิ่มด้วย | ||
|
||
**1.4 Dispensable:** สิ่งที่ไม่จำเป็นและควรถูกกำจัดออกไปเพื่อทำให้โค้ดสะอาดขึ้น | ||
+ Comments: เมธอดที่เต็มไปด้วยคอมเมนต์ ถ้าเขียนโค้ดให้ชัดเจนเพียงพอ คอมเมนต์ก็ไม่จำเป็น | ||
+ Duplicate Code: โค้ดที่เหมือนกันหรือคล้ายกันในหลายส่วน | ||
+ Lazy Class: คลาสที่มีขนาดเล็กมากหรือไม่มีประโยชน์ | ||
+ Dead Code: โค้ดที่ไม่ถูกใช้งาน | ||
+ Speculative Generality: คลาส เมธอด ฟิลด์ หรือพารามิเตอร์ที่ไม่ได้ถูกใช้งาน | ||
|
||
**1.5 Couplers:** การเชื่อมโยงระหว่างคลาสมากเกินไป | ||
+ Feature Envy: เมธอดที่เข้าถึงข้อมูลจากคลาสอื่นมากกว่าข้อมูลของตัวเอง | ||
+ Inappropriate Intimacy: คลาสหนึ่งที่ใช้ฟิลด์ภายในหรือเมธอดของอีกคลาส | ||
+ Message Chains: การเรียกเมธอดต่อเนื่องกันหลายขั้นตอน เช่น $a->b()->c()->d() | ||
+ Middleman: คลาสที่ทำหน้าที่เพียงแค่ส่งต่อการทำงานไปยังคลาสอื่น | ||
|
||
**1.6 Other Smells:** | ||
+ Incomplete Library Class: ไลบรารีที่ไม่สามารถตอบสนองความต้องการได้ | ||
|
||
### 2. ทำการ Refactor โดยใช้ Refactoring Techniques | ||
การ Refactor สามารถทำได้หลายวิธี โดยมี 6 ประเภทหลัก ได้แก่: | ||
+ การจัดการเมธอด | ||
+ การย้ายฟีเจอร์ระหว่างคลาส | ||
+ การจัดการข้อมูล | ||
+ การทำให้เงื่อนไขง่ายขึ้น | ||
+ การทำให้การเรียกเมธอดง่ายขึ้น | ||
+ การจัดการ generalization | ||
|
||
สามารถดูเทคนิคและตัวอย่างได้ใน [Refactoring Cheatsheet](https://rachanee.medium.com/code-refactoring-c268b7665262) | ||
คุณ[เปิ้ล](https://medium.com/@rachanee)ผู้เขียนได้รวบรวมทั้งหมด **66** เทคนิคในการ refactor code ออกมาเป็น cheatsheet ไว้ด้านล่างสุดของบทความ คุณสามารถนำไปใช้ได้เลย | ||
|
||
|
||
## Reference | ||
+ [Refactoring Guru](https://refactoring.guru/refactoring) | ||
|
||
|