| کانال توسعه‌دهندگان وب |
3.09K subscribers
57 photos
2 videos
53 links
⭕️ کانال توسعه‌دهندگان وب دولوپیکس

💠 دولوپیکس | جامعه توسعه‌دهندگان ایرانی

💎 @Developix
🚀 Developix.ir

📌 پشتیبانی و تبلیغات:
@DevelopixSupport
Download Telegram
اصل تک‌مسئولیتی (Single Responsibility Principle) یعنی هر ماژول یا کامپوننت فقط یک دلیل برای تغییر داشته باشد. در پروژه‌های وب پیچیده، رعایت SRP باعث می‌شود کد قابل تست‌تر، قابل تغییرتر و خواناتر شود. تجربهٔ عملی: وقتی کد را به واحدهای کوچکتر با مسئولیت مشخص تقسیم می‌کنید، باگ‌ها راحت‌تر پیدا و ویژگی‌های جدید سریع‌تر اضافه می‌شوند.

مثال فرانت‌اند (React)
کامپوننت بد: هم دیتا می‌گیرد، هم وضعیت مدیریت می‌کند، هم رندر می‌کند.
function Dashboard(){
const [data,setData]=useState(null);
useEffect(()=>{fetch('/api/items').then(r=>r.json()).then(setData)},[]);
function save(item){fetch('/api/items', {method:'POST', body:JSON.stringify(item)})}
return <div>{data?.map(i=><div key={i.id}>{i.name}</div>)}</div>
}

تقسیم به مسئولیت‌ها: یک useFetch hook و یک Presentational کامپوننت:
function useFetch(url){
const [data,setData]=useState(null);
useEffect(()=>{fetch(url).then(r=>r.json()).then(setData)},[url]);
return data;
}
function DashboardView({data}){ return <div>{data?.map(i=><div key={i.id}>{i.name}</div>)}</div> }
function Dashboard(){ const data=useFetch('/api/items'); return <DashboardView data={data}/> }


این تقسیم باعث می‌شود تست hook و view جداگانه امکان‌پذیر و تغییر منطق دریافت داده بدون لمس رندر انجام شود.

مثال بک‌اند (Node.js / Express)
به‌جای نوشتن منطق اعتبارسنجی، منطق تجاری و دسترسی به دیتابیس در یک فایل کنترلر، آنها را جدا کنید:
// controller
async function createItem(req,res){ const item=await itemService.create(req.body); res.json(item) }
// service
async function create(data){ validate(data); return repository.insert(data) }


این ساختار واحدها را قابل تست می‌کند و تغییر در لایهٔ ذخیره‌سازی تأثیر کمتری روی کنترلر دارد.

برای مرجع بیشتر منابعی مثل Refactoring.Guru و کتاب "Clean Code" پیشنهاد می‌شوند. نکتهٔ عملی: اگر نوشتن تست برای یک تابع سخت است، احتمالاً آن تابع بیش از یک مسئولیت دارد — آن را شکسته و ساده کنید.

🔖 #Web #وب #Frontend #Backend #clean_code #SRP #React #Node.js #refactoring #architecture #best_practices

👤 Developix

💎 Channel: @DevelopixWeb
👍71👎1🔥1
‏تمیز کردن Controller با تکنیک Extract Function 🧹

یکی از ساده‌ترین و تاثیرگذارترین تکنیک‌های 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 &rarr; فقط validation
ensureUserNotExists &rarr; فقط چک کردن business rule
createUser &rarr; فقط ساختن 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
👍31