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

Ответ

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

Ключевая идея:

Каждая часть знания в системе должна иметь единственное, однозначное и авторитетное представление.

Это относится не только к дублированию кода, но и к дублированию логики, данных, конфигурации и документации.

Пример нарушения и исправления DRY:

Плохо (повторение логики валидации):

func CreateUser(name string, email string) error {
    // Блок валидации
    if len(name) < 3 {
        return errors.New("name is too short")
    }
    if !strings.Contains(email, "@") {
        return errors.New("invalid email format")
    }
    // ... логика создания пользователя
    return nil
}

func UpdateUser(name string, email string) error {
    // Такой же блок валидации
    if len(name) < 3 {
        return errors.New("name is too short")
    }
    if !strings.Contains(email, "@") {
        return errors.New("invalid email format")
    }
    // ... логика обновления пользователя
    return nil
}

Хорошо (логика вынесена в отдельную функцию):

func validateUserData(name string, email string) error {
    if len(name) < 3 {
        return errors.New("name is too short")
    }
    if !strings.Contains(email, "@") {
        return errors.New("invalid email format")
    }
    return nil
}

func CreateUser(name string, email string) error {
    if err := validateUserData(name, email); err != nil {
        return err
    }
    // ... логика создания пользователя
    return nil
}

func UpdateUser(name string, email string) error {
    if err := validateUserData(name, email); err != nil {
        return err
    }
    // ... логика обновления пользователя
    return nil
}

Преимущества следования DRY:

  • Поддерживаемость: Изменения в логике нужно вносить только в одном месте.
  • Надежность: Снижается риск ошибок, когда при изменении логики забывают обновить одну из ее копий.
  • Читаемость: Код становится чище и понятнее, так как намерение выражено в одном месте.

Когда применять с осторожностью? Слепое следование DRY может привести к созданию плохих или преждевременных абстракций. Иногда небольшое дублирование кода (принцип WET — Write Everything Twice) предпочтительнее, чем сложная и запутанная абстракция, которая связывает части системы, не имеющие на самом деле ничего общего.

Ответ 18+ 🔞

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

Смысл в чём, сука? Каждая единица знания — будь то код, логика, конфиг или даже описание в документации — должна жить в одном-единственном, чётко определённом месте. Один раз написал, один раз описал — и на него все ссылаются. А не так, чтобы раскидать эту хуйню по всему проекту, как говно по тарелкам.

Вот смотри, как бывает у криворуких распиздяев. Берут и тупо копируют один и тот же кусок кода:

func CreateUser(name string, email string) error {
    // Блок валидации
    if len(name) < 3 {
        return errors.New("name is too short")
    }
    if !strings.Contains(email, "@") {
        return errors.New("invalid email format")
    }
    // ... логика создания пользователя
    return nil
}

func UpdateUser(name string, email string) error {
    // Такой же блок валидации
    if len(name) < 3 {
        return errors.New("name is too short")
    }
    if !strings.Contains(email, "@") {
        return errors.New("invalid email format")
    }
    // ... логика обновления пользователя
    return nil
}

Видишь? Одна и та же валидация, как мартышлюшка, сидит в двух местах. И что будет, если заказчик прибежит и заорёт: «Хочу, чтобы имя было минимум 5 символов, а не 3, блядь!»? Правильно, придётся бегать и менять эту цифру в двух (а на деле-то в десяти!) местах. И обязательно где-то забудешь, и всё, пиздец, бага на продакшене. На тебе, пользователь, «Vasya» — короткое имя, ебать твою мать.

А теперь смотри, как делают адекватные люди:

func validateUserData(name string, email string) error {
    if len(name) < 3 {
        return errors.New("name is too short")
    }
    if !strings.Contains(email, "@") {
        return errors.New("invalid email format")
    }
    return nil
}

func CreateUser(name string, email string) error {
    if err := validateUserData(name, email); err != nil {
        return err
    }
    // ... логика создания пользователя
    return nil
}

func UpdateUser(name string, email string) error {
    if err := validateUserData(name, email); err != nil {
        return err
    }
    // ... логика обновления пользователя
    return nil
}

Вот! Всё, блядь, логику валидации вынесли в одну функцию. Теперь если что менять — тык пальцем в одно место, и вся система обновится. Красота, да? Это и есть DRY в действии, ебать мои старые костыли.

Чем это, сука, выгодно?

  • Поддерживать проще: Не нужно искать по всему коду, где ты эту хуйню размножил. Поменял в одном месте — и волна изменений пошла.
  • Надёжнее: Шанс, что ты где-то просрёшь нужное изменение, стремится к нулю. Ну, почти.
  • Читать приятнее: Код чистый, как слеза младенца. Не засран повторяющейся хуетой.

Но есть нюанс, ёпта! Не надо сходить с ума и пытаться всё и везде абстрагировать. Иногда два похожих куска кода — это просто два похожих куска кода, а не одна и та же сущность. Если начать их насильно склеивать в какую-то пиздопроебибну абстракцию с кучей условий и флагов, получится только хуже. Иногда лучше написать что-то дважды (это называется WET — Write Everything Twice), посмотреть, как оно живёт, и уже потом, если реально видишь общую суть, — абстрагировать. А то так можно доверия ебать ноль ко всему коду получить.

Короче, применяй DRY с умом, а не как дурак.