قانون «یک سطح انتزاع در هر تابع» در 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