Keywords: tooling, testing, modules, playbook
อ่านแบบคน Python:
- ถ้าอยากเอา “ภาพรวม” ก่อน: จำ 4 คำสั่งแกน
check → test → fmt → clippy - ถ้าอยาก “ลงมือทำ”: ใช้
cargo checkเป็น default แล้วค่อยไล่ step ถัดไป - ถ้าติด: เปิด 12-learning-playbook.md
บทนี้สั้นแต่สำคัญ: ทำให้ workflow Rust ลื่นแบบมืออาชีพ
ถ้าคุณมาจาก Python คุณอาจคุ้นกับวงจรประมาณนี้:
- แก้โค้ด → รัน → เจอ error → แก้ → รันใหม่
Rust ก็ทำแบบนั้นได้ แต่ถ้าจับ workflow ที่ถูก คุณจะรู้สึกว่า:
- แก้โค้ด →
cargo check/cargo test→ ได้ feedback ที่ชัด → แก้ต่อแบบไม่เดา
แนวคิดหลักของบทนี้:
- ให้ compiler + tests + lints เป็น “ระบบ feedback” ที่คอยพาคุณไปทางที่ถูก
- ลดการเสียเวลาไปกับ bug ที่ตรวจได้ตั้งแต่ก่อนรัน
กรณีศึกษาจากโค้ด Python จริงที่เจอบ่อย (สิ่งที่ควรเลี่ยง):
- ติดตั้ง dependency ตอน runtime (เช่นเรียก
pip install ...ในโค้ด) → พังยาก, reproducibility แย่, และเสี่ยงด้านความปลอดภัย
Rust ชอบให้ “dependencies ถูกประกาศ” และ “สภาพแวดล้อมนิ่ง”:
- dependencies อยู่ใน
Cargo.tomlและถูกล็อกด้วยCargo.lock - โค้ดควรจะ “รันได้เหมือนเดิม” ระหว่างเครื่อง dev/CI/production
ถ้าคุณกำลังแก้โค้ดอยู่ ให้ยึด 4 ตัวนี้เป็นแกน:
cargo check(เร็วที่สุด)
- ไล่ type/borrow errors
cargo test
- ยืนยันพฤติกรรม (ไม่ใช่แค่ compile ผ่าน)
cargo fmt
- จัดรูปแบบให้มาตรฐาน
cargo clippy
- เก็บ lint/code smell และ pattern เสี่ยง
ถ้าคุณทำตามลำดับนี้เป็นนิสัย คุณจะรู้สึกว่า “คุมระบบได้” มากขึ้นแบบชัดเจน
Python (เทียบคำสั่งที่คุ้น):
- รันไฟล์:
python main.py - รันโมดูล:
python -m package.module
Rust:
cargo run
cargo build
cargo check
cargo build --releaseความหมายโดยย่อ:
cargo run= build + run (เหมาะตอนอยากเห็น behavior)cargo build= build อย่างเดียว (เช็คว่า compile ผ่าน)cargo check= type-check/borrow-check แบบเร็ว (เหมาะตอนยังแก้อยู่)cargo build --release= build แบบ optimized (เหมาะตอนอยากวัด performance/ปล่อยใช้งาน)
จุดต่างที่ควรรู้:
cargoจะ cache ผลลัพธ์การ build (incremental) ทำให้แก้เล็ก ๆ แล้วรันเร็วขึ้น- ถ้าเจอ error compile: ให้แก้ให้ผ่านก่อนค่อยไปขั้นต่อไป (อย่าพยายาม “รันฝืน”) เพราะ Rust ตั้งใจให้ error ถูกแก้ตั้งแต่ต้นทาง
ทิป: ถ้าคุณรันโปรแกรมผ่าน cargo run แล้วอยากส่ง args ให้ binary ต้องคั่นด้วย --
- ตัวอย่าง:
cargo run -- status
cargo fmt (rustfmt) คือ auto-formatter มาตรฐานของ Rust ecosystem
ทำไมมันสำคัญกว่าที่คิด:
- เวลาอ่านโค้ด Rust คนมักคาดหวัง format มาตรฐาน → ถ้าทุกไฟล์เหมือนกัน คุณจะโฟกัสที่ “ตรรกะ” ไม่ใช่ “สไตล์”
- ลด churn ใน code review (ไม่เถียงเรื่องเว้นวรรค/วงเล็บ)
แนวทางใช้งาน:
- รันก่อน commit/แชร์โค้ด
- ถ้า IDE รองรับ ให้ตั้ง format-on-save จะช่วยมาก
cargo clippy คือ linter ที่เก่งมากของ Rust ecosystem
มันช่วยอะไรในทางปฏิบัติ:
- ชี้ code smell ที่ compile ผ่านแต่ “เสี่ยง” (เช่น clone เกินจำเป็น)
- ชี้ bug pattern ที่คนเขียนใหม่ ๆ มักพลาด
- ให้ feedback แบบมีเหตุผล (หลายอันมีข้อความแนะนำพร้อมตัวอย่าง)
วิธีใช้ clippy แล้วไม่หงุดหงิด:
- มองว่า clippy คือ “รีวิวอัตโนมัติ” ไม่ใช่การจับผิดส่วนตัว
- แก้ทีละอัน โดยเริ่มจาก warning ที่เกี่ยวกับ correctness ก่อน แล้วค่อยไล่เรื่อง style/perf
Test คือ “เบรก” ที่ช่วยให้คุณ refactor ได้เร็วโดยไม่พังเงียบ ๆ
Python (เทียบกับสิ่งที่คุ้น):
- แบบง่ายสุด:
assertในไฟล์ - หรือใช้
pytest/unittest
Rust mindset:
- unit test มักอยู่ใกล้โค้ด (ในไฟล์เดียวกัน) และถูก compile แยกตอน
cargo test - Rust strict ทำให้ bug เชิงโครงสร้างบางชนิด “ไม่เกิด” ตั้งแต่แรก แต่คุณยังต้อง test พฤติกรรม (business rules) อยู่ดี
ตัวอย่าง (Python):
def add(a: int, b: int) -> int:
return a + b
def test_add() -> None:
assert add(1, 2) == 3Output (example):
(no output — tests pass silently)
Rust:
fn add(a: i32, b: i32) -> i32 {
a + b
}
#[test]
fn test_add() {
assert_eq!(add(1, 2), 3);
}Output (example):
(no output — tests pass silently)
ทิปที่ใช้จริง:
- ถ้าต้องการเห็น output (
println!) ตอน test ผ่านด้วย ให้รันcargo test -- --nocapture - ถ้าต้องการรันแค่บาง test:
cargo test name_of_test
Rust ecosystem ใช้ doc comments และ cargo doc
cargo docสร้างเอกสารของโปรเจกต์และ dependencies- อ่าน docs.rs และ std docs ได้เร็วมาก ถ้าคุณคุ้นกับ pattern ของมัน
เวลาแก้ปัญหาแบบไม่หลงทาง ให้คิดเป็นวงจร:
- ทำให้ compile ผ่าน (
cargo check) - ทำให้พฤติกรรมถูก (
cargo test) - ทำให้โค้ดอ่านง่าย (
cargo fmt) - ทำให้หลบ bug pattern (
cargo clippy)
-
สร้างโปรเจกต์ใหม่แล้วรัน
cargo fmtและcargo clippy -
เพิ่ม test 1 ตัวและรัน
cargo test -
ลองทำให้ test fail 1 ครั้ง แล้วอ่าน output ว่ามันช่วยบอกอะไร
-
(เสริม) ลองสร้างสถานการณ์ “dependency หาย” แล้วสังเกต workflow ที่ดี
- Python: ถ้าโปรเจกต์พึ่ง
pip installตอน runtime คุณจะเจอความไม่แน่นอน (เครื่องนี้มี/เครื่องนั้นไม่มี) - Rust: ทดลองเพิ่ม dependency ใน
Cargo.tomlแล้วรันcargo build/cargo checkดูว่า error ชัดขึ้นยังไง