Composing Methods
จุดประสงค์
หัวข้อที่มีชื่อว่า “จุดประสงค์”กลุ่ม composing methods ว่าด้วยเรื่อง ภายใน ของ function ล้วน ๆ คือ statement ถูกจัดกลุ่ม ตั้งชื่อ และเรียงลำดับกันอย่างไร refactoring กลุ่มนี้ไม่แตะ behavior แต่เปลี่ยนว่าคนอ่านจะตามสิ่งที่ function ต้องการสื่อได้ง่ายแค่ไหน
Code Smell
หัวข้อที่มีชื่อว่า “Code Smell”function โตขึ้นตามเวลา สะสม temporary variable ไว้ตรงนี้ เงื่อนไขบรรทัดเดียวสุดฉลาดตรงนั้น แล้วก็ loop ที่แอบทำงานสามอย่างพร้อมกันเงียบ ๆ สุดท้ายก็ไม่มีใครอ่านจากบนลงล่างแล้วสรุปได้ในประโยคเดียว วิธีรักษาในโมดูลนี้จัดการปัญหานั้นตรง ๆ คือแยกชิ้นส่วนที่พันกันออกจากกัน ตั้งชื่อให้ส่วนสำคัญ แล้วปล่อยให้ code ที่เหลืออ่านได้เหมือนสรุปเจตนาสั้น ๆ
| Code Smell | อาการที่บ่งชี้ | ท่าที่แนะนำ |
|---|---|---|
| Long Method | function ยาวจนอ่านจากบนลงล่างแล้วอธิบายไม่ได้ในประโยคเดียว | Extract Function |
| Duplicated Code | logic เดิมซ้ำในหลายจุด คัดลอก-วางมาพร้อมบั๊ก | Extract Function |
| Cryptic Expression | sub-expression ที่อ่านแล้วไม่รู้ความหมาย | Extract Variable |
| Temporary Variable | temporary variable ที่คำนวณค่าซับซ้อนแล้วส่งต่อ | Replace Temp with Query |
| Divergent Change | function เดียวทำสองงานที่ต่างกัน แก้ที่หนึ่งกระทบอีกที่ | Split Phase |
flowchart TD
A["A long, tangled function"] --> B{"What is wrong?"}
B -->|"A block does one named thing"| C["Extract Function"]
B -->|"A helper adds no clarity"| D["Inline Function"]
B -->|"A sub-expression is cryptic"| E["Extract Variable"]
B -->|"A temp holds a computed value"| F["Replace Temp with Query"]
B -->|"Two unrelated jobs in one flow"| G["Split Phase"]
C --> H["Code that reads like intent"]
D --> H
E --> H
F --> H
G --> H โมดูลนี้ครอบคลุมอะไรบ้าง
หัวข้อที่มีชื่อว่า “โมดูลนี้ครอบคลุมอะไรบ้าง”refactoring เก้าแบบ แต่ละแบบเล็กและย้อนกลับได้:
- Extract Function — ยกชิ้นส่วนหนึ่งขึ้นไปเป็น function ที่มีชื่อของตัวเอง เพื่อให้จุดที่เรียกอ่านได้เหมือนรายการของเจตนา เป็นท่าพื้นฐานที่สุดของทั้งหมด
- Inline Function — ท่าตรงข้าม พอ body ของ helper ง่ายพอ ๆ กับชื่อ ก็พับกลับเข้าไป
- Extract Variable — ตั้งชื่อให้ sub-expression ที่ชวนสับสน เพื่อให้บรรทัดนั้นอธิบายตัวเองได้
- Inline Variable — ท่าตรงข้าม ลบตัวแปรที่เป็นแค่เสียงสะท้อนของ expression และไม่ได้เพิ่มความชัดเจนอะไร
- Replace Temp with Query — เปลี่ยนตัวแปร local ที่เก็บค่าคำนวณไว้ให้กลายเป็น function เพื่อให้เอาการคำนวณกลับมาใช้ซ้ำและ extract ต่อได้ง่าย
- Slide Statements — ย้าย statement ที่เกี่ยวข้องกันมาอยู่ติดกัน ชิ้นส่วนที่เข้าชุดกันจะได้พร้อมให้อ่านหรือ extract
- Split Phase — พอบล็อกเดียวทำงานสองอย่างที่ไม่เกี่ยวกัน ก็หั่นออกเป็น phase ที่เรียงลำดับ แล้วเชื่อมด้วยค่ากลางที่ชัดเจน
- Substitute Algorithm — เปลี่ยนวิธีทำที่ซับซ้อนยุ่งเหยิงเป็นวิธีที่ชัดเจนกว่าและให้ผลลัพธ์เดียวกัน
- Replace Loop with Pipeline — แปลง loop แบบ imperative ให้เป็นโซ่ของขั้นตอนที่มีชื่อ ได้แก่ filter, map, reduce
แต่ละบทเรียนใช้ตัวอย่าง before-and-after ชุดเดียวกันใน TypeScript, Python, Go และ Rust แล้วพาไล่ mechanics ทีละขั้นแบบปลอดภัย โดยรัน test คั่นทุกขั้นตอน