# Code Smells

เวลาที่เราทำงานกับโค้ดอยู่เคยรู้สึกแปลกๆกับโค้ดกันไหม เช่น **ทำไมต้องเขียนแบบนี้ ทำไมใช้ยากจัง มันควรเป็นแบบนี้จริงๆเหรอ** อะไรทำนองนี้ นั่นแหละคือสัญญาณแบบนึงที่บอกว่าโค้ดพวกนั้นกำลังมีปัญหา ซึ่งเขาเรียกว่า**มันกำลังส่งกลิ่นเหม็นออกมา** ดังนั้นหน้าที่ของ developer ที่ดีคือไล่ตามกลิ่นพวกนั้นไปแล้ว**จัดการอย่าให้โค้ดเน่า**ซะ ( ไม่ต้องเอาจมูกไปชิดจอแล้วไล่ดมโค้ดชาวบ้านไปทั่วนะครับ 🤣 )

{% hint style="info" %}
**Code smells**\
คือหลักการที่เอาไว้ตรวจว่า **โค้ดที่เราออกแบบไว้มันไปผิดหลักการออกแบบหรือเปล่า** ซึ่งถ้าผิดมันหมายความว่าโครงสร้างพวกนั้นจะมีปัญหาในอนาคต และมีอีกชื่อนึงคือ **Design Smells**
{% endhint %}

## ❓ โค้ดส่งกลิ่นเน่าแล้วไง ?

คุณอยากทำงานกับโปรเจคแบบนี้ไหม **แก้โค้ด 1 จุด bug ผุดกระจาย** หรือ **เพิ่ม 1 feature แต่ต้องไปแก้ 10 feature ที่ไม่เกี่ยวข้องด้วยไม่งั้นเพิ่ม feature ใหม่ไม่ได้** และอื่นๆอีกมากมาย ซึ่งถ้าไม่โรคจิตพอก็น่าจะตอบว่า "ไม่" แล้วถามต่อว่า แล้วจะมีใครอยากมาทำงานโปรเจคแบบนี้ไหม? คนที่อยู่ในโปรเจคแบบนี้เขาอยากรีบหนีไปทำโปรเจคอื่นไหม? นี่ยังไม่นับรวมเรื่อง deadline ของโปรเจคนี้ที่กำลังบีบเข้ามาด้วยนะ ... แค่นี้ก็น่าจะเห็นภาพแล้วใช่ไหมว่า โค้ดเน่ามันส่งผลเสียยังไง . . . หรือก็เป็นอยู่จนชินกันแล้ว ?  😱

## 🤢 อาการของกลิ่นเน่า

### 👃 Rigidity (ดื้อ)

คืออาการของ**โค้ดที่แก้ไขเพิ่มเติมยาก** แม้ว่าจะเป็นแค่เรื่องง่ายๆก็ตาม เช่น แก้ 1 จุด แต่มันไปกระทบกับโค้ดอื่นๆที่เกี่ยวข้องกับมัน ทำให้เราต้องไปตามแก้เพื่อให้มันทำกับแบบใหม่ได้ แย่กว่านั้นอีกแก้ A กระทบ B, แก้ B กระทบ C, แก้ C ดันย้อนมากระทบ A เป็นงูกินหาง

{% hint style="info" %}
**แก้ 1 กระทบ 10**\
เคยไหมคิดว่าจะแก้โค้ดแค่ 1-2 วันวัน แต่พอทำไปทำมาบางทีกินเวลาเป็น 1-2 อาทิตย์เลย ทำให้เราไม่สามรถประเมินว่างานจะเสร็จเมื่อไหร่ได้เลย 😧
{% endhint %}

### 👃 Fragility (เปราะบาง)

คืออาการของโค้ดที่ **แก้ 1 จุด bug ผุดเป็นดอกเห็ด** เลวร้ายกว่านั้นอีก bug ที่ผุดขึ้นมาในบางทีไม่เกี่ยวข้องกับเรื่องนั้นเลย เช่น แก้โปรแกรมลงเวลา แล้ว bug ไปเกิดตอนคำนวณเงินเดือน ยิ่งแก้ก็ยิ่งผลิด bug ออกมาไม่จบไม่สิ้น

{% hint style="info" %}
**แก้ 1 จุด bug ผุดเป็นดอกเห็ด**\
เคยไหม bug มันเยอะแก้ยังไงก็ไม่หมด จนคิดว่าเขียนส่วนนั้นใหม่ตั้งแต่ต้นอาจจะเร็วกว่า ปัญหานี้ developer ทุกคนรู้จักดี และบางครั้งรู้ด้วยว่ามันเป็นไฟล์นี้ แต่ไม่มีคนอยากไปแก้มันเพราะกลัวฟาร์มเห็ดจะผลิบาน
{% endhint %}

### 👃 Immobility (ย้ายที่ไม่ได้)

คืออาการของโค้ดที่เรารู้สึกว่ามันไม่ควรอยู่ตรงนี้นะ แต่ก็ย้ายมันออกจากตรงนี้ไม่ได้เพราะมันถูกใช้งานอยู่ และถ้าจะย้ายมันไปที่ๆของมันก็อาจจะเสียเวลามากจนไม่คุ้ม (พบเจอได้บ่อยกับพวก helper class กับ database connector หรือไม่ก็โค้ดที่คนอื่นเขียนไว้ไม่อยากไปยุ่งกับมัน)

### 👃 Viscosity (หนืด)

เคยไหมเวลาที่จะเขียนโค้ดบางที **เรารู้ว่ามันควรจะทำยังไงถึงจะถูก แต่ถ้าทำแบบนั้นมันจะเสียเวลา เราเลยทำแบบให้มันใช้งานได้ไปก่อน**&#x20;

{% hint style="info" %}
**ทำให้ใช้งานได้ไปก่อนเดี๋ยวค่อยกลับมาแก้**\
การทำแบบนั้นทำให้โค้ดที่จะตามมาในอนาคต **มีโอกาสสุ่มเสี่ยงที่จะทำให้โค้ดออกนอกลู่นอกทางจากสิ่งที่มันควรจะเป็น** แล้วเมื่อไหร่เราจะไปแก้โค้ดพวกนั้นกันนะ ? 😧
{% endhint %}

### 👃 Needless Complexity (ซับซ้อนโดยไม่จำเป็น)

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

{% hint style="info" %}
**ซับซ้อนโดยไม่จำเป็น**\
ตัวอย่างที่เจอได้ง่ายสุดๆคือ จะแสดงเลขทศนิยมสูงสุดเพียงแค่ 2 ตำแหน่ง เช่น 3.1415 จะต้องแสดงเป็น 3.14 แต่ developer ไปเขียนสูตรคำนวณเพื่อตัด string หรือไม่ก็ x 100 เข้า แล้วหาร 100 ออกบลาๆ ซึ่งทำไมไม่ใช่ **Math.Round()** แฟร๊ พูดแล้วขึ้น 😡
{% endhint %}

### 👃 Needless Repetition (ใช้โค้ดซ้ำโดยไม่จำเป็น)

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

{% hint style="info" %}
**โค้ดไร้ประโยชน์กระจายตัวไปทั่ว**\
สมมุติว่ามีการเปลี่ยนการทำงานเรื่องที่เกี่ยวกับเจ้าโค้ดไร้ประโยชน์นั้นเข้าล่ะ แน่นอนมันก็ยังไร้ประโยชน์เช่นเดิมแต่สิ่งที่เพิ่มขึ้นมาคือ ทุกจุดที่มันอยู่ bug ก็จะผุดขึ้นมาด้วย โดยที่เรื่องนั้นๆไม่เกี่ยวกับเจ้าโค้ดไร้ประโยชน์นี้เลยก็ตาม&#x20;

**ตัวอย่าง** แก้โครงสร้าง database รถยนต์ แต่เรื่องคำนวณวันหยุดพัง เรื่องตารางนัดหมายพัง เรื่องระบบประชุมพัง เพราะแต่ละจุดดันมีโค้ดไร้ประโยชน์ที่มันต้องไปดึงข้อมูลรถยนต์ซ่อนอยู่ในนั้นด้วย แล้วมันไม่ได้ถูกแก้ตามโครงสร้าง database ตัวใหม่ ก็เลยพัง **ทำให้เราเสียเวลาไปหาสาเหตุที่ไร้สาระแต่เป็นงานด่วน** 😱
{% endhint %}

### 👃 Opacity (เข้าใจยาก)

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

## 🤔 ทำไมโค้ดถึงเน่า ?

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

{% hint style="info" %}
**พูดสั้นๆ**\
กลับไปเก็บ exp มาให้เยอะๆซะ (รวมถึงผมด้วย) เพราะการเขียนซอฟต์แวร์ต้องเรียนรู้ตลอดไปไม่สามารถหยุดเรียนได้ เทคโนโลยีในตอนนี้เปลี่ยนวันต่อวันเลยทีเดียว 🤧
{% endhint %}

## 🎯 บทสรุป

โค้ดเน่าทำให้การพัฒนาซอฟต์แวร์กลายเป็นนรก เพราะ โปรเจคประเมินเวลาและค่าใช้จ่ายไม่ได้ ไม่มีคนอยากทำโปรเจคนั้น ดังนั้นจงอย่าทำให้มันเน่า

แล้วจะทำยังไงมันถึงจะไม่เน่า ? ... ออกไปเก็บประสบการณ์ซะ อ่านโค้ดจาก GitHub คนที่เก่งๆ ร่วม Contribute source code กับ GitHub ระดับโลกซักตัว เราจะได้รับคำแนะนำมาเต็มเลย และที่สำคัญที่สุดคือไปศึกษาหลักการออกแบบที่ดีมาซะ

### 👨‍🚀 **คอร์สที่จะช่วยให้โค้ดไม่เน่า**

{% content-ref url="/pages/-LmXswgLXrRV0ZatXkxU" %}
[SOLID Design Principles](/basic/solid.md)
{% endcontent-ref %}

{% content-ref url="/pages/-LmTBsJjoq1GWMJb8oCt" %}
[Test-Driven Development](/software-testing/tdd101.md)
{% endcontent-ref %}

{% content-ref url="/pages/-LmQMABDZJvFe25M6sbA" %}
[Design Patterns](/software-design/designpatterns.md)
{% endcontent-ref %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.saladpuk.com/basic/code-smells.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
