Skip to content

Clean Code

Meaningful Names

การตั้งชื่อที่มีความหมายชัดเจน ทำให้โค้ดอ่านง่ายและเข้าใจได้ทันที

javascript
// Bad
const d = new Date(); 
const n = "John";
const arr = [1, 2, 3];

// Good
const currentDate = new Date();
const userName = "John";
const numberList = [1, 2, 3];

Single Responsibility

ฟังก์ชันหรือคลาสควรมีหน้าที่เดียวที่ชัดเจน

javascript
// Bad
function handleUser(user) {
	validateUser(user);
	saveToDatabase(user);
	sendEmail(user);
}

// Good
function validateUser(user) { /* ... */ }
function saveUser(user) { /* ... */ }
function notifyUser(user) { /* ... */ }

function handleNewUser(user) {
	validateUser(user);
	saveUser(user);
	notifyUser(user);
}

DRY (Don't Repeat Yourself)

หลีกเลี่ยงการเขียนโค้ดซ้ำซ้อน นำโค้ดที่ใช้บ่อยมาทำเป็นฟังก์ชัน

javascript
// Bad
function validateEmail(email) {
	const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
	return regex.test(email);
}

function validateUserEmail(user) {
	const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
	return regex.test(user.email);
}

// Good
function isValidEmail(email) {
	const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
	return regex.test(email);
}

function validateEmail(email) {
	return isValidEmail(email);
}

function validateUserEmail(user) {
	return isValidEmail(user.email);
}

Small Functions

ฟังก์ชันควรมีขนาดเล็ก ทำหน้าที่เดียว และมีความชัดเจน

javascript
// Bad
function processOrder(order) {
	let total = 0;
	for (const item of order.items) {
		total += item.price * item.quantity;
	}
	const tax = total * 0.1;
	total += tax;
	order.total = total;
	
	const db = connectToDatabase();
	db.save(order);
	
	const email = createEmailTemplate(order);
	sendEmail(order.email, email);
}

// Good
function calculateSubtotal(items) {
	return items.reduce((total, item) => total + (item.price * item.quantity), 0);
}

function calculateTax(amount) {
	return amount * 0.1;
}

function calculateTotal(subtotal, tax) {
	return subtotal + tax;
}

function processOrder(order) {
	const subtotal = calculateSubtotal(order.items);
	const tax = calculateTax(subtotal);
	order.total = calculateTotal(subtotal, tax);
	
	saveOrder(order);
	notifyCustomer(order);
}

Meaningful Comments

เขียน Comment เมื่อจำเป็น อธิบายเหตุผลว่าทำไม ไม่ใช่อธิบายว่าทำอะไร

javascript
// Bad
// Loop through users
for (const user of users) {
	// Check if admin
	if (user.role === 'admin') {
		// Do something
	}
}

// Good
// Skip deleted users to prevent ghost data in reports
for (const user of activeUsers) {
	if (user.role === 'admin') {
		generateAdminReport(user);
	}
}

Error Handling

จัดการ Error อย่างเหมาะสม ใช้ Try-Catch เมื่อจำเป็น

javascript
// Bad
function divide(a, b) {
	return a / b;
}

// Good
function divide(a, b) {
	if (b === 0) {
		throw new Error('Division by zero is not allowed');
	}
	return a / b;
}

// Better
function divideNumbers(a, b) {
	try {
		return divide(a, b);
	} catch (error) {
		logger.error('Division failed:', error);
		return null;
	}
}

Consistent Formatting

ใช้รูปแบบการเขียนโค้ดที่สม่ำเสมอ ใช้ Code Formatter ช่วย

javascript
// Bad
function  calculateTotal (items){
	let total=0
	for(const item of items){
		total+=item.price*item.quantity
	}
return total
}

// Good
function calculateTotal(items) {
	let total = 0;
	
	for (const item of items) {
		total += item.price * item.quantity;
	}
	
	return total;
}

Avoid Magic Numbers

หลีกเลี่ยงการใช้ตัวเลขโดยตรงในโค้ด ให้กำหนดเป็นค่าคงที่ที่มีความหมาย

javascript
// Bad
if (user.age >= 18) {
	allowAccess();
}
setTimeout(checkStatus, 86400000);

// Good
const LEGAL_AGE = 18;
const ONE_DAY_IN_MS = 24 * 60 * 60 * 1000;

if (user.age >= LEGAL_AGE) {
	allowAccess();
}
setTimeout(checkStatus, ONE_DAY_IN_MS);

Use Strong Types

ใช้ Type System ช่วยป้องกันข้อผิดพลาด

typescript
// Bad
function processUser(user) {
	if (user.age > 18) {
		// ...
	}
}

// Good
interface User {
	name: string;
	age: number;
	email: string;
}

function processUser(user: User) {
	if (user.age > LEGAL_AGE) {
		// ...
	}
}

Dependency Injection

ส่งผ่านการพึ่งพาจากภายนอกเข้ามา แทนการสร้างภายในฟังก์ชัน

javascript
// Bad
class UserService {
	constructor() {
		this.database = new Database();
		this.logger = new Logger();
	}
}

// Good
class UserService {
	constructor(database, logger) {
		this.database = database;
		this.logger = logger;
	}
}

const database = new Database();
const logger = new Logger();
const userService = new UserService(database, logger);

Released under the MIT License