บทที่ 7: While You Are Coding — ระหว่างที่เขียนโค้ด
4 min readภาพรวม
การเขียนโค้ดไม่ใช่กระบวนการทางกล (mechanical process) — มันคือการตัดสินใจทุกนาทีที่ต้องใช้ความคิดและการตัดสินใจอย่างรอบคอบ บทนี้ครอบคลุมเทคนิคตั้งแต่การฟังสัญชาตญาณ ไปจนถึงการตั้งชื่อ ครอบคลุม 8 หัวข้อ
Topic 37: Listen to Your Lizard Brain — ฟังเสียงสมองส่วนสัตว์เลื้อยคลาน
Tip 61: Listen to Your Inner Lizard — ฟังเสียงภายใน
เมื่อ intuition บอกว่ามีอะไรบางอย่างผิดปกติ — ฟังมัน มันมักจะถูก สมองส่วนลึกของคุณรับรู้ pattern โดยที่คุณไม่รู้ตัว — เมื่อรู้สึกว่าโค้ด "ไม่ถูก" หรือ design "ฝืน" ให้หยุดและตรวจสอบ
สิ่งที่ควรทำเมื่อสัญชาตญาณส่งสัญญาณ:
- หยุดสิ่งที่กำลังทำ
- สังเกตว่าความรู้สึกนั้นเกี่ยวกับอะไร — โค้ดส่วนไหน, design ส่วนไหน
- ถ้ามันรู้สึกผิด — มันอาจจะผิดจริง ๆ
Topic 38: Programming by Coincidence — การเขียนโปรแกรมด้วยความบังเอิญ
Tip 62: Don't Program by Coincidence — อย่าเขียนโปรแกรมด้วยความบังเอิญ
Programming by coincidence คือการที่โค้ดทำงานได้ — แต่คุณไม่รู้ว่า ทำไม มันถึงทำงาน — คุณลองนั่นลองนี่จนมันทำงานโดยบังเอิญ นี่คือกับระเบิดรอเวลาที่จะระเบิดเมื่อเงื่อนไขเปลี่ยน
อาการของ programming by coincidence:
- ลองเพิ่มโค้ดบางอย่าง — มันทำงาน — ไม่ถามว่าทำไม
- assumption ที่ไม่ได้ตรวจสอบ
- "มันทำงานบนเครื่องฉันนี่นา"
- ติดตั้ง library โดยไม่รู้ว่ามันทำอะไร
ต้องรู้ว่า ทำไม โค้ดถึงทำงาน — ไม่ใช่แค่ว่ามันทำงาน — ถ้าไม่เข้าใจ — หยุดและหาคำตอบก่อนเดินต่อ
Topic 39: Algorithm Speed — ความเร็วของอัลกอริทึม
Tip 63: Estimate the Order of Your Algorithms — ประมาณ order ของอัลกอริทึม
Tip 64: Test Your Estimates — ทดสอบการประมาณของคุณ
Big-O Notation เป็นวิธีประมาณว่าเวลา/ทรัพยากรที่ใช้เพิ่มขึ้นอย่างไรเมื่อขนาด input เพิ่ม:
| Notation | ชื่อ | ตัวอย่าง |
|---|---|---|
| O(1) | Constant | เข้าถึง array element |
| O(log n) | Logarithmic | Binary search |
| O(n) | Linear | Sequential search |
| O(n log n) | Linearithmic | Quicksort (average) |
| O(n²) | Quadratic | Bubble sort |
| O(2ⁿ) | Exponential | Traveling salesman |
คำแนะนำ: ถ้าคุณมีลูปซ้อนกัน — alert! รู้ว่า Big-O ของโค้ดคุณคืออะไร — ทดสอบด้วยข้อมูลจริง — อย่า optimize โดยไม่วัดก่อน
Topic 40: Refactoring — การรีแฟกเตอร์
Tip 65: Refactor Early, Refactor Often — รีแฟกเตอร์ตั้งแต่เนิ่น ๆ และบ่อย ๆ
Refactoring คือการปรับโครงสร้างโค้ดโดยไม่เปลี่ยนพฤติกรรมภายนอก — เป้าหมายคือทำให้โค้ด ETC (Easier To Change)
เมื่อไหร่ควร refactor:
- Duplication (DRY violation)
- Non-orthogonal design
- ความรู้ที่ล้าสมัย (requirements เปลี่ยน, ความเข้าใจ domain ดีขึ้น)
- Performance issues
- การผ่าน tests — นี่คือเวลาที่ดีที่สุด เพราะคุณมี safety net
หลักการ:
- อย่า refactor และเพิ่มฟีเจอร์พร้อมกัน
- มี good tests ก่อนเริ่ม refactoring
- ก้าวสั้น ๆ — เปลี่ยนทีละน้อยแล้ว test
Martin Fowler: "Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure."
Topic 41: Test to Code — ทดสอบระหว่างเขียนโค้ด
Tip 66: Testing Is Not About Finding Bugs — การทดสอบไม่ใช่การหา bugs
Tip 67: A Test Is the First User of Your Code — test คือผู้ใช้คนแรกของโค้ดคุณ
Tip 69: Build End-to-End, Not Top-Down or Bottom-Up — สร้างแบบ end-to-end
Tip 70: Test Your Software, or Your Users Will — ทดสอบซอฟต์แวร์ของคุณ ไม่งั้นผู้ใช้จะทดสอบให้
Testing ไม่ใช่แค่การหา bugs — มันคือการได้ feedback ต่อ design, API, coupling ของคุณ — ประโยชน์หลักของการทดสอบเกิดตอนที่คุณ คิดและเขียน tests — ไม่ใช่ตอนที่คุณ run มัน
Test-Driven Development (TDD): เขียน test ก่อนเขียนโค้ด — test คือ specification ที่ executable ได้ — มันบังคับให้คุณคิดเกี่ยวกับ interface ก่อน implementation
ประโยชน์ของการทดสอบ:
- ทำให้ coupling ชัดเจน — ถ้า test เขียนยาก แสดงว่าโค้ด coupled เกินไป
- เป็น documentation ที่ executable ได้
- ให้ความมั่นใจในการ refactor
Build tests เป็นส่วนหนึ่งของการสร้างซอฟต์แวร์ — ไม่ใช่ phase ที่แยกออกมาต่างหาก
Topic 42: Property-Based Testing — การทดสอบแบบ property-based
Tip 71: Use Property-Based Tests to Validate Your Assumptions
แทนที่จะเขียน test cases ด้วย input ที่คุณคิดเอง — ให้คอมพิวเตอร์ generate input แบบสุ่มตาม constraints ที่คุณกำหนด — และตรวจสอบว่า properties (contracts, invariants) ของโค้ดยังคงเป็นจริง
ตัวอย่าง property: หลังจาก sort list — ความยาวต้องเท่าเดิม (invariant) และไม่มี element ใดมากกว่า element ถัดไป
ข้อดี:
- พบ assumptions ที่ผิดพลาดซึ่งคุณไม่เคยนึกถึง
- บังคับให้คุณคิดถึง invariants และ contracts — ทำให้ design ดีขึ้น
- ทดสอบ edge cases ที่คุณอาจมองไม่เห็น
เมื่อพบ bug: สร้าง unit test จาก parameters ที่ทำให้ fail — เพื่อเป็น regression test
Topic 43: Stay Safe Out There — อยู่อย่างปลอดภัย
Tip 72: Keep It Simple and Minimize Attack Surfaces
Tip 73: Apply Security Patches Quickly
Security ไม่ใช่ feature — มันคือ mindset นักพัฒนาที่ careless คือสาเหตุของ data breaches เกือบทั้งหมด — ไม่ใช่เพราะแฮกเกอร์เก่ง
หลักการพื้นฐานด้านความปลอดภัย:
- Minimize Attack Surface Area: โค้ดซับซ้อน = attack vectors มากขึ้น — ข้อมูลจากภายนอกต้อง sanitize — authenticated/unauthenticated services ต้องคิดให้ดี — output data และ debugging info ก็เป็น attack vectors
- Principle of Least Privilege: ใช้สิทธิ์น้อยที่สุดเท่าที่จำเป็น — ในเวลาสั้นที่สุด
- Secure Defaults: ค่า default ต้องปลอดภัยที่สุด — ให้ผู้ใช้เลือกลดความปลอดภัยเอาเองถ้าต้องการ
- Encrypt Sensitive Data: อย่าเก็บ PII, passwords, credentials ใน plain text
- Maintain Security Updates: อัปเดต security patches ทันที — data breaches ครั้งใหญ่ที่สุดในประวัติศาสตร์เกิดจากระบบที่ไม่อัปเดต
กฎเหล็กของ cryptography: อย่าทำเอง — ใช้ libraries ที่ผ่านการตรวจสอบอย่างดีแล้วเท่านั้น
Password Antipatterns: อย่าจำกัดความยาวน้อยกว่า 64 ตัวอักษร — อย่า disable paste — อย่าบังคับเปลี่ยนรหัสผ่านโดยไม่มีเหตุ — อย่าบังคับ composition rules (ตัวใหญ่/เล็ก/ตัวเลข/พิเศษ)
Topic 44: Naming Things — การตั้งชื่อ
Tip 74: Name Well; Rename When Needed
ชื่อมีความสำคัญอย่างยิ่ง — สมองมนุษย์อ่านและเข้าใจคำได้เร็วกว่ากิจกรรมอื่น ๆ (Stroop Effect) — ดังนั้นชื่อที่ดีช่วยให้เข้าใจโค้ดได้เร็วขึ้น
หลักการตั้งชื่อ:
- ตั้งชื่อตามบทบาท (role) ที่สิ่งนั้นเล่นในโค้ด — ไม่ใช่แค่สิ่งที่มันทำ
- ถามตัวเอง: "แรงจูงใจในการสร้างสิ่งนี้คืออะไร?"
- ใช้ชื่อที่เฉพาะเจาะจง:
buyerแทนuser,applyDiscountแทนdeductPercent - ใช้ types เพื่อสื่อความหมาย:
Percentageแทนdouble - Honor the culture: ใช้ convention ของภาษานั้น ๆ —
i,j,kในภาษา C เป็นที่ยอมรับ แต่ใน Clojure ไม่ใช่ - Consistency: ใช้คำศัพท์เดียวกันทั่วทั้งโปรเจกต์ — สร้าง project glossary
- เมื่อความหมายเปลี่ยน — เปลี่ยนชื่อทันที — อย่าปล่อยให้มี misleading names