تمیز کردن Controller با تکنیک Extract Function 🧹
یکی از سادهترین و تاثیرگذارترین تکنیکهای refactor در وب، مخصوصاً توی backend، Extract Function هست: جدا کردن بخشهای منطقیِ یک تابع بزرگ به چند تابع کوچک، واضح و قابل تست. 👌
وقتی یک controller یا handler همهچیز را خودش انجام میدهد (validation، لاگ، query، mapping، ارسال response)، سریع تبدیل به کد شلوغ و سختقابلتغییر میشود؛ همون چیزی که تو Clean Code بهش میگن God Function یا Long Method.
بیایید یک مثال Node.js & Express ببینیم.
قبل از Extract Function (کد شلوغ)
این تابع "کار میکند"، اما:
• چندین سطح responsibility قاطی شده 🔥
• تست کردنش سختتر است
• توسعه بعدی (مثل اضافهکردن audit log یا event) ریسک bug دارد
بعد از Extract Function (کد تمیزتر)
الان هر تابع یک کار مشخص انجام میدهد:
•
•
•
چند مزیت مهم:
• تست واحد برای validation و منطقِ وجود کاربر مستقل از Express ✅
• خوانایی خیلی بهتر؛ controller مثل یک سناریو step-by-step شده 📖
• آماده برای reuse در endpoint یا سرویسهای دیگر ♻️
برای مطالعه بیشتر درباره Extract Function و refactoring:
refactoring.guru/extract-method
این نوع refactorهای کوچک، در طول زمان معماری backend و حتی frontend (مثلاً در handlerهای React/Next.js) را بسیار تمیزتر و قابلنگهداریتر میکند. امروز روی یک متد شلوغ امتحانش کنید و تفاوت را در خوانایی حس کنید. 🚀
🔖 #Web #وب #Frontend #Backend #refactoring #clean_code #nodejs #express #backend #extract_function #controller
👤 Developix
💎 Channel: @DevelopixWeb
یکی از سادهترین و تاثیرگذارترین تکنیکهای refactor در وب، مخصوصاً توی backend، Extract Function هست: جدا کردن بخشهای منطقیِ یک تابع بزرگ به چند تابع کوچک، واضح و قابل تست. 👌
وقتی یک controller یا handler همهچیز را خودش انجام میدهد (validation، لاگ، query، mapping، ارسال response)، سریع تبدیل به کد شلوغ و سختقابلتغییر میشود؛ همون چیزی که تو Clean Code بهش میگن God Function یا Long Method.
بیایید یک مثال Node.js & Express ببینیم.
قبل از Extract Function (کد شلوغ)
app.post('/api/users', async (req, res) => {
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).json({ message: 'Invalid data' });
}
console.log('Creating user', email);
const exists = await User.findOne({ email });
if (exists) {
return res.status(409).json({ message: 'User exists' });
}
const hash = await bcrypt.hash(password, 10);
const user = await User.create({ email, password: hash });
return res.status(201).json({
id: user.id,
email: user.email,
});
});این تابع "کار میکند"، اما:
• چندین سطح responsibility قاطی شده 🔥
• تست کردنش سختتر است
• توسعه بعدی (مثل اضافهکردن audit log یا event) ریسک bug دارد
بعد از Extract Function (کد تمیزتر)
function validateCreateUser(body) {
const { email, password } = body;
if (!email || !password) {
throw new Error('INVALID_DATA');
}
}
async function ensureUserNotExists(email) {
const exists = await User.findOne({ email });
if (exists) {
throw new Error('USER_EXISTS');
}
}
async function createUser(email, password) {
const hash = await bcrypt.hash(password, 10);
return User.create({ email, password: hash });
}
app.post('/api/users', async (req, res) => {
try {
validateCreateUser(req.body);
const { email, password } = req.body;
await ensureUserNotExists(email);
const user = await createUser(email, password);
return res.status(201).json({
id: user.id,
email: user.email,
});
} catch (err) {
if (err.message === 'INVALID_DATA') {
return res.status(400).json({ message: 'Invalid data' });
}
if (err.message === 'USER_EXISTS') {
return res.status(409).json({ message: 'User exists' });
}
return res.status(500).json({ message: 'Server error' });
}
});الان هر تابع یک کار مشخص انجام میدهد:
•
validateCreateUser → فقط validation•
ensureUserNotExists → فقط چک کردن business rule•
createUser → فقط ساختن userچند مزیت مهم:
• تست واحد برای validation و منطقِ وجود کاربر مستقل از Express ✅
• خوانایی خیلی بهتر؛ controller مثل یک سناریو step-by-step شده 📖
• آماده برای reuse در endpoint یا سرویسهای دیگر ♻️
برای مطالعه بیشتر درباره Extract Function و refactoring:
refactoring.guru/extract-method
این نوع refactorهای کوچک، در طول زمان معماری backend و حتی frontend (مثلاً در handlerهای React/Next.js) را بسیار تمیزتر و قابلنگهداریتر میکند. امروز روی یک متد شلوغ امتحانش کنید و تفاوت را در خوانایی حس کنید. 🚀
🔖 #Web #وب #Frontend #Backend #refactoring #clean_code #nodejs #express #backend #extract_function #controller
👤 Developix
💎 Channel: @DevelopixWeb
👍3❤1
در کد زیر سعی شده در یک route مربوط به Express دادهها از یک API خارجی گرفته شده و به صورت JSON برگردانده شود، اما یک اشتباه/Anti Pattern جدی در استفاده از async/await و مدیریت error وجود دارد که میتواند باعث رفتارهای غیرقابل پیشبینی روی سرور شود.
با دقت به این کد نگاه کنید:
چه چیزی باید در این کد اصلاح شود تا استفاده از async/await و مدیریت خطا به شکل درست و قابل پیشبینی انجام شود؟
🔖 #Web #وب #Frontend #Backend
👤 Developix
💎 Channel: @DevelopixWeb
با دقت به این کد نگاه کنید:
app.get('/posts', async (req, res) => {
try {
const response = fetch('https://example.com/api/posts');
response
.then(r => r.json())
.then(data => {
res.json({
success: true,
posts: data
});
})
.catch(err => {
console.error('Fetch error:', err);
res.status(500).json({ message: 'Internal error' });
});
} catch (err) {
console.error('Route error:', err);
res.status(500).json({ message: 'Route failed' });
}
});چه چیزی باید در این کد اصلاح شود تا استفاده از async/await و مدیریت خطا به شکل درست و قابل پیشبینی انجام شود؟
🔖 #Web #وب #Frontend #Backend
👤 Developix
💎 Channel: @DevelopixWeb
اسکرول صفحات روی موبایل اگه کلی event listener مثل
به طور پیشفرض، مرورگر مجبور میشه صبر کنه ببینه توی handler از
هر جا فقط میخوای event رو بخونی و قصد
مرجع: MDN - Passive event listeners
🔖 #Web #وب #Frontend #Backend #JavaScript #Performance #Frontend #Scroll #Event_Listener
👤 Developix
💎 Channel: @DevelopixWeb
touchstart و wheel داشته باشه، راحت لگ میزنه. یه ترفند ساده توی جاوااسکریپت کمک میکنه این مشکل خیلی کمتر بشه: استفاده از passive event listener ✅به طور پیشفرض، مرورگر مجبور میشه صبر کنه ببینه توی handler از
event.preventDefault() استفاده میکنی یا نه؛ همین مکث، اسکرول رو کند میکنه. اگه به مرورگر بگی این listener «passive» هست، دیگه صبر نمیکنه و اسکرول رو روان انجام میده. 🚀// همیشه قبل از استفاده، پشتیبانی رو چک کن
const passiveIfSupported = (() => {
let passive = false;
try {
const opts = Object.defineProperty({}, 'passive', {
get() {
passive = { passive: true };
}
});
window.addEventListener('test', null, opts);
} catch (e) {}
return passive;
})();
window.addEventListener('scroll', handleScroll, passiveIfSupported);
function handleScroll(e) {
// اینجا از e.preventDefault() استفاده نشه
}
هر جا فقط میخوای event رو بخونی و قصد
preventDefault() نداری (مثل analytics روی اسکرول یا لمس)، استفاده از گزینه { passive: true } هم UX رو بهتر میکنه هم performance رو. ✨مرجع: MDN - Passive event listeners
🔖 #Web #وب #Frontend #Backend #JavaScript #Performance #Frontend #Scroll #Event_Listener
👤 Developix
💎 Channel: @DevelopixWeb
👍3❤2
Forwarded from Developix Support
This media is not supported in your browser
VIEW IN TELEGRAM
🏆آفرهای جام جهانی ۲۰۲۶ هاستایران فعال شد!
با کمپین «ترکیب برنده سایتت»، زیرساخت سایتت رو برای روزهای پرترافیک آماده کن:
🔥 ۲۵٪ تخفیف روی پلنهای ۳ ماهه هاست اشتراکی ایران
⚡ ۵۰٪ تخفیف روی پلنهای یکماهه سرویس ابری در دیتاسنترهای تهران، مشهد و اهواز
🧠 مشاوره رایگان زیرساخت توسط کارشناسان هاستایران
فرصت استفاده از تخفیفها و ثبت فرم مشاوره محدود است.
📌 برای کپی کدهای تخفیف و ثبتنام در فرم مشاوره، روی لینک زیر کلیک کنید:
📌صفحه فرم مشاوره
📌تلگرام هاستایران
📌بله هاستایران
#هاست_ایران #سرور_ابری_هاست_ایران #هاست_اشتراکی #دیتاسنتر #مشاوره_زیرساخت #جام_جهانی2026
با کمپین «ترکیب برنده سایتت»، زیرساخت سایتت رو برای روزهای پرترافیک آماده کن:
🔥 ۲۵٪ تخفیف روی پلنهای ۳ ماهه هاست اشتراکی ایران
⚡ ۵۰٪ تخفیف روی پلنهای یکماهه سرویس ابری در دیتاسنترهای تهران، مشهد و اهواز
🧠 مشاوره رایگان زیرساخت توسط کارشناسان هاستایران
فرصت استفاده از تخفیفها و ثبت فرم مشاوره محدود است.
📌 برای کپی کدهای تخفیف و ثبتنام در فرم مشاوره، روی لینک زیر کلیک کنید:
📌صفحه فرم مشاوره
📌تلگرام هاستایران
📌بله هاستایران
#هاست_ایران #سرور_ابری_هاست_ایران #هاست_اشتراکی #دیتاسنتر #مشاوره_زیرساخت #جام_جهانی2026
در نمونهکد بالا هندل کردن خطا در Express بهصورت اشتباه انجام شده است؛ Middleware مربوط به خطا باید در انتهای زنجیره Routeها و سایر Middlewareها قرار بگیرد و امضای تابع آن هم باید چهار آرگومان
🔖 #Web #وب #Frontend #Backend
👤 Developix
💎 Channel: @DevelopixWeb
err، req، res و next را داشته باشد. با رعایت این الگو، خطاهای Async (مثلاً خطاهای Promise در درخواستهای پایگاهداده) بهدرستی لاگ و مدیریت شده و از ارسال پاسخهای ناقص یا Crash شدن ناگهانی سرور در محیط Production جلوگیری میشود.🔖 #Web #وب #Frontend #Backend
👤 Developix
💎 Channel: @DevelopixWeb
❤3
در نمونهکد بالا در روش اشتباه، در هر بار اجرا شدن
در روش صحیح با استفاده از یک متغیر سراسری و کشکردن
به این ترتیب، هم مصرف منابع بهشدت کاهش پیدا میکند، هم زمان پاسخگویی API و صفحات server-side بهتر میشود و در عین حال ریسک Memory Leak و اشباع شدن کانکشنهای دیتابیس پایین میآید.
🔖 #Web #وب #Frontend #Backend
👤 Developix
💎 Channel: @DevelopixWeb
getServerSideProps یک کانکشن جدید به دیتابیس ساخته میشود و هرگز بسته یا دوباره استفاده نمیشود؛ این کار روی سرور واقعی (مثلاً در Next.js زیر بار ترافیک بالا) باعث Connection Exhaustion، افت شدید کارایی و حتی کرش شدن سرویس میشود.در روش صحیح با استفاده از یک متغیر سراسری و کشکردن
MongoClient (یا هر Driver دیگری)، در محیط development جلوی ساخت کانکشنهای تکراری بعد از هر Hot-Reload گرفته شده و در محیط production هم تنها یک بار به دیتابیس متصل میشویم و همه درخواستها از همان کانکشن/Pool استفاده میکنند.به این ترتیب، هم مصرف منابع بهشدت کاهش پیدا میکند، هم زمان پاسخگویی API و صفحات server-side بهتر میشود و در عین حال ریسک Memory Leak و اشباع شدن کانکشنهای دیتابیس پایین میآید.
🔖 #Web #وب #Frontend #Backend
👤 Developix
💎 Channel: @DevelopixWeb
👍2
Forwarded from Developix Support
با Migration Boost هاستایران، برای مهاجرت به سرور ابری دوباره هزینه ترافیک نده! 🚀
با خرید اولین سرور ابری غیرساعتی از **هاستایران**، بسته ترافیک هدیه مهاجرت بهصورت خودکار برای سرویس شما فعال میشود:
✅ حداقل ۱۰۰ گیگابایت ترافیک هدیه مهاجرت
✅ افزایش حجم هدیه متناسب با ظرفیت دیسک اولیه
✅ ترافیک آپلود رایگان
✅ بدون محدودیت زمانی
سرور ابری هاستایران را راهاندازی کنید و بکاپها، فایلها و پایگاه داده خود را بدون دغدغه هزینههای پنهان ترافیک منتقل کنید.
👇 مشاهده پلنهای سرور ابری هاستایران
hostiran.club/Migration
hostiran.club/Migration
با خرید اولین سرور ابری غیرساعتی از **هاستایران**، بسته ترافیک هدیه مهاجرت بهصورت خودکار برای سرویس شما فعال میشود:
✅ حداقل ۱۰۰ گیگابایت ترافیک هدیه مهاجرت
✅ افزایش حجم هدیه متناسب با ظرفیت دیسک اولیه
✅ ترافیک آپلود رایگان
✅ بدون محدودیت زمانی
سرور ابری هاستایران را راهاندازی کنید و بکاپها، فایلها و پایگاه داده خود را بدون دغدغه هزینههای پنهان ترافیک منتقل کنید.
👇 مشاهده پلنهای سرور ابری هاستایران
hostiran.club/Migration
hostiran.club/Migration
❤1
🎨 تم روشن/تاریک فقط با CSS Variables
خیلی وقتها برای پیادهسازی dark mode سریع میشه از CSS Custom Properties (همون CSS variables) استفاده کرد و بدون دست زدن به کلی selector، رنگ کل UI رو عوض کرد. ✨
ایده اینه که همه رنگها رو روی
با این روش، اضافهکردن stateهای جدید (مثل high-contrast) هم فقط یعنی تعریف چند متغیر جدید، نه refactor بزرگ روی کل CSS. 🔧
مرجع بیشتر در MDN 👇
Using CSS custom properties - MDN
🔖 #Web #وب #Frontend #Backend #CSS #dark_mode #CSS_variables #frontend #web
👤 Developix
💎 Channel: @DevelopixWeb
خیلی وقتها برای پیادهسازی dark mode سریع میشه از CSS Custom Properties (همون CSS variables) استفاده کرد و بدون دست زدن به کلی selector، رنگ کل UI رو عوض کرد. ✨
ایده اینه که همه رنگها رو روی
:root تعریف بشه و بعد با اضافه کردن یک class به <html> یا <body>، تم عوض بشه. فقط یکبار style مینویسی و هرجا لازم بود از var(--color-name) استفاده میکنی. 🔁:root {
--bg: #ffffff;
--text: #111111;
}
html.dark {
--bg: #111827;
--text: #f9fafb;
}
body {
background-color: var(--bg);
color: var(--text);
}
// JavaScript
const html = document.documentElement;
const toggleTheme = () => {
html.classList.toggle('dark');
};
با این روش، اضافهکردن stateهای جدید (مثل high-contrast) هم فقط یعنی تعریف چند متغیر جدید، نه refactor بزرگ روی کل CSS. 🔧
مرجع بیشتر در MDN 👇
Using CSS custom properties - MDN
🔖 #Web #وب #Frontend #Backend #CSS #dark_mode #CSS_variables #frontend #web
👤 Developix
💎 Channel: @DevelopixWeb
👍3