قانون «یک سطح انتزاع در هر تابع» در JavaScript 🧠✨
یکی از نکات طلایی در Clean Code این است که هر تابع فقط با یک سطح انتزاع کار کند. یعنی یا درگیر جزئیات low-level باشد، یا فقط کارهای high-level را صدا بزند؛ نه هر دو را قاطی.
این قانون کمک میکند:
• خوانایی کد بالا برود 👀
• Refactor کردن سادهتر شود 🔧
• تستنویسی راحتتر شود ✅
🍂 یک مثال از کد شلوغ در Node.js / Express
این تابع هم validation انجام میدهد، هم کار دیتابیس، هم جزئیات hash، هم پاسخ HTTP. سطحهای انتزاع قاطی شدهاند.
🌱 Refactor با یک سطح انتزاع در هر تابع
حالا:
• تابع
• تابع
• route handler فقط orchestration انجام میدهد ✅
این جداسازی باعث میشود بعداً راحتتر TypeScript اضافه کنید، Unit Test بنویسید، یا منطق ساخت کاربر را در سرویس دیگری (مثلاً در یک worker) استفاده کنید.
منابع برای مطالعه بیشتر:
• Refactoring.Guru
• MDN – Learn JS
قدمبهقدم همین الگو را روی قسمتهای شلوغ پروژههای Node.js / React / Next.js خود پیاده کنید؛ هر بار که یک تابع را به یک سطح انتزاع محدود میکنید، کدتان قابلاعتمادتر و نگهداریپذیرتر میشود 🚀
🔖 #Javascript #JS #جاوااسکریپت #Clean_Code #JavaScript #Node_js #Express #Refactoring #Best_Practices
👤 Developix
💎 Channel: @DevelopixJavascript
یکی از نکات طلایی در Clean Code این است که هر تابع فقط با یک سطح انتزاع کار کند. یعنی یا درگیر جزئیات low-level باشد، یا فقط کارهای high-level را صدا بزند؛ نه هر دو را قاطی.
این قانون کمک میکند:
• خوانایی کد بالا برود 👀
• Refactor کردن سادهتر شود 🔧
• تستنویسی راحتتر شود ✅
🍂 یک مثال از کد شلوغ در Node.js / Express
app.post('/api/users', async (req, res) => {
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).json({ message: 'Invalid data' });
}
if (!email.includes('@')) {
return res.status(400).json({ message: 'Invalid email' });
}
const exists = await db.collection('users').findOne({ email });
if (exists) {
return res.status(409).json({ message: 'Already exists' });
}
const hash = await bcrypt.hash(password, 10);
const user = {
email,
password: hash,
createdAt: new Date()
};
await db.collection('users').insertOne(user);
res.status(201).json({ id: user._id, email: user.email });
});این تابع هم validation انجام میدهد، هم کار دیتابیس، هم جزئیات hash، هم پاسخ HTTP. سطحهای انتزاع قاطی شدهاند.
🌱 Refactor با یک سطح انتزاع در هر تابع
const validateUserPayload = (body) => {
const { email, password } = body;
if (!email || !password) return 'Invalid data';
if (!email.includes('@')) return 'Invalid email';
return null;
};
const createUser = async ({ email, password }, db, hasher) => {
const exists = await db.collection('users').findOne({ email });
if (exists) return { error: 'Already exists' };
const passwordHash = await hasher(password);
const user = {
email,
password: passwordHash,
createdAt: new Date()
};
const result = await db.collection('users').insertOne(user);
return { id: result.insertedId, email: user.email };
};
app.post('/api/users', async (req, res) => {
const validationError = validateUserPayload(req.body);
if (validationError) {
return res.status(400).json({ message: validationError });
}
const result = await createUser(
req.body,
db,
(password) => bcrypt.hash(password, 10)
);
if (result.error) {
return res.status(409).json({ message: result.error });
}
res.status(201).json(result);
});حالا:
• تابع
validateUserPayload فقط validation است ✅• تابع
createUser فقط منطق ساخت کاربر را دارد ✅• route handler فقط orchestration انجام میدهد ✅
این جداسازی باعث میشود بعداً راحتتر TypeScript اضافه کنید، Unit Test بنویسید، یا منطق ساخت کاربر را در سرویس دیگری (مثلاً در یک worker) استفاده کنید.
منابع برای مطالعه بیشتر:
• Refactoring.Guru
• MDN – Learn JS
قدمبهقدم همین الگو را روی قسمتهای شلوغ پروژههای Node.js / React / Next.js خود پیاده کنید؛ هر بار که یک تابع را به یک سطح انتزاع محدود میکنید، کدتان قابلاعتمادتر و نگهداریپذیرتر میشود 🚀
🔖 #Javascript #JS #جاوااسکریپت #Clean_Code #JavaScript #Node_js #Express #Refactoring #Best_Practices
👤 Developix
💎 Channel: @DevelopixJavascript
👍4❤3👎3
اصل مهمی در Clean Code این است که هر تابع فقط یک وظیفهٔ واضح داشته باشد ✨
وقتی یک تابع چند کار مختلف انجام میدهد:
- تستنویسی سخت میشود
- احتمال باگ بالا میرود
- خواندن و تغییر کد زمانبر میشود
به این ایده در Design Principleها میگویند: Single Responsibility Principle (SRP).
نمونهٔ یک تابع شلوغ در Node.js 👇
این تابع هم اعتبارسنجی میکند، هم دیتابیس میزند، هم ایمیل میفرستد؛ یعنی چند مسئولیت در یک جا.
حالا همان منطق را با توابع کوچکتر تمیزتر میکنیم 🧼
حالا:
- تست کردن
- تغییر قانون پسورد، فقط در یک تابع انجام میشود ✅
- خطاها واضحتر و قابل مدیریتتر هستند ✅
برای کدهای React، Express، Next.js و هر محیط JavaScript/TypeScript دیگر همین ایده جواب میدهد: توابع کوچک، با نام خوب و یک کار مشخص.
برای مطالعهٔ بیشتر میتوان از Refactoring.Guru و MDN کمک گرفت.
قدمهای کوچک refactor کردن همین امروز روی یکی از فانکشنهای شلوغ پروژه، بعد از چند هفته تاثیر زیادی در خوانایی و کیفیت کد میگذارد 🚀
🔖 #Javascript #JS #جاوااسکریپت #JavaScript #Clean_Code #Node_js #Refactoring #SRP
👤 Developix
💎 Channel: @DevelopixJavascript
وقتی یک تابع چند کار مختلف انجام میدهد:
- تستنویسی سخت میشود
- احتمال باگ بالا میرود
- خواندن و تغییر کد زمانبر میشود
به این ایده در Design Principleها میگویند: Single Responsibility Principle (SRP).
نمونهٔ یک تابع شلوغ در Node.js 👇
const registerUser = async (req, res) => {
const { email, password } = req.body;
// validate
if (!email || !password || password.length < 8) {
return res.status(400).json({ message: 'Invalid data' });
}
// check duplicate
const existing = await User.findOne({ email });
if (existing) {
return res.status(409).json({ message: 'Email exists' });
}
// hash password
const bcrypt = await import('bcrypt');
const hashed = await bcrypt.hash(password, 10);
// save user
const user = await User.create({ email, password: hashed });
// send welcome email
await sendWelcomeEmail(email);
return res.status(201).json({ id: user.id, email: user.email });
};این تابع هم اعتبارسنجی میکند، هم دیتابیس میزند، هم ایمیل میفرستد؛ یعنی چند مسئولیت در یک جا.
حالا همان منطق را با توابع کوچکتر تمیزتر میکنیم 🧼
const validateRegisterInput = ({ email, password }) => {
if (!email || !password) return 'Email and password are required';
if (password.length < 8) return 'Password too short';
return null;
};
const ensureEmailUnique = async (email) => {
const existing = await User.findOne({ email });
if (existing) throw new Error('EMAIL_TAKEN');
};
const createUser = async ({ email, password }) => {
const bcrypt = await import('bcrypt');
const hashed = await bcrypt.hash(password, 10);
return User.create({ email, password: hashed });
};
const registerUser = async (req, res) => {
const { email, password } = req.body;
const error = validateRegisterInput({ email, password });
if (error) return res.status(400).json({ message: error });
try {
await ensureEmailUnique(email);
const user = await createUser({ email, password });
await sendWelcomeEmail(email);
return res.status(201).json({ id: user.id, email: user.email });
} catch (err) {
if (err.message === 'EMAIL_TAKEN') {
return res.status(409).json({ message: 'Email exists' });
}
return res.status(500).json({ message: 'Server error' });
}
};حالا:
- تست کردن
validateRegisterInput و createUser مستقل و ساده است ✅- تغییر قانون پسورد، فقط در یک تابع انجام میشود ✅
- خطاها واضحتر و قابل مدیریتتر هستند ✅
برای کدهای React، Express، Next.js و هر محیط JavaScript/TypeScript دیگر همین ایده جواب میدهد: توابع کوچک، با نام خوب و یک کار مشخص.
برای مطالعهٔ بیشتر میتوان از Refactoring.Guru و MDN کمک گرفت.
قدمهای کوچک refactor کردن همین امروز روی یکی از فانکشنهای شلوغ پروژه، بعد از چند هفته تاثیر زیادی در خوانایی و کیفیت کد میگذارد 🚀
🔖 #Javascript #JS #جاوااسکریپت #JavaScript #Clean_Code #Node_js #Refactoring #SRP
👤 Developix
💎 Channel: @DevelopixJavascript
👍7❤1
یکی از سادهترین تکنیکهای Refactoring برای تمیزتر شدن کد جاوااسکریپت، استفاده از الگوی Early Return است ✨
در این الگو بهجای اینکه یک تابع را با if تو در تو و بلاکهای بزرگ بپیچیم، شرطهای نامعتبر را زودتر برمیگردانیم و مسیر «عادی» تابع را خوانا و سرراست نگه میکنیم.
نمونه کد شلوغ بدون Early Return 👇
خواندن این تابع سخت است؛ منطق اصلی بین ifهای تودرتو گم شده.
همان منطق با Early Return 🧼
حالا:
• تمام شرطهای نامعتبر بالا جمع شدهاند و سریع تابع را ترک میکنند ✅
• «مسیر خوشحال» وسط تابع مثل یک داستان خطی و قابلخواندن است ✅
• دیباگ و لاگگرفتن سادهتر شده است ✅
نکته کاربردی در پروژههای React / Node.js
در هندلرهای API و کنترلرهای Express هم همین الگو کمک زیادی میکند تا از callback hell جدید یعنی if hell فرار شود:
در مستندات MDN درباره return و جریان کنترل توضیحات بیشتری آمده که مطالعهاش دید خوبی میدهد.
هرجا تابعی دیدۀ میشود که تو در تو و سختخوان است، یک بار با Early Return بازنویسیاش، هم برای خودتان هم برای تیم، خوانایی کد را چند درجه بالا میبرد 🚀
🔖 #Javascript #JS #جاوااسکریپت #JavaScript #Clean_Code #Refactoring #Early_Return #Node_js #Express #Readability
👤 Developix
💎 Channel: @DevelopixJavascript
در این الگو بهجای اینکه یک تابع را با if تو در تو و بلاکهای بزرگ بپیچیم، شرطهای نامعتبر را زودتر برمیگردانیم و مسیر «عادی» تابع را خوانا و سرراست نگه میکنیم.
نمونه کد شلوغ بدون Early Return 👇
function createOrder(user, items) {
if (user) {
if (user.isActive) {
if (Array.isArray(items) && items.length > 0) {
const total = items.reduce((sum, it) => sum + it.price, 0);
if (total > 0) {
return { userId: user.id, total, status: "CREATED" };
} else {
throw new Error("Total must be positive");
}
} else {
throw new Error("Items required");
}
} else {
throw new Error("User not active");
}
} else {
throw new Error("User required");
}
}
خواندن این تابع سخت است؛ منطق اصلی بین ifهای تودرتو گم شده.
همان منطق با Early Return 🧼
function createOrder(user, items) {
if (!user) {
throw new Error("User required");
}
if (!user.isActive) {
throw new Error("User not active");
}
if (!Array.isArray(items) || items.length === 0) {
throw new Error("Items required");
}
const total = items.reduce((sum, it) => sum + it.price, 0);
if (total <= 0) {
throw new Error("Total must be positive");
}
return { userId: user.id, total, status: "CREATED" };
}
حالا:
• تمام شرطهای نامعتبر بالا جمع شدهاند و سریع تابع را ترک میکنند ✅
• «مسیر خوشحال» وسط تابع مثل یک داستان خطی و قابلخواندن است ✅
• دیباگ و لاگگرفتن سادهتر شده است ✅
نکته کاربردی در پروژههای React / Node.js
در هندلرهای API و کنترلرهای Express هم همین الگو کمک زیادی میکند تا از callback hell جدید یعنی if hell فرار شود:
export const handler = async (req, res) => {
const { user } = req;
if (!user) {
return res.status(401).json({ message: "Unauthorized" });
}
if (!user.isActive) {
return res.status(403).json({ message: "Inactive user" });
}
const data = await loadDashboardData(user.id);
return res.json(data);
};
در مستندات MDN درباره return و جریان کنترل توضیحات بیشتری آمده که مطالعهاش دید خوبی میدهد.
هرجا تابعی دیدۀ میشود که تو در تو و سختخوان است، یک بار با Early Return بازنویسیاش، هم برای خودتان هم برای تیم، خوانایی کد را چند درجه بالا میبرد 🚀
🔖 #Javascript #JS #جاوااسکریپت #JavaScript #Clean_Code #Refactoring #Early_Return #Node_js #Express #Readability
👤 Developix
💎 Channel: @DevelopixJavascript
👍6❤2