Какие знаешь принципы программирования

Ответ

SOLID — основные принципы ООП:

  1. Single Responsibility — класс должен решать только одну задачу.
  2. Open-Closed — классы должны быть открыты для расширения, но закрыты для изменений.
  3. Liskov Substitution — подклассы должны заменять родительские классы без ошибок.
  4. Interface Segregation — лучше много узких интерфейсов, чем один универсальный.
  5. Dependency Inversion — зависимости должны строиться на абстракциях, а не на конкретных классах.

DRY (Don’t Repeat Yourself) — избегай дублирования кода.

KISS (Keep It Simple, Stupid) — простота важнее избыточной сложности.

YAGNI (You Aren’t Gonna Need It) — не добавляй функциональность "на будущее".

Пример SOLID (TypeScript):

// Принцип единственной ответственности
class Logger {
  log(message: string) {
    console.log(message);
  }
}

class UserService {
  constructor(private logger: Logger) {}

  saveUser(user: User) {
    // логика сохранения
    this.logger.log(`User saved: ${user.name}`);
  }
}

Ответ 18+ 🔞

А, смотри-ка, опять про эти ваши принципы! Ну ладно, давай разжую, как для дебила, только без мата... Хотя, блядь, куда ж без него.

Вот смотри, есть такая штука — SOLID. Это не про то, что твой код должен быть твёрдым, как член с похмелья. Это пять правил, чтобы твои классы не превращались в такое монструозное говно, которое потом сам же и будешь разгребать.

  1. S — Single Responsibility (Принцип единственной ответственности). Это как с мужиком в доме. Один хуярит на работе, другой — с детьми сидит, третий — жрачку готовит. Нельзя, чтобы один чувак был и сантехником, и электриком, и крёстным отцом твоих детей одновременно. Класс должен делать что-то одно. Не пытайся впихнуть в UserService логику отправки email, логирования и расчёта налогов. Получится пиздец, а не класс. Смотри:
// ПЛОХО: Этот урод делает всё
class UserManager {
  saveUser() { /* ... */ }
  sendEmail() { /* ... */ }
  generateReport() { /* ... */ }
  logActivity() { /* ... */ }
}

// ХОРОШО: Каждый занимается своим делом, как в хорошей шараге
class UserRepository {
  saveUser(user: User) { /* ... */ }
}

class EmailService {
  sendEmail(to: string) { /* ... */ }
}

class Logger {
  log(message: string) { /* ... */ }
}
  1. O — Open-Closed (Открыт для расширения, закрыт для изменений). Представь, у тебя есть класс ReportGenerator. Тебе начальник говорит: «А сделай-ка, чтобы отчёт ещё в PDF и в Excel выгружался». Если ты полезешь внутрь этого класса и начнёшь там ковыряться, добавляя if (format === 'pdf'), то ты мудак. Ты должен сделать так, чтобы можно было добавить новую фичу (новый формат), не ломая и не меняя старый, работающий код. Через интерфейсы, абстракции, вот это всё.

  2. L — Liskov Substitution (Подстановки Барбары Лисков). Звучит, как диагноз, но суть проста. Если у тебя есть класс Утка с методом летать(), и от него наследуется класс РезиноваяУтка, то эта резиновая уёбыш должна тоже уметь летать(). Или хотя бы не выёбываться и не кидать ошибку. Иначе подставить её вместо обычной утки не получится — программа ебнется. Наследник должен полностью заменять родителя. Если не может — твоя архитектура хуйня.

  3. I — Interface Segregation (Разделение интерфейсов). Это про то, что не надо делать один интерфейс IMegaWorker с методами писатьКод(), тестировать(), кофеВарить() и подтиратьЖопуБоссу(). Если у тебя есть класс Стажёр, который только кофе варит, он всё равно будет вынужден реализовывать ВСЕ методы, даже те, что ему нахуй не сдались. Делай много маленьких и узких интерфейсов: ICoder, ITester, ICoffeeMaker. Бери только то, что нужно. Не тащи на себе всё, как последний олень.

  4. D — Dependency Inversion (Инверсия зависимостей). Высокоуровневые модули (логика приложения) не должны зависеть от низкоуровневых (работа с базой, файловой системой, API). И те, и другие должны зависеть от абстракций (интерфейсов). Проще говоря, твой сервис не должен кричать «Дай мне PostgreSQL драйвер версии 15.4!». Он должен говорить: «Мне нужен какой-нибудь клиент для базы данных, который умеет executeQuery». А уж что ты ему подсунешь — Postgres, MySQL или файлик на диске — ему похуй. Гибкость, ёпта!


А теперь про остальные три буквы, которые все любят повторять, но нихуя не соблюдают.

DRY (Don’t Repeat Yourself — Не Повторяйся). Если ты скопипастил один и тот же кусок кода в трёх разных местах, ты — говнокодер. Вынеси это в отдельную функцию, класс, хелпер. Потому что когда придёт время это менять, ты забудешь один из этих мест, всё сломается, и тебе придётся ебаться в три смены. Не создавай себе проблем на ровном месте.

KISS (Keep It Simple, Stupid — Будь Проще, Дурак). Не выёбывайся. Не пихай паттерны ради паттернов. Не создавай десятиуровневую абстракцию для задачи, которая решается в три строчки. Самый простой работающий код — лучший код. Сложность — это враг. Врага надо, как Муму, топить в пизду нахуй.

YAGNI (You Aren’t Gonna Need It — Тебе Это Не Понадобится). Самое важное правило для всех архитекторов-недоучек. Не пили фичи «на будущее», «а вдруг пригодится». Не добавляй в интерфейс методы, которые сейчас не используются. 99%, что они не понадобятся никогда, а вот поддерживать и тестировать этот хлам тебе придётся всегда. Делай только то, что требуется прямо сейчас. Всё остальное — похуй.

Вот и вся философия. Следуешь ей — живешь как человек. Не следуешь — получаешь легаси-проект, который все ненавидят, и в котором любое изменение стоит, как чугунный мост. Выбор за тобой, дружище.