تمیز کردن 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.ema…
خواندن کامل ←