
บทความนี้สรุปภาพรวมของเครื่องมือพัฒนาซอฟต์แวร์ (Software Development Tools) ครอบคลุมทั้ง Text Editor, IDE, Compiler/Interpreter, Build System, Debugger, Package Manager, Documentation, CI/CD, Testing และ Code Quality Tools พร้อมตัวอย่างใช้งานจริงบน Linux เพื่อให้ผู้เรียนสร้าง Toolchain ที่เหมาะกับงานของตนเองได้
การพัฒนาซอฟต์แวร์ในยุคปัจจุบันเป็นงานที่ซับซ้อนและประกอบด้วยขั้นตอนจำนวนมาก นักพัฒนาจึงไม่สามารถทำงานทั้งหมดด้วยมือหรือเครื่องมือเพียงชิ้นเดียวได้ เครื่องมือพัฒนาซอฟต์แวร์ (Development Tools) คือชุดของโปรแกรมที่ช่วยให้นักพัฒนาเขียน (Write), สร้าง (Build), ทดสอบ (Test), ดีบั๊ก (Debug), และนำขึ้นใช้งาน (Deploy) ซอฟต์แวร์ได้อย่างมีประสิทธิภาพ
วงจรการพัฒนาซอฟต์แวร์ (Software Development Life Cycle – SDLC) คือกระบวนการที่กำหนดขั้นตอนการสร้างระบบซอฟต์แวร์ตั้งแต่เริ่มต้นจนถึงการบำรุงรักษา โดยแต่ละขั้นตอนจะมีเครื่องมือที่เหมาะสมเข้ามาช่วย
flowchart LR
A[วางแผน
Planning]:::gruvblue --> B[วิเคราะห์
Analysis]:::gruvaqua
B --> C[ออกแบบ
Design]:::gruvgreen
C --> D[พัฒนา
Implementation]:::gruvyellow
D --> E[ทดสอบ
Testing]:::gruvorange
E --> F[นำขึ้นใช้งาน
Deployment]:::gruvred
F --> G[บำรุงรักษา
Maintenance]:::gruvpurple
G -.Iterate.-> A
classDef gruvblue fill:#458588,stroke:#83a598,color:#ebdbb2
classDef gruvaqua fill:#689d6a,stroke:#8ec07c,color:#ebdbb2
classDef gruvgreen fill:#98971a,stroke:#b8bb26,color:#282828
classDef gruvyellow fill:#d79921,stroke:#fabd2f,color:#282828
classDef gruvorange fill:#d65d0e,stroke:#fe8019,color:#ebdbb2
classDef gruvred fill:#cc241d,stroke:#fb4934,color:#ebdbb2
classDef gruvpurple fill:#b16286,stroke:#d3869b,color:#ebdbb2
แนวคิด SDLC มีหลายโมเดล เช่น
Toolchain หมายถึงชุดเครื่องมือที่ทำงานร่วมกันตลอดสายการผลิตซอฟต์แวร์ (Software Pipeline) คำว่า "chain" สื่อความหมายว่าเครื่องมือหนึ่งรับผลลัพธ์จากอีกเครื่องมือหนึ่งต่อกันไปเหมือนสายโซ่
flowchart TB
subgraph Dev["Development Toolchain"]
direction LR
A1[Editor/IDE]:::gruvblue --> A2[Compiler/Interpreter]:::gruvaqua
A2 --> A3[Linker/Bundler]:::gruvgreen
A3 --> A4[Executable/Artifact]:::gruvyellow
end
subgraph QA["Quality Assurance"]
direction LR
B1[Linter]:::gruvorange --> B2[Formatter]:::gruvorange
B2 --> B3[Test Runner]:::gruvred
B3 --> B4[Coverage]:::gruvpurple
end
subgraph Ops["Operations"]
direction LR
C1[Version Control
Git]:::gruvblue --> C2[CI/CD]:::gruvaqua
C2 --> C3[Registry/Artifact Store]:::gruvgreen
C3 --> C4[Deployment]:::gruvred
end
Dev --> QA
QA --> Ops
classDef gruvblue fill:#458588,stroke:#83a598,color:#ebdbb2
classDef gruvaqua fill:#689d6a,stroke:#8ec07c,color:#ebdbb2
classDef gruvgreen fill:#98971a,stroke:#b8bb26,color:#282828
classDef gruvyellow fill:#d79921,stroke:#fabd2f,color:#282828
classDef gruvorange fill:#d65d0e,stroke:#fe8019,color:#ebdbb2
classDef gruvred fill:#cc241d,stroke:#fb4934,color:#ebdbb2
classDef gruvpurple fill:#b16286,stroke:#d3869b,color:#ebdbb2
ตัวอย่าง Toolchain สำหรับพัฒนา Web Application ด้วย Python:
| ขั้นตอน (Stage) | เครื่องมือ (Tool) | หน้าที่ (Role) |
|---|---|---|
| เขียนโค้ด | Neovim / VS Code | Text Editor |
| จัดการ Dependency | uv / Poetry | Package Manager |
| รันโปรแกรม | Python (CPython) | Interpreter |
| ตรวจคุณภาพโค้ด | Ruff | Linter + Formatter |
| ทดสอบ | pytest | Test Runner |
| คุมเวอร์ชัน | Git | VCS |
| Build/Deploy | GitHub Actions + Docker | CI/CD + Container |
เครื่องมือพัฒนาซอฟต์แวร์แบ่งออกเป็น 2 กลุ่มใหญ่ตามรูปแบบการใช้งาน
Command-line Interface (CLI) Tools
git, gcc, make, docker, sshGraphical User Interface (GUI) Tools
นักพัฒนาในยุคปัจจุบันนิยมผสมผสานทั้งสองแบบ ใช้ CLI สำหรับงานที่ต้อง Automate และ GUI สำหรับงานที่ต้อง Visualize ข้อมูลซับซ้อน
Developer Experience (DevEx) คือแนวคิดเกี่ยวกับประสบการณ์รวมของนักพัฒนาเมื่อใช้เครื่องมือ แพลตฟอร์ม และกระบวนการในการทำงาน เปรียบได้กับ User Experience (UX) ที่ให้ความสำคัญกับผู้ใช้ปลายทาง แต่ DevEx ให้ความสำคัญกับ "นักพัฒนา" เป็นผู้ใช้งานแทน
หลัก 3 ข้อของ DevEx ที่ดี (ตามงานวิจัยของ Nicole Forsgren และคณะ):
สามารถวัดเชิงคุณภาพได้จากสมการดัชนี DevEx เบื้องต้น:
โดยที่ คือคะแนน Flow State, คือความเร็วของ Feedback Loop (เช่น 1/เวลาที่ใช้ Build), คือ Cognitive Load ที่วัดจากจำนวนขั้นตอน, คือน้ำหนักของแต่ละปัจจัย และ คือค่าคงที่เพื่อป้องกันการหารด้วยศูนย์
ตัวอย่างปัจจัยที่ส่งผลต่อ DevEx:
Text Editor และ IDE เป็นเครื่องมือหลักที่นักพัฒนาใช้ทำงานทุกวัน การเลือกเครื่องมือที่เหมาะกับภาษาและสไตล์การทำงานมีผลต่อประสิทธิภาพระยะยาวอย่างมาก
Text Editor คือโปรแกรมแก้ไขไฟล์ข้อความล้วน (Plain Text) ไม่มีการ Compile หรือ Debug ในตัวเอง แต่มีความเบา (Lightweight) และปรับแต่งได้สูง
ตัวอย่างการเปิดแก้ไขไฟล์ hello.py ด้วย editor แต่ละตัว:
# เปิดไฟล์ด้วย nano (เหมาะสำหรับผู้เริ่มต้น)
nano hello.py
# เปิดด้วย Vim
vim hello.py
# เปิดด้วย Neovim
nvim hello.py
# เปิดด้วย Helix
hx hello.py
# เปิดด้วย Emacs ในโหมด terminal
emacs -nw hello.py
Lightweight IDE คือโปรแกรมที่อยู่กลางระหว่าง Text Editor กับ Full IDE มีฟีเจอร์ครบถ้วนพอสมควร เปิดได้เร็ว ใช้ทรัพยากรน้อยกว่า Full IDE
ตัวอย่างการเปิด project ด้วย VS Code จาก command line:
# เปิดโฟลเดอร์ปัจจุบันใน VS Code
code .
# เปิดไฟล์เฉพาะพร้อมระบุบรรทัด
code hello.py:42
# ติดตั้ง Extension จาก CLI
code --install-extension ms-python.python
code --install-extension charliermarsh.ruff
# เปิด Zed
zed .
Full-featured IDE คือ Integrated Development Environment ที่รวมเครื่องมือสำหรับพัฒนาซอฟต์แวร์ไว้ครบในโปรแกรมเดียว ได้แก่ Editor, Compiler/Interpreter, Debugger, Profiler, Build Tool, VCS Integration, Database Tool และอื่น ๆ
JetBrains Suite – ตระกูล IDE คุณภาพสูง แบ่งตามภาษา:
Eclipse: IDE ฟรี Open-source ที่เริ่มจากพัฒนา Java แต่ขยายสู่ภาษาอื่นผ่าน Plugin และเป็น Base ของ IDE อื่น ๆ เช่น STS, Spoon Gear
NetBeans: IDE จาก Apache Foundation รองรับ Java, PHP, C/C++ มักใช้ในงานการศึกษา
เปรียบเทียบการใช้ทรัพยากรของ Editor/IDE ยอดนิยม:
| เครื่องมือ | ใช้ RAM เริ่มต้น | ภาษาหลัก | AI Built-in | Open-source |
|---|---|---|---|---|
| nano | ~5 MB | ทุกภาษา | ไม่มี | ใช่ (GPL) |
| Vim | ~10 MB | ทุกภาษา | ผ่าน Plugin | ใช่ (Vim License) |
| Neovim | ~15 MB | ทุกภาษา | ผ่าน Plugin | ใช่ (Apache 2.0) |
| Helix | ~30 MB | ทุกภาษา | ผ่าน LSP | ใช่ (MPL 2.0) |
| VS Code | ~300 MB | ทุกภาษา | Copilot | บางส่วน (MIT) |
| Zed | ~150 MB | ทุกภาษา | Agent Panel | ใช่ (GPL v3) |
| IntelliJ IDEA | ~1.5 GB | Java/Kotlin | AI Assistant | Community Edition |
| Cursor | ~400 MB | ทุกภาษา | ใช่ (เน้น AI) | ไม่ใช่ |
IDE บางตัวถูกออกแบบมาเฉพาะสำหรับภาษาหรือแพลตฟอร์มหนึ่ง ๆ เพื่อให้ประสบการณ์ที่ดีที่สุดในด้านนั้น
การที่ซอร์สโค้ดจะกลายเป็นโปรแกรมที่ทำงานได้นั้น ต้องผ่านกระบวนการแปล (Translation) จากภาษาที่มนุษย์เข้าใจไปเป็นคำสั่งที่เครื่องเข้าใจ กระบวนการนี้ทำโดย Compiler หรือ Interpreter และอาจต้องอาศัย Runtime System ในการรัน
GCC (GNU Compiler Collection): Compiler ดั้งเดิมของ GNU Project รองรับหลายภาษา เช่น C, C++, Objective-C, Fortran, Ada, Go เป็น Compiler ที่ใช้คอมไพล์ Linux Kernel
Clang/LLVM: Compiler Front-end (Clang) + Back-end (LLVM) ออกแบบใหม่ให้เป็น Modular มี Error Message ที่ชัดเจนกว่า GCC เป็นเครื่องมือหลักของ macOS/FreeBSD
MSVC (Microsoft Visual C++): Compiler ของ Microsoft สำหรับ Windows ใช้ร่วมกับ Visual Studio
ตัวอย่างการ Compile โปรแกรม C อย่างง่าย:
// hello.c - โปรแกรมตัวอย่างภาษา C
// แสดงข้อความพร้อมรับชื่อจาก argument
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
// ถ้าไม่มี argument ใช้ "World" เป็นค่า default
const char *name = (argc > 1) ? argv[1] : "World";
printf("Hello, %s!\n", name);
return 0;
}
คำสั่ง Compile และรัน:
# Compile ด้วย GCC พร้อม optimization level 2 และเปิด warning ทุกตัว
gcc -O2 -Wall -Wextra -o hello hello.c
# Compile ด้วย Clang
clang -O2 -Wall -Wextra -o hello hello.c
# Cross-compile สำหรับ ARM64
aarch64-linux-gnu-gcc -O2 -o hello-arm64 hello.c
# รัน
./hello Moo
# Output: Hello, Moo!
JVM (Java Virtual Machine) เป็น Virtual Machine ที่รัน Bytecode (.class) ที่ได้จากการ Compile ภาษาตระกูล JVM เช่น Java, Kotlin, Scala, Groovy, Clojure
javac: Compiler ของ Java ที่แปลง .java → .class
JVM Implementations:
ตัวอย่างภาษา Java:
// HelloWorld.java - โปรแกรมตัวอย่างภาษา Java
public class HelloWorld {
public static void main(String[] args) {
// รับชื่อจาก argument ถ้ามี
String name = (args.length > 0) ? args[0] : "World";
System.out.println("Hello, " + name + "!");
}
}
# Compile เป็น bytecode
javac HelloWorld.java
# รันด้วย JVM
java HelloWorld Moo
# Output: Hello, Moo!
# รันแบบ Native Image ด้วย GraalVM (ถ้าติดตั้งไว้)
native-image HelloWorld
./helloworld Moo
.NET เป็นแพลตฟอร์มจาก Microsoft ประกอบด้วย
ตัวอย่างสร้าง Console App ด้วย .NET:
# สร้างโปรเจกต์ใหม่แบบ console
dotnet new console -n HelloApp
cd HelloApp
# เพิ่ม dependency
dotnet add package Newtonsoft.Json
# รัน
dotnet run -- Moo
# Build เป็น executable
dotnet publish -c Release -r linux-x64 --self-contained
Interpreter คือโปรแกรมที่อ่านและรันโค้ดทีละบรรทัดโดยไม่ต้อง Compile ล่วงหน้า ทำให้เริ่มต้นได้เร็วแต่ทำงานช้ากว่า Compiled Language
เปรียบเทียบการรัน Hello World ในภาษา Interpreter ต่าง ๆ:
# Python
python3 -c "print('Hello, World!')"
# Node.js
node -e "console.log('Hello, World!')"
# Ruby
ruby -e "puts 'Hello, World!'"
# Perl
perl -e "print 'Hello, World!\n'"
ภาษา Compiled ยุคใหม่ที่เน้น Memory Safety, Concurrency และประสิทธิภาพสูง
ตัวอย่างโค้ด Rust ที่ใช้ memory safety ในตัว:
// hello.rs - โปรแกรมตัวอย่างภาษา Rust
// แสดงชื่อที่รับจาก command-line argument
use std::env;
fn main() {
// รวบรวม arguments จาก command line
let args: Vec<String> = env::args().collect();
// ใช้ match pattern เพื่อเลือก default ถ้าไม่มี arg
let name = match args.get(1) {
Some(n) => n.as_str(),
None => "World",
};
println!("Hello, {}!", name);
}
# Compile ด้วย rustc
rustc -O hello.rs -o hello
./hello Moo
# หรือสร้างโปรเจกต์ด้วย Cargo
cargo new hello_proj
cd hello_proj
cargo run -- Moo
ตัวอย่างโค้ด Go:
// hello.go - โปรแกรมตัวอย่างภาษา Go
package main
import (
"fmt"
"os"
)
func main() {
// รับ argument ที่ 1 หรือใช้ "World" เป็น default
name := "World"
if len(os.Args) > 1 {
name = os.Args[1]
}
fmt.Printf("Hello, %s!\n", name)
}
# รันโดยตรง
go run hello.go Moo
# Build เป็น binary static link
go build -o hello hello.go
./hello Moo
Cross-compilation คือการ Compile โปรแกรมบนเครื่องหนึ่ง (Host) เพื่อให้ทำงานบนอีกเครื่อง/สถาปัตยกรรมหนึ่ง (Target)
Target Triple คือรหัสระบุแพลตฟอร์มเป้าหมาย ในรูปแบบ <arch>-<vendor>-<os>-<abi> เช่น
x86_64-unknown-linux-gnu – Linux 64-bit x86aarch64-apple-darwin – macOS ARM (Apple Silicon)x86_64-pc-windows-msvc – Windows 64-bit with MSVCarmv7-unknown-linux-gnueabihf – Raspberry Pi 32-bitwasm32-unknown-unknown – WebAssemblyตัวอย่าง Cross-compile ด้วย Rust:
# ติดตั้ง target
rustup target add aarch64-unknown-linux-gnu
# Compile สำหรับ ARM64 Linux
cargo build --release --target aarch64-unknown-linux-gnu
# Go cross-compile (ง่ายกว่ามาก เพราะ built-in)
GOOS=linux GOARCH=arm64 go build -o hello-arm64 hello.go
GOOS=windows GOARCH=amd64 go build -o hello.exe hello.go
เมื่อโปรเจกต์มีไฟล์หลายไฟล์ การ Compile/รันด้วยมือเป็นเรื่องยาก จึงเกิด Build System ขึ้นเพื่อจัดการขั้นตอนเหล่านี้ให้อัตโนมัติ รวมถึง Task Runner ที่ช่วยจัดการงานซ้ำ ๆ ทั่วไป
Make เป็น Build Tool ที่เก่าแก่ที่สุด พัฒนาในปี 1976 ใช้ไฟล์ Makefile กำหนดกฎการ build แบบ Declarative ด้วยแนวคิด "ถ้า target เก่ากว่า prerequisite ให้รัน recipe"
# Makefile - ตัวอย่าง Build C project
# ตัวแปร
CC = gcc
CFLAGS = -O2 -Wall -Wextra
TARGET = hello
SRCS = hello.c util.c
OBJS = $(SRCS:.c=.o)
# กฎ default (เรียกเมื่อพิมพ์ make เปล่า ๆ)
all: $(TARGET)
# Link object files เป็น executable
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $@ $^
# Pattern rule: Compile .c เป็น .o
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
# Phony target สำหรับคำสั่งพิเศษ
.PHONY: clean test
clean:
rm -f $(OBJS) $(TARGET)
test: $(TARGET)
./$(TARGET) Moo
การใช้งาน:
make # build ทั้งหมด
make clean # ลบไฟล์ที่ build
make test # build แล้ว run test
make -j4 # build แบบ parallel 4 jobs
CMake: Meta Build System ที่ Generate Makefile, Ninja หรือ Visual Studio Project จาก CMakeLists.txt เป็นมาตรฐานของโปรเจกต์ C/C++ ยุคใหม่
Meson: Meta Build System สมัยใหม่ เขียน Config ด้วย Python-like syntax เน้นความเร็วและอ่านง่าย ใช้ Ninja เป็น Back-end
Ninja: Low-level Build System เน้นความเร็วสูงสุด ไม่ออกแบบมาให้มนุษย์เขียนเอง แต่ให้ Tool อื่น Generate ให้
ตัวอย่าง CMakeLists.txt:
# CMakeLists.txt - ตัวอย่างโปรเจกต์ C++ ด้วย CMake
cmake_minimum_required(VERSION 3.20)
project(HelloApp VERSION 1.0.0 LANGUAGES CXX)
# กำหนด C++ standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# เพิ่ม executable จาก source files
add_executable(hello
src/main.cpp
src/util.cpp
)
# ระบุ include directory
target_include_directories(hello PRIVATE include)
# Compiler warnings
target_compile_options(hello PRIVATE -Wall -Wextra)
คำสั่ง Build:
# Out-of-source build pattern
mkdir build && cd build
cmake .. # Configure (generate build files)
cmake --build . -j8 # Build parallel 8 threads
./hello
GNU Autotools เป็นชุดเครื่องมือคลาสสิก (autoconf, automake, libtool) ที่ Generate configure script สำหรับตรวจสอบ Environment ของระบบก่อน Build ใช้ในโปรเจกต์ Open-source เก่า ๆ จำนวนมาก
ขั้นตอนการติดตั้งโปรแกรมจากซอร์สโค้ดแบบคลาสสิก:
# 1. Extract ซอร์สโค้ด
tar -xzf program-1.0.tar.gz
cd program-1.0
# 2. Configure: ตรวจสอบ environment และ generate Makefile
./configure --prefix=/usr/local
# 3. Build
make -j$(nproc)
# 4. Install (ต้องใช้ sudo ถ้าลงในระบบ)
sudo make install
Maven: Build Tool มาตรฐานของ Java Community ใช้ pom.xml (XML) มี Central Repository
Gradle: Build Tool สมัยใหม่ ใช้ Groovy หรือ Kotlin DSL ยืดหยุ่นและเร็วกว่า Maven เป็น default ของ Android
SBT (Scala Build Tool): Build Tool สำหรับ Scala และโปรเจกต์ Functional
ตัวอย่าง build.gradle.kts สำหรับโปรเจกต์ Kotlin:
// build.gradle.kts
plugins {
kotlin("jvm") version "2.0.0"
application
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
testImplementation(kotlin("test"))
}
application {
mainClass.set("com.example.MainKt")
}
./gradlew build # build โปรเจกต์
./gradlew run # รัน application
./gradlew test # รัน unit test
ในโลก JavaScript/TypeScript มี Package Manager หลายตัวที่รวมบทบาทของ Task Runner ไปด้วย
ตัวอย่าง package.json กับ npm scripts:
{
"name": "my-app",
"version": "1.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"test": "vitest",
"lint": "eslint src --ext ts,tsx",
"format": "prettier --write \"src/**/*.{ts,tsx}\""
},
"dependencies": {
"react": "^18.3.0"
},
"devDependencies": {
"vite": "^5.4.0",
"vitest": "^2.0.0",
"eslint": "^9.0.0",
"prettier": "^3.0.0"
}
}
npm install # ติดตั้ง dependencies
npm run dev # รัน script "dev"
pnpm install # เร็วและประหยัด disk กว่า
bun install # เร็วที่สุดในกลุ่ม
bun run build # เร็วมากเมื่อใช้กับ Bun runtime
ภาษาสมัยใหม่มักรวม Build และ Package Manager ไว้ใน CLI เดียว
Cargo (Rust):
cargo new my_app # สร้างโปรเจกต์ใหม่
cargo build # build แบบ debug
cargo build --release # build แบบ optimized
cargo run # build + รัน
cargo test # รัน unit test
cargo add serde # เพิ่ม dependency
cargo fmt # format code
cargo clippy # lint
Go Toolchain:
go mod init example.com/myapp # สร้าง go.mod
go get github.com/gin-gonic/gin # เพิ่ม dependency
go build -o app . # build
go run . # build + run
go test ./... # test ทุก package
go vet ./... # static analysis
Python สมัยใหม่ – uv (เขียนด้วย Rust เร็วกว่า pip 10–100 เท่า):
# สร้างโปรเจกต์
uv init myapp
cd myapp
# เพิ่ม dependency
uv add requests pandas
uv add --dev pytest ruff
# รัน
uv run python main.py
# sync environment จาก uv.lock
uv sync
Task Runner คือ Tool ที่ออกแบบมาเพื่อรันคำสั่งซ้ำ ๆ ในโปรเจกต์ คล้าย make แต่ไม่ใช่ Build System
justfile syntax คล้าย Makefile แต่เรียบง่ายและไม่มี dependency graph ที่ซับซ้อนตัวอย่าง justfile:
# justfile - ตัวอย่างคำสั่งที่ใช้บ่อยในโปรเจกต์
# คำสั่ง default เมื่อพิมพ์ just เปล่า ๆ
default:
@just --list
# รัน server ในโหมด development
dev:
uv run uvicorn app.main:app --reload --port 8000
# รัน test พร้อม coverage
test:
uv run pytest --cov=app tests/
# Format + Lint
fmt:
uv run ruff format .
uv run ruff check --fix .
# Build Docker image
build tag="latest":
docker build -t myapp:{{tag}} .
# Deploy ไปยัง production (รับ arg)
deploy env:
@echo "Deploying to {{env}}..."
ansible-playbook deploy.yml -e env={{env}}
การใช้งาน:
just # แสดง list คำสั่ง
just dev # รัน dev server
just test # test
just build v1.2 # build พร้อม tag v1.2
just deploy production
การหาสาเหตุของ bug และจุดที่ทำงานช้าเป็นงานสำคัญ Debugger ช่วยให้ดูการทำงานของโปรแกรมทีละขั้น ส่วน Profiler ช่วยวิเคราะห์เรื่องประสิทธิภาพ
GDB เป็น Debugger มาตรฐานของ Unix/Linux สำหรับ C/C++/Rust/Go/Fortran รองรับ breakpoint, watchpoint, backtrace, หยุดที่ signal
LLDB เป็น Debugger จากโปรเจกต์ LLVM ใช้เป็น default บน macOS
ตัวอย่างใช้ GDB ดีบั๊ก:
// buggy.c - โปรแกรมตัวอย่างที่มี bug (array out of bounds)
#include <stdio.h>
int main() {
int arr[5] = {1, 2, 3, 4, 5};
int sum = 0;
// bug: วนเกินขอบเขต array (ควรเป็น i < 5)
for (int i = 0; i <= 5; i++) {
sum += arr[i];
}
printf("Sum = %d\n", sum);
return 0;
}
# Compile ด้วย debug symbol (-g) และไม่ optimize (-O0)
gcc -g -O0 -o buggy buggy.c
# เปิด gdb
gdb ./buggy
# คำสั่งภายใน gdb
(gdb) break main # set breakpoint ที่ main
(gdb) run # รันโปรแกรม
(gdb) next # step ข้าม function (step over)
(gdb) step # step เข้า function (step into)
(gdb) print sum # ดูค่าตัวแปร sum
(gdb) print arr[5] # ดูค่านอกขอบเขต
(gdb) watch sum # watch การเปลี่ยนแปลงของ sum
(gdb) backtrace # ดู call stack
(gdb) continue # รันต่อจนจบหรือถึง breakpoint ถัดไป
(gdb) quit
strace – ติดตาม System Call ที่โปรแกรมเรียก ใช้หา bug ระดับ OS interaction
ltrace – ติดตาม Library Call (เช่น libc functions)
# ดู system call ของคำสั่ง ls ทั้งหมด
strace ls /tmp
# ติดตามเฉพาะบาง syscall (เช่น open, read)
strace -e trace=open,openat,read cat /etc/hostname
# วัดเวลาที่ใช้ใน syscall แต่ละตัว
strace -c -f python3 myscript.py
# ดู library call
ltrace -c ./hello Moo
Valgrind เป็นชุด tool สำหรับตรวจสอบ memory และ profiling โปรแกรม C/C++
# ตรวจหา memory leak
valgrind --leak-check=full --show-leak-kinds=all ./myprogram
# Profile ด้วย callgrind
valgrind --tool=callgrind ./myprogram
kcachegrind callgrind.out.* # ดูผลผ่าน GUI
# วัด heap usage
valgrind --tool=massif ./myprogram
ms_print massif.out.*
perf – เครื่องมือ profiling ใน Linux Kernel ใช้ hardware performance counter
gprof – Profiler ดั้งเดิมของ GNU ต้อง compile ด้วย -pg
Flamegraph – วิธีการแสดงผล profiling ในรูป graph แบบ flame (กราฟเปลวไฟ) ทำให้ดู hotspot ง่าย
# Record profiling data (ต้องใช้สิทธิ์)
sudo perf record -F 99 -g ./myprogram
# แสดงรายงาน
sudo perf report
# สร้าง Flamegraph
sudo perf record -F 99 -g ./myprogram
sudo perf script > out.perf
./stackcollapse-perf.pl out.perf | ./flamegraph.pl > flame.svg
สูตรคำนวณ Sampling Rate Overhead โดยประมาณ:
โดยที่ คือความถี่ในการ sample (เช่น 99 Hz), คือเวลาที่ใช้ในการเก็บ 1 sample และ คือเวลา CPU ทั้งหมด ยิ่ง Overhead ต่ำ ยิ่งได้ข้อมูลใกล้ความเป็นจริง
IDE สมัยใหม่ผนวก Debugger เข้าผ่าน Debug Adapter Protocol (DAP) ทำให้ใช้ได้โดยไม่ต้องเปิด Terminal แยก
ตัวอย่าง .vscode/launch.json สำหรับดีบั๊ก Python:
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": false,
"env": {
"PYTHONPATH": "${workspaceFolder}"
}
},
{
"name": "FastAPI Server",
"type": "debugpy",
"request": "launch",
"module": "uvicorn",
"args": ["app.main:app", "--reload"],
"jinja": true
}
]
}
Package Manager คือเครื่องมือที่ช่วยติดตั้ง อัปเดต และถอดถอน Library/โปรแกรมได้แบบอัตโนมัติ โดยจัดการ Dependency ระหว่าง package ให้ด้วย
แต่ละภาษาโปรแกรมมี Package Manager ประจำของตนเอง เก็บ Library ใน Registry ของตัวเอง
| ภาษา | Package Manager | Registry | ไฟล์ Manifest |
|---|---|---|---|
| Python | pip, uv, Poetry | PyPI | requirements.txt, pyproject.toml |
| JavaScript | npm, pnpm, yarn, Bun | npm registry | package.json |
| Rust | Cargo | crates.io | Cargo.toml |
| Go | go mod | (proxy.golang.org) | go.mod |
| Ruby | gem, bundler | RubyGems | Gemfile |
| PHP | Composer | Packagist | composer.json |
| Java | Maven, Gradle | Maven Central | pom.xml, build.gradle |
| .NET | NuGet | nuget.org | .csproj |
| Haskell | cabal, stack | Hackage | *.cabal |
| Elixir | mix + hex | Hex.pm | mix.exs |
Package Manager ระดับ OS จัดการซอฟต์แวร์ทั้งระบบ (รายละเอียดอยู่ในหัวข้อ 2.6)
Environment Manager ช่วยให้มีหลาย version ของภาษาหรือ dependency แยกกันในเครื่องเดียว ป้องกันปัญหา "ทำงานได้บนเครื่องของฉัน" (Works on my machine)
ตัวอย่างการใช้ mise:
# ติดตั้ง mise
curl https://mise.run | sh
# ติดตั้งหลาย version
mise install python@3.12
mise install python@3.11
mise install node@20
mise install rust@stable
# กำหนด version สำหรับโปรเจกต์ (สร้าง .tool-versions หรือ .mise.toml)
cd myproject
mise use python@3.12 node@20
# ตรวจสอบ
mise current
ตัวอย่าง venv ของ Python ล้วน ๆ:
# สร้าง virtual environment
python3 -m venv .venv
# เปิดใช้งาน (Activate)
source .venv/bin/activate # Linux/macOS
# .venv\Scripts\activate # Windows
# ติดตั้ง package ในนี้เท่านั้น
pip install requests pandas
# Export dependency list
pip freeze > requirements.txt
# ปิด environment
deactivate
Lock File เป็นไฟล์ที่เก็บ version ที่ resolve แล้ว (exact version) ของ dependency ทุกตัว รวมถึง dependency ของ dependency (Transitive Dependency) เพื่อให้สร้าง environment ที่เหมือนกันทุกเครื่อง = Reproducible Build
| Package Manager | Lock File |
|---|---|
| npm | package-lock.json |
| pnpm | pnpm-lock.yaml |
| yarn | yarn.lock |
| Cargo | Cargo.lock |
| Poetry | poetry.lock |
| uv | uv.lock |
| Bundler | Gemfile.lock |
| Composer | composer.lock |
| go mod | go.sum |
หลักการสำคัญ:
เอกสารคือหนึ่งในองค์ประกอบสำคัญของซอฟต์แวร์ที่มักถูกละเลย มีคำกล่าวที่ว่า "If it's not documented, it doesn't exist" เครื่องมือสร้างเอกสารจึงมีบทบาทสำคัญในการผลักดันวัฒนธรรมการเขียนเอกสาร
Markdown คือภาษา Markup น้ำหนักเบา (Lightweight) ที่อ่านรู้เรื่องแม้เป็น plain text พัฒนาโดย John Gruber ปี 2004 ปัจจุบัน CommonMark เป็นมาตรฐานที่กำหนดไวยากรณ์ให้ชัดเจน และ GitHub Flavored Markdown (GFM) เป็น superset ที่เพิ่ม table, task list, strikethrough
ตัวอย่าง Markdown พื้นฐาน:
# หัวเรื่องหลัก (H1)
## หัวข้อรอง (H2)
**ตัวหนา** และ *ตัวเอน* และ ~~ขีดฆ่า~~
- รายการแจกแจง 1
- รายการแจกแจง 2
- รายการย่อย
1. ลำดับ 1
2. ลำดับ 2
> Blockquote สำหรับการอ้างอิง
`inline code` และ
```python
# code block
print("Hello")
| คอลัมน์ 1 | คอลัมน์ 2 |
|---|---|
| A | B |
### 4.7.2 Pandoc (แปลงเอกสารข้ามฟอร์แมต)
**Pandoc** คือ "Swiss Army Knife" สำหรับแปลงเอกสาร รองรับกว่า 40 format เช่น Markdown, HTML, LaTeX, DOCX, PDF, EPUB, reStructuredText, Org-mode
```bash
# Markdown → PDF (ต้องมี LaTeX)
pandoc document.md -o document.pdf
# Markdown → DOCX
pandoc document.md -o document.docx
# Markdown → HTML พร้อม TOC และ CSS
pandoc document.md -o document.html \
--toc \
--standalone \
--css=style.css \
--metadata title="เอกสารของฉัน"
# Markdown → EPUB สำหรับ e-book
pandoc chapter*.md -o book.epub \
--metadata title="หนังสือของฉัน" \
--metadata author="Moo"
# รวมหลายไฟล์ Markdown เป็น PDF ผ่าน LaTeX engine
pandoc chapter*.md -o book.pdf \
--pdf-engine=xelatex \
-V mainfont="Sarabun" \
-V CJKmainfont="Sarabun"
API Documentation ถูกสร้างโดยอัตโนมัติจาก Comment ในโค้ด ทำให้เอกสารกับโค้ดอยู่ใกล้กันเสมอ
/// commentsตัวอย่าง Docstring แบบต่าง ๆ:
# Python with Sphinx/Google style docstring
def calculate_gpa(grades: list[float], credits: list[int]) -> float:
"""คำนวณ GPA จากเกรดและหน่วยกิต
Args:
grades: รายการคะแนนเกรด (0.0 - 4.0) ในแต่ละวิชา
credits: จำนวนหน่วยกิตของแต่ละวิชา
Returns:
GPA ในช่วง 0.0 - 4.0
Raises:
ValueError: หากความยาวของ grades และ credits ไม่เท่ากัน
ZeroDivisionError: หากผลรวมหน่วยกิตเป็น 0
Example:
>>> calculate_gpa([4.0, 3.5, 3.0], [3, 3, 2])
3.5625
"""
if len(grades) != len(credits):
raise ValueError("grades and credits must have same length")
total_points = sum(g * c for g, c in zip(grades, credits))
total_credits = sum(credits)
return total_points / total_credits
/// คำนวณ GPA จากเกรดและหน่วยกิต
///
/// # Arguments
/// * `grades` - รายการคะแนนเกรด (0.0 - 4.0)
/// * `credits` - จำนวนหน่วยกิตของแต่ละวิชา
///
/// # Returns
/// GPA ในช่วง 0.0 - 4.0
///
/// # Examples
/// ```
/// let gpa = calculate_gpa(&[4.0, 3.5, 3.0], &[3, 3, 2]);
/// assert!((gpa - 3.5625).abs() < 1e-6);
/// ```
pub fn calculate_gpa(grades: &[f64], credits: &[u32]) -> f64 {
let total_points: f64 = grades.iter().zip(credits)
.map(|(g, c)| g * (*c as f64))
.sum();
let total_credits: f64 = credits.iter().sum::<u32>() as f64;
total_points / total_credits
}
คำสั่ง generate เอกสาร:
# Rust
cargo doc --open
# Go
godoc -http=:6060 # ดู doc ของ package ที่ติดตั้ง
# Python (Sphinx)
sphinx-quickstart docs
cd docs && make html
# TypeScript (TypeDoc)
npx typedoc --out docs src/index.ts
Static Site Generator (SSG) สร้าง HTML แบบ static จากไฟล์ Markdown เหมาะทำ Documentation Website, Blog, Landing Page
ตัวอย่าง mkdocs.yml:
site_name: My Project Documentation
site_url: https://docs.example.com
repo_url: https://github.com/example/myproject
theme:
name: material
palette:
- scheme: slate
primary: deep orange
accent: orange
features:
- navigation.tabs
- navigation.sections
- search.suggest
- content.code.copy
plugins:
- search
- mermaid2
markdown_extensions:
- admonition
- pymdownx.highlight
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
nav:
- Home: index.md
- Getting Started: getting-started.md
- User Guide:
- Installation: guide/install.md
- Configuration: guide/config.md
- API Reference: api.md
# สร้าง
mkdocs new my-docs
cd my-docs
# รัน dev server
mkdocs serve
# Build เป็น static HTML
mkdocs build
# Deploy ไปยัง GitHub Pages
mkdocs gh-deploy
Man Page (Manual Page) คือคู่มือมาตรฐานของ Unix/Linux แบ่งเป็น 8 section เช่น
ls, grep)open, read)printf)tty)passwd, fstab)ascii, regex)mount, fdisk)man ls # ดู man page ของ ls
man 2 open # ดู man ของ open system call (section 2)
man -k network # ค้นหา man page ที่มีคำว่า network
man -f printf # ดูทุก section ที่มี printf
apropos compression # ค้นหา man page ที่เกี่ยวกับ compression
flowchart TB
A[Commit โค้ด
git push]:::gruvblue --> B[CI Trigger]:::gruvaqua
B --> C[Build
สร้าง artifact]:::gruvgreen
C --> D[Test
Unit + Integration]:::gruvyellow
D --> E{ผ่านทั้งหมด?}:::gruvorange
E -->|ไม่ผ่าน| F[แจ้งเตือนผู้พัฒนา
Notify]:::gruvred
E -->|ผ่าน| G[Package
Docker Image]:::gruvpurple
G --> H[Deploy Staging]:::gruvaqua
H --> I{Manual Approval?}:::gruvorange
I -->|CD| J[Deploy Production
Manual]:::gruvgreen
I -->|CDE| K[Deploy Production
Auto]:::gruvgreen
classDef gruvblue fill:#458588,stroke:#83a598,color:#ebdbb2
classDef gruvaqua fill:#689d6a,stroke:#8ec07c,color:#ebdbb2
classDef gruvgreen fill:#98971a,stroke:#b8bb26,color:#282828
classDef gruvyellow fill:#d79921,stroke:#fabd2f,color:#282828
classDef gruvorange fill:#d65d0e,stroke:#fe8019,color:#ebdbb2
classDef gruvred fill:#cc241d,stroke:#fb4934,color:#ebdbb2
classDef gruvpurple fill:#b16286,stroke:#d3869b,color:#ebdbb2
DORA Metrics เป็นมาตรวัดประสิทธิภาพของทีม DevOps 4 ตัว:
โดยที่ คือจำนวน deployment ที่ล้มเหลวและ คือจำนวน deployment ทั้งหมดในช่วงเวลาหนึ่ง ทีมระดับ Elite มักมีค่านี้ต่ำกว่า 15%
Pipeline คือลำดับของ Job ที่รันเรียงกันใน CI/CD System โดยแบ่งเป็น Stage ต่าง ๆ เช่น Build, Test, Security Scan, Deploy แต่ละ Stage อาจมี Job หลายตัวที่รันพร้อมกันได้ (Parallel Jobs)
แนวคิดสำคัญ:
node_modules)GitHub Actions – Built-in กับ GitHub ใช้ YAML ที่ .github/workflows/
GitLab CI/CD – Built-in กับ GitLab ใช้ .gitlab-ci.yml
Jenkins – Self-hosted CI ที่เก่าแก่และยืดหยุ่นที่สุด ใช้ Jenkinsfile (Groovy)
CircleCI, Drone, Woodpecker CI – ทางเลือกอื่นแต่ละตัวมีจุดเด่นต่างกัน
ตัวอย่าง GitHub Actions workflow:
# .github/workflows/ci.yml - สำหรับ Python project
name: CI
# Trigger: เมื่อ push หรือเปิด PR บน main
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
name: Test on Python ${{ matrix.python-version }}
runs-on: ubuntu-latest
# ทดสอบบน Python หลาย version พร้อมกัน
strategy:
matrix:
python-version: ['3.11', '3.12']
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
- name: Set up Python
run: uv python install ${{ matrix.python-version }}
- name: Install dependencies
run: uv sync --all-extras --dev
- name: Lint with Ruff
run: uv run ruff check .
- name: Format check
run: uv run ruff format --check .
- name: Run tests with coverage
run: uv run pytest --cov=src --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
files: ./coverage.xml
build-docker:
name: Build Docker image
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository }}:latest
ghcr.io/${{ github.repository }}:${{ github.sha }}
ตัวอย่าง GitLab CI:
# .gitlab-ci.yml
stages:
- test
- build
- deploy
variables:
PYTHON_VERSION: "3.12"
cache:
paths:
- .venv/
test:
stage: test
image: python:${PYTHON_VERSION}-slim
before_script:
- pip install uv
- uv sync --dev
script:
- uv run pytest --cov=src
coverage: '/TOTAL.*\s+(\d+%)$/'
build:
stage: build
image: docker:24
services:
- docker:24-dind
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
only:
- main
deploy:
stage: deploy
script:
- echo "Deploy to production"
environment:
name: production
url: https://myapp.example.com
when: manual
only:
- main
Artifact คือผลผลิตของการ Build เช่น JAR, WAR, Executable, Docker Image, npm package, Wheel (.whl)
Artifact Repository เก็บและแจกจ่าย Artifact:
Release เป็นการแพคเกจ artifact พร้อม release notes และ semantic version
การทดสอบเป็นส่วนสำคัญที่ป้องกันไม่ให้ bug หลุดขึ้น production Test Pyramid เป็นหลักการจัดสัดส่วนของ test ที่แนะนำ
flowchart TB
E2E["E2E / UI Test
(น้อย 5-10%)
ช้า, แพง, บอบบาง"]:::gruvred
INT["Integration Test
(ปานกลาง 20-30%)
ทดสอบการทำงานร่วมของ component"]:::gruvyellow
UNIT["Unit Test
(มาก 60-70%)
เร็ว, เจาะจง, เชื่อถือได้"]:::gruvgreen
E2E --> INT
INT --> UNIT
classDef gruvgreen fill:#98971a,stroke:#b8bb26,color:#282828
classDef gruvyellow fill:#d79921,stroke:#fabd2f,color:#282828
classDef gruvred fill:#cc241d,stroke:#fb4934,color:#ebdbb2
Unit Test ทดสอบหน่วยเล็กที่สุด (function, method) แยกต่างหาก
ตัวอย่าง pytest:
# src/calculator.py
def add(a: int, b: int) -> int:
return a + b
def divide(a: float, b: float) -> float:
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
# tests/test_calculator.py
import pytest
from src.calculator import add, divide
# Unit Test ปกติ
def test_add_positive():
assert add(2, 3) == 5
def test_add_negative():
assert add(-1, -1) == -2
# Test หลายกรณีด้วย parametrize
@pytest.mark.parametrize("a,b,expected", [
(10, 2, 5.0),
(15, 3, 5.0),
(7, 2, 3.5),
(-10, 2, -5.0),
])
def test_divide(a, b, expected):
assert divide(a, b) == expected
# Test exception
def test_divide_by_zero():
with pytest.raises(ValueError, match="Cannot divide by zero"):
divide(10, 0)
# Fixture: ข้อมูลใช้ซ้ำ
@pytest.fixture
def sample_data():
return {"x": 10, "y": 20}
def test_with_fixture(sample_data):
assert add(sample_data["x"], sample_data["y"]) == 30
# รัน test
pytest # รันทั้งหมด
pytest tests/test_calculator.py # รันไฟล์เดียว
pytest -v # verbose
pytest -k "divide" # รันเฉพาะ test ที่มีคำว่า divide
pytest --cov=src # พร้อม coverage
pytest -x # หยุดที่ failure แรก
pytest --lf # รันเฉพาะที่ fail ครั้งที่แล้ว
ตัวอย่าง Vitest (TypeScript):
// src/math.ts
export const add = (a: number, b: number): number => a + b;
export const multiply = (a: number, b: number): number => a * b;
// src/math.test.ts
import { describe, it, expect } from 'vitest';
import { add, multiply } from './math';
describe('Math operations', () => {
it('adds two numbers correctly', () => {
expect(add(2, 3)).toBe(5);
expect(add(-1, 1)).toBe(0);
});
it('multiplies two numbers correctly', () => {
expect(multiply(4, 5)).toBe(20);
expect(multiply(0, 100)).toBe(0);
});
it.each([
[1, 2, 3],
[2, 3, 5],
[10, 20, 30],
])('add(%i, %i) = %i', (a, b, expected) => {
expect(add(a, b)).toBe(expected);
});
});
ตัวอย่าง Go test:
// calculator.go
package calculator
func Add(a, b int) int { return a + b }
// calculator_test.go
package calculator
import "testing"
func TestAdd(t *testing.T) {
tests := []struct {
name string
a, b int
expected int
}{
{"positive", 2, 3, 5},
{"negative", -1, -1, -2},
{"zero", 0, 5, 5},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Add(tt.a, tt.b); got != tt.expected {
t.Errorf("Add(%d, %d) = %d; want %d",
tt.a, tt.b, got, tt.expected)
}
})
}
}
// Benchmark
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
Add(1, 2)
}
}
go test ./... # รันทั้งหมด
go test -v # verbose
go test -run TestAdd # รันเฉพาะ test
go test -bench=. # รัน benchmark
go test -cover # coverage
Integration Test ทดสอบการทำงานร่วมกันของหลาย module
E2E Test ทดสอบระบบทั้งหมดจากมุมมองผู้ใช้
ตัวอย่าง Playwright:
// tests/login.spec.ts
import { test, expect } from '@playwright/test';
test.describe('Login Flow', () => {
test('successful login redirects to dashboard', async ({ page }) => {
// ไปหน้า login
await page.goto('https://app.example.com/login');
// กรอกฟอร์ม
await page.fill('input[name="email"]', 'user@example.com');
await page.fill('input[name="password"]', 'password123');
// คลิก submit
await page.click('button[type="submit"]');
// ตรวจว่า redirect ไป /dashboard
await expect(page).toHaveURL(/.*dashboard/);
// ตรวจว่ามีข้อความต้อนรับ
await expect(page.locator('h1')).toContainText('Welcome');
});
test('invalid credentials show error', async ({ page }) => {
await page.goto('https://app.example.com/login');
await page.fill('input[name="email"]', 'wrong@example.com');
await page.fill('input[name="password"]', 'wrongpass');
await page.click('button[type="submit"]');
await expect(page.locator('.error-message'))
.toContainText('Invalid credentials');
});
});
# รัน Playwright
npx playwright test
npx playwright test --ui # เปิด UI mode
npx playwright test --headed # เห็น browser
npx playwright show-report # ดูรายงาน
Code Coverage วัดว่า test ทดสอบโค้ดกี่เปอร์เซ็นต์ มีหลายระดับ:
โดยที่ คือจำนวนบรรทัดที่ถูกรัน และ คือจำนวนบรรทัดทั้งหมดในโค้ด แต่ทีมควรเน้นคุณภาพของ test มากกว่าการไล่ตามเปอร์เซ็นต์ Coverage 100% ไม่ได้หมายความว่าไม่มี bug
# Python
pytest --cov=src --cov-report=html --cov-report=term-missing
# เปิด htmlcov/index.html ในเบราว์เซอร์
# JavaScript/TypeScript
npx vitest run --coverage
# Go
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
# Rust
cargo install cargo-tarpaulin
cargo tarpaulin --out Html
Mutation Testing สร้าง "mutant" (การแก้โค้ดเล็กน้อยที่ควรทำให้ test fail) ถ้า test ยัง pass แสดงว่า test นั้นอ่อนแอ
Fuzz Testing ป้อน input แบบสุ่มเพื่อหา crash, hang, security vulnerability
// Go Fuzz Testing (Go 1.18+)
func FuzzReverse(f *testing.F) {
// Seed corpus
f.Add("hello")
f.Add("12345")
f.Fuzz(func(t *testing.T, s string) {
reversed := Reverse(s)
doubleReversed := Reverse(reversed)
if s != doubleReversed {
t.Errorf("Before: %q, After: %q", s, doubleReversed)
}
})
}
go test -fuzz=FuzzReverse -fuzztime=30s
curl – CLI คลาสสิกสำหรับ HTTP(S) และโปรโตคอลอื่น ๆ มีบน Linux/macOS/Windows
HTTPie – CLI ที่ทำให้ request HTTP ดูสวยและอ่านง่าย
xh – Alternative ของ HTTPie เขียนด้วย Rust เร็วกว่า
ตัวอย่างเรียก API ด้วย 3 tool:
# curl - GET
curl -i https://api.github.com/users/torvalds
# curl - POST JSON
curl -X POST https://httpbin.org/post \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TOKEN" \
-d '{"name": "Moo", "role": "lecturer"}'
# HTTPie - syntax ง่ายกว่ามาก
http GET https://api.github.com/users/torvalds
http POST https://httpbin.org/post \
name=Moo role=lecturer \
Authorization:"Bearer TOKEN"
# xh - เหมือน HTTPie แต่เร็วกว่า
xh POST httpbin.org/post name=Moo role=lecturer
# curl แบบสรุปผล timing
curl -w "@-" -o /dev/null -s https://example.com <<'EOF'
time_namelookup: %{time_namelookup}s
time_connect: %{time_connect}s
time_appconnect: %{time_appconnect}s
time_total: %{time_total}s
EOF
GUI API Client เหมาะสำหรับสำรวจ API ใหม่, จัดการ collection ของ request, ทำ automated test
.bru)Extension ของ IDE ช่วยให้ส่ง request ได้จากในไฟล์ .http โดยไม่ต้องออกจาก editor
### ตัวอย่างไฟล์ api.http สำหรับ REST Client (VS Code)
### GET user info
GET https://api.github.com/users/torvalds
Accept: application/json
### Create a post
POST https://httpbin.org/post HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}
{
"title": "Development Tools",
"author": "Moo",
"published": true
}
### Use response from previous request
@postId = {{createPost.response.body.$.id}}
### Get created post
GET https://api.example.com/posts/{{postId}}
OpenAPI Specification (OAS) เดิมเรียก Swagger คือมาตรฐานอธิบาย REST API ในรูป YAML/JSON สามารถ generate client SDK, documentation, mock server ได้อัตโนมัติ
ตัวอย่าง OpenAPI (ย่อ):
openapi: 3.0.3
info:
title: Student API
version: 1.0.0
description: API for managing students
servers:
- url: https://api.example.com/v1
paths:
/students:
get:
summary: List all students
parameters:
- name: limit
in: query
schema:
type: integer
default: 20
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Student'
post:
summary: Create a student
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Student'
responses:
'201':
description: Created
components:
schemas:
Student:
type: object
required: [id, name]
properties:
id:
type: string
format: uuid
name:
type: string
example: "สมชาย ใจดี"
gpa:
type: number
minimum: 0
maximum: 4
Tool ที่ใช้กับ OpenAPI:
โค้ดที่ทำงานได้ ≠ โค้ดที่ดี โค้ดที่ดีต้องอ่านง่าย บำรุงรักษาได้ ทีมอ่านตรงกัน Code Quality Tools ช่วยบังคับมาตรฐานเหล่านี้โดยอัตโนมัติ
Linter วิเคราะห์โค้ดแบบ static เพื่อหาปัญหาที่อาจเกิดขึ้น เช่น ตัวแปรที่ไม่ใช้, dead code, anti-pattern, bug ที่เห็นได้จากโครงสร้าง
| ภาษา | Linter แนะนำ | หมายเหตุ |
|---|---|---|
| Python | Ruff | เขียนด้วย Rust เร็วกว่า Pylint/Flake8 10-100x |
| JavaScript/TypeScript | ESLint, Biome | Biome เขียนด้วย Rust |
| Shell | ShellCheck | จับ bug bash/sh ได้มาก |
| Go | golangci-lint | รวม linter หลายตัว |
| Rust | clippy | มากับ rustup |
| C/C++ | clang-tidy, cppcheck | |
| YAML | yamllint | |
| Dockerfile | hadolint | |
| Kubernetes | kubeval, kube-linter |
ตัวอย่างไฟล์ config Ruff pyproject.toml:
[tool.ruff]
line-length = 100
target-version = "py312"
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"N", # pep8-naming
"UP", # pyupgrade
"B", # flake8-bugbear
"SIM", # flake8-simplify
"RUF", # Ruff-specific rules
]
ignore = ["E501"] # ไม่สน line too long (Formatter จัดการเอง)
[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = ["S101"] # allow assert ในไฟล์ test
# ตรวจอย่างเดียว
ruff check .
# แก้อัตโนมัติเท่าที่ทำได้
ruff check --fix .
# Watch mode
ruff check --watch .
ตัวอย่าง ShellCheck:
#!/bin/bash
# bad_script.sh - script ที่มี bug ทั่วไป
# bug: ไม่ quote variable ทำให้ path ที่มี space พัง
FILE=/tmp/my file.txt
cat $FILE
# bug: ใช้ $? แทน exit code ของคำสั่งก่อนหน้าทันที
grep "pattern" input.txt
if [ $? -eq 0 ]; then
echo "Found"
fi
shellcheck bad_script.sh
# จะรายงาน:
# SC2086: Double quote to prevent globbing and word splitting.
# SC2181: Check exit code directly with e.g. 'if mycmd;'
Formatter จัดรูปแบบโค้ดให้สวยงามและสม่ำเสมอ ข้อดีคือเลิกทะเลาะเรื่อง indent/bracket กันในทีม
# ตรวจว่า format ถูกต้อง (ใช้ใน CI)
ruff format --check .
gofmt -l .
rustfmt --check src/main.rs
prettier --check "src/**/*.{ts,tsx}"
# Format ทุกไฟล์ (in-place)
ruff format .
gofmt -w .
cargo fmt
prettier --write "src/**/*.{ts,tsx}"
Git Hook คือ script ที่ Git รันอัตโนมัติในจังหวะต่าง ๆ เช่น ก่อน commit, ก่อน push pre-commit framework เป็น tool ยอดนิยมที่ช่วยจัดการ hook หลายตัวรวมกัน
ตัวอย่าง .pre-commit-config.yaml:
# .pre-commit-config.yaml
repos:
# Hook ทั่วไปสำหรับจัดการไฟล์
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
args: ['--maxkb=500']
- id: check-merge-conflict
# Ruff: lint + format Python
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
# ShellCheck สำหรับ shell scripts
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.10.0.1
hooks:
- id: shellcheck
# Hadolint สำหรับ Dockerfile
- repo: https://github.com/hadolint/hadolint
rev: v2.13.0
hooks:
- id: hadolint
# Secret scanner: ไม่ให้ commit API key/password
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks
การใช้งาน:
# ติดตั้ง framework
pip install pre-commit
# หรือ uv tool install pre-commit
# ติดตั้ง hook ใน .git/hooks/
pre-commit install
# รันทุก hook กับทุกไฟล์ (ครั้งแรกเท่านั้น)
pre-commit run --all-files
# หลังจากนี้ hook จะรันอัตโนมัติทุกครั้งที่ git commit
วัฒนธรรมที่ดี: รวม pre-commit เข้ากับ CI (pre-commit run --all-files) เพื่อรับประกันว่าคนที่ bypass ด้วย --no-verify จะถูกจับได้ใน Pull Request
เพื่อความเข้าใจบริบท เครื่องมือพัฒนาซอฟต์แวร์มีวิวัฒนาการมายาวนานตั้งแต่ยุค Mainframe จนถึง AI-native ปัจจุบัน
flowchart TB
subgraph Era1["ยุค 1: Mainframe (1950-1970)"]
direction LR
A1[Assembler
1950s]:::gruvblue --> A2[FORTRAN Compiler
1957]:::gruvblue
A2 --> A3[ed editor
1969]:::gruvblue
end
subgraph Era2["ยุค 2: Unix Era (1970-1990)"]
direction LR
B1[ed, ex, vi
1976]:::gruvaqua --> B2[Make
1976]:::gruvaqua
B2 --> B3[SCCS/RCS
1972/1982]:::gruvaqua
B3 --> B4[GCC
1987]:::gruvaqua
end
subgraph Era3["ยุค 3: GUI IDE (1990-2005)"]
direction LR
C1[Visual Basic
1991]:::gruvgreen --> C2[Eclipse
2001]:::gruvgreen
C2 --> C3[IntelliJ IDEA
2001]:::gruvgreen
C3 --> C4[CVS/SVN
1990/2000]:::gruvgreen
end
subgraph Era4["ยุค 4: DVCS + Open Source (2005-2015)"]
direction LR
D1[Git
2005]:::gruvyellow --> D2[GitHub
2008]:::gruvyellow
D2 --> D3[Jenkins
2011]:::gruvyellow
D3 --> D4[Docker
2013]:::gruvyellow
end
subgraph Era5["ยุค 5: Cloud-Native + DevOps (2015-2022)"]
direction LR
E1[VS Code
2015]:::gruvorange --> E2[Kubernetes
2015]:::gruvorange
E2 --> E3[GitHub Actions
2019]:::gruvorange
E3 --> E4[LSP Protocol
2016]:::gruvorange
end
subgraph Era6["ยุค 6: AI-Native (2022-ปัจจุบัน)"]
direction LR
F1[GitHub Copilot
2022]:::gruvred --> F2[Cursor
2023]:::gruvred
F2 --> F3[Aider/Zed Agent
2024]:::gruvred
F3 --> F4[Claude Code/MCP
2024-2025]:::gruvpurple
end
Era1 --> Era2
Era2 --> Era3
Era3 --> Era4
Era4 --> Era5
Era5 --> Era6
classDef gruvblue fill:#458588,stroke:#83a598,color:#ebdbb2
classDef gruvaqua fill:#689d6a,stroke:#8ec07c,color:#ebdbb2
classDef gruvgreen fill:#98971a,stroke:#b8bb26,color:#282828
classDef gruvyellow fill:#d79921,stroke:#fabd2f,color:#282828
classDef gruvorange fill:#d65d0e,stroke:#fe8019,color:#ebdbb2
classDef gruvred fill:#cc241d,stroke:#fb4934,color:#ebdbb2
classDef gruvpurple fill:#b16286,stroke:#d3869b,color:#ebdbb2
ปัจจุบันเทรนด์ของ Development Tools เน้น 4 ทิศทาง: