Что такое принцип DRY в разработке?

Ответ

DRY (Don't Repeat Yourself) — это фундаментальный принцип разработки программного обеспечения, направленный на устранение дублирования логики и данных. В контексте Node.js это означает вынос повторяющегося кода в отдельные функции, модули, утилиты или мидлвари.

Пример нарушения DRY в Node.js приложении:

// Повторение валидации в разных маршрутах
app.post('/api/users', (req, res) => {
  if (!req.body.email || !req.body.email.includes('@')) {
    return res.status(400).json({ error: 'Invalid email' });
  }
  // Создание пользователя
});

app.put('/api/users/:id', (req, res) => {
  if (!req.body.email || !req.body.email.includes('@')) {
    return res.status(400).json({ error: 'Invalid email' });
  }
  // Обновление пользователя
});

Пример применения DRY:

// Вынос валидации в отдельную функцию-мидлварь
const validateEmail = (req, res, next) => {
  if (!req.body.email || !req.body.email.includes('@')) {
    return res.status(400).json({ error: 'Invalid email' });
  }
  next();
};

// Использование в маршрутах
app.post('/api/users', validateEmail, userController.create);
app.put('/api/users/:id', validateEmail, userController.update);

// Или создание утилитарного модуля
// utils/validators.js
export const isValidEmail = (email) => {
  return email && email.includes('@') && email.length > 5;
};

Преимущества DRY в Node.js:

  • Упрощение поддержки: Изменения вносятся в одном месте
  • Снижение ошибок: Устраняется риск рассинхронизации дублированной логики
  • Улучшение тестирования: Легче покрыть тестами централизованный код
  • Повышение читаемости: Код становится более декларативным

Когда стоит отступить от DRY:

  • Если абстракция усложнит понимание кода
  • Для одноразовой или тривиальной логики
  • Когда две похожие части кода могут эволюционировать в разных направлениях

Ответ 18+ 🔞

Э, слушай, а вот есть такая штука в программировании — DRY. Расшифровывается как «Don't Repeat Yourself», что в переводе на наш могучий означает «не повторяйся, ёпта». Суть проще пареной репы: если пишешь один и тот же кусок кода в двух местах, ты уже делаешь хуже себе и всем, кто будет это читать потом. Это как рассказывать одну и ту же байку в баре каждый вечер — всем надоест, да и сам запутаешься в деталях.

Вот смотри, какой пиздец бывает в Node.js, если этот принцип проигнорировать. Представь, пишешь ты API для пользователей.

// Допустим, у тебя есть роут для создания юзера
app.post('/api/users', (req, res) => {
  // И вот тут ты нагородил проверку почты
  if (!req.body.email || !req.body.email.includes('@')) {
    return res.status(400).json({ error: 'Invalid email' });
  }
  // ...код создания
});

// А потом тебе понадобился роут для обновления
app.put('/api/users/:id', (req, res) => {
  // И ты, бля, тупо копируешь ту же самую проверку!
  if (!req.body.email || !req.body.email.includes('@')) {
    return res.status(400).json({ error: 'Invalid email' });
  }
  // ...код обновления
});

Видишь? Одна и та же хуйня в двух местах. Доверия ебать ноль, что ты не забудешь её поправить в одном из мест, когда логика валидации усложнится. А она всегда усложняется, поверь. Придёт заказчик и скажет: «А добавьте ещё проверку на точку в домене». И ты побежишь, как угорелый, исправлять это в двадцати файлах. Терпения ноль ебать на такое.

А теперь смотри, как надо делать по-человечески, с применением DRY. Выносим эту логику в одно место.

Вариант раз: мидлварь. Идеально для Express.

// Создаём одну функцию-проверку
const validateEmail = (req, res, next) => {
  if (!req.body.email || !req.body.email.includes('@')) {
    return res.status(400).json({ error: 'Invalid email' });
  }
  // Если всё ок — идём дальше
  next();
};

// И просто подключаем её к нужным роутам
app.post('/api/users', validateEmail, userController.create);
app.put('/api/users/:id', validateEmail, userController.update);

Вариант два: утилитарная функция. Если логика нужна не только в мидлварях.

// utils/validators.js
export const isValidEmail = (email) => {
  // Всю свою гениальную проверку пишешь тут, в одном месте
  return email && email.includes('@') && email.length > 5;
};

// И используешь где угодно
import { isValidEmail } from './utils/validators.js';
if (!isValidEmail(req.body.email)) { ... }

В чём профит, спросишь? Да овердохуища преимуществ!

  • Поддержка: Захотел поменять валидацию — тыкнул в один файл, поправил и спишь спокойно. Не нужно бегать по всему проекту, как мартышлюшка.
  • Меньше ошибок: Нет риска, что в одном месте проверка работает, а в другом — хуй с горы. Всё централизовано.
  • Тесты: Проще покрыть тестами одну функцию, чем двадцать одинаковых if'ов, раскиданных по коду.
  • Читаемость: Код роутов становится чистым и понятным. Сразу видно: «а, тут валидация почты». Не нужно вникать в детали каждый раз.

Но, чувак, есть и подводные камни. Не нужно с фанатизмом впендюривать DRY куда попало.

Когда можно и нужно отступить:

  1. Если твоя «умная» абстракция станет пиздопроебибной и непонятной. Лучше простой повторяющийся код, чем хитрая жопа, которую никто не может понять.
  2. Если логика тривиальная и одноразовая. Не стоит городить отдельный модуль для конкатенации двух строк, которые встречаются один раз.
  3. Если сегодня два куска кода выглядят одинаково, но завтра они могут разойтись в развитии. Слепишь их в один — потом всё равно придётся раздирать. Подозрение ебать чувствую к таким ситуациям.

Короче, правило простое: если скопировал код — э, бошка, думай. Скорее всего, пора выносить. Но без фанатизма, а то сам от себя охуеешь, насколько всё можно усложнить.

Видео-ответы