SOLID здорової людини

Більшість інженерів, включаючи мене, відносяться скептично до строгого дотримання цих принципів. Але сучасна розробка — це майже завжди trade-off і якщо трохи підігнати їх під реальне життя, вийде доволі непоганий набір хороших практик.

Тому ловіть життєву версію SOLID:

S — Single Responsibility

Якщо ти назвав свій сервіс AuthService, то будь ласка не пхай туди логіку повʼязану з платежами, валідацією і так далі.

Принцип каже, що має бути тільки одна причина для зміни цього сервісу і це зміни в Auth Flow.

O — Open/Closed

Якщо тобі треба внести якісь зміни в сервіс чи компонент на 2000 рядків коду, і ввечері ти хочеш відпочивати, а не відкочувати свої зміни з проду, краще не чіпай те гівно, а додай свої зміни поверх цього атракціону.

Принцип каже, що компоненти системи мають бути закритими для змін, але відкритими для розширення.

L — Liskov Substitution

Якщо ти по пʼяні вирішив перевизначити стандартний метод у репозиторії якоїсь ORM, наприклад UserRepository.find(), то семантично цей метод усе ще має щось шукати. Не треба в ньому щось видаляти чи створювати нові записи.

Принцип каже, що дочірній клас має безпечно замінювати батьківський.

I — Interface Segregation

Якщо бачиш величезний інтерфейс чи тип і хочеш зробити вигляд бурхливої діяльності, можеш розбити його на кілька менших. Це нічого не змінить, але ти зробиш PR і матимеш що сказати на дейліку.

Принцип каже, що краще мати кілька малих інтерфейсів, ніж один великий: так їх простіше перевикористовувати.

D — Dependency Inversion

В ідеалі твоя архітектура має залежати від абстракцій, а не від реалізацій. У реальному житті базовий мінімум — це взяти нормальний Node.js фреймворк, де з коробки є Dependency Injection, наприклад NestJS.

Без цього доведеться ініціалізувати залежності всередині бізнес-логіки. А це розірве вам дупу, коли проєкт розростеться і треба буде вносити зміни або покривати код тестами.

Принцип каже, що високорівневі модулі не мають залежати від конкретних реалізацій. Тобто вашому API контролеру має бути все одно, який саме сервіс підставлять усередину. Головне, щоб він відповідав потрібній абстракції: інтерфейсу, класу або токену провайдера.

Також, підписуйся на мій Telegram, там пишу про інженерний розвиток — t.me/devshive
І буду вдячний за підписку на YouTube канал — www.youtube.com/...​UCgd6DqNqG2mesv8_FID9NRg

👍ПодобаєтьсяСподобалось1
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Насправді SOLID це банальна спроба перемогти ІТ хаос застосувавши прості та перевірені часом інженерні практики. Приклад, який сподіваюся кожному відомий — це конструктор LEGO.
S — Single Responsibility. Це очевидно: елемент конструктора має бути простий і очевидний. Одинарний блок, подвійний, прозорий — не прозорий, кутовий, колесо — у кожного своє призначення. Якщо зробити великий складний елемент — він буде не універсальним і не зручним.
O — Open/Closed. Один з найочевидніших принципів у реальному світі: є мінімальні деталі які використовують як є. Блоки лего не відрізають як треба і не обробляють напилком. Якщо один блок не підходить — беруть інший. На жаль в ІТ це правило найчастіше порушують. Замість додати новий метод чи клас — міняють існуючій. Якій вже давно і правильно працює у купі місць, перевірений тестами та часом. І потім очікувано вигрібають купу проблем.
L — Liskov Substitution. Також очевидно: замість одного лего блока можна поставити інший. Наприклад замінив звичайні блоки на прозорі — зробив «вікно».
I — Interface Segregation. Це просто база лего! Невеликі зручні «кубіки» — інтерфейси, які між собою легко комбінуються. Особливо цікаво як, наприклад, роблять конструктор якогось об’єкта: тобто фактично моноліт розбирають на окремі елементи з такими інтерфейсами аби потім зібралося до купи.
D — Dependency Inversion. Сама суть збирання великого об’єкта по інструкції: спочатку з «кубіків» збираємо окремі модулі, а потім модулі стикуємо у більші об’єкти. Наприклад лего-Титинік треба збирати як 3 окремі частини, які поєднуються вже наприкінці.
Можна навести багато прикладів з інших інженерних галузей: як паяють електричні схеми з окремих деталей, як збирають механічні передачі з окремих шестерень, будують мости і т.і.

Один раз выучить и забыть до следующего собеса)

На практиці теж корисний (в рамках здорового глузду

CRUD без збереження стану це марнування часу. Звісно і без початкової ініціалізації чи завантаження з якогось джерела зберігання даних. О, і логування внесених змін.
Ось скільки спілкуюся з LLM моделями вони це на автоматі все одразу не видають.

можна докинути скіли, для Nest.js непогано справляється — www.skills.sh/...​lls/nestjs-best-practices

більше працює як економія токенів, бо по замовчуванню ± адекватно генерить код і не потрібно багато рефакторити

а що означає, що архітектура має залежати від абстракцій, а не від реалізацій?
а ще як зрозуміти, що інтерфейс вже величезний?

а взагалі не дуже розумію людей які раз в рік тут з’являються щоб відкрити людям таємниці SOLID

можете не читати в такому випадку, нащо себе мучити))

Кроме того следование SOLID ведет к нарушению YAGNI, KISS и DRY. Главный конфликт возникает, когда разработчики, стремясь сделать код «гибким» и «расширяемым», начинают проектировать архитектуру «на вырост».
Нарушение YAGNI (You Aren’t Gonna Need It): Этот принцип гласит: «Вам это не понадобится». Слепое следование SOLID часто приводит к созданию абстракций, интерфейсов и фабрик «на будущее», которые никогда не используются.
Результат: Простая задача, которая могла быть решена 2-3 классами, превращается в непонятную систему из 10+ сущностей. Код становится сложнее, но не гибче.
Нарушение KISS (Keep It Simple, Stupid): Принцип «Не усложняй». Стремление разбить каждую ответственность на отдельный класс или интерфейс может привести к чрезмерному дроблению системы.
Результат: Вместо понятной архитектуры получается «архитектурный космолет», который сложно понять и поддерживать. Это также противоречит здравому смыслу, так как бизнес об этом не просил.
Нарушение DRY (Don’t Repeat Yourself): Иногда, в погоне за «правильным» разделением ответственности (SRP), разработчики выносят логику в разные классы, что приводит к дублированию кода. Кроме того, SOLID превращает простую задачу в сложную архитектуру, это верный признак того, что разраб, возможно, нарушаете принцип YAGNI.Поэтому, лучшее решение это начинать юзать код с простого дизайна и рефакторить код по мере появления реальной необходимости в гибкости, как то так...

Мій поінт в тому що завжди потрібно шукати баланс. Сучасна розробка завжди про пошук компромісів😁

А що, є якісь інші? Во ж банальна логіка на граблях. Тобто я про те, що тут описані базові очевидні речі, до яких навіть ті хто не вчить то з досвідом колись приходить самостійно.

Ну так, от я і вирішив їх описати😁
А так принципів і хороших практик багато і з досвідом розумієш, які працюють, а які ні

Підписатись на коментарі