From 88c288256f51d411ceb3d58d21a18826bcee9ba8 Mon Sep 17 00:00:00 2001 From: Rachanee Saengkrajai Date: Wed, 16 Oct 2024 12:32:21 +0700 Subject: [PATCH] Add code refactoring article --- .vitepress/config.mts | 8 +- paths/practices/coding/code-refactoring.md | 86 ++++++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 paths/practices/coding/code-refactoring.md diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 4c5eceb..603962d 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -477,6 +477,12 @@ function sidebarPractices(): DefaultTheme.SidebarItem[] { base: "/paths/practices/design/", items: [{ text: "Design Patterns", link: "design-patterns" }], }, + { + text: "Coding Practices", + collapsed: true, + base: "/paths/practices/coding/", + items: [{ text: "Code Refactoring", link: "code-refactoring" }], + }, ], }, ]; @@ -907,4 +913,4 @@ function sidebarWordPress(): DefaultTheme.SidebarItem[] { ], }, ]; -} +} \ No newline at end of file diff --git a/paths/practices/coding/code-refactoring.md b/paths/practices/coding/code-refactoring.md new file mode 100644 index 0000000..5b07873 --- /dev/null +++ b/paths/practices/coding/code-refactoring.md @@ -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) + +