Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «YAGNI (вам це не знадобиться)». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**YAGNI (You Aren't Gonna Need It)** - будуй лише те, що вимагає поточна специфікація. Пропускай решту, поки реальна потреба не з'явиться. ```javascript // специфікація каже "фільтр активних" - і нічого більше function getActiveUsers(users) { return users.filter(u => u.active); } ``` **Ключове:** пиши код для сьогоднішніх вимог, а не для завтрашніх здогадок.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**YAGNI (You Aren't Gonna Need It)** - принцип розробки, який каже: реалізуй лише те, що вимагає поточна специфікація, і додавай більше лише тоді, коли реальна потреба з'являється. ## Теорія ### Коротко - Аналогія: будуй кухню зараз, а не преміальну кулінарну студію, яка "може знадобиться". - Головне правило: "Чи вимагає специфікація цього сьогодні?" Якщо ні - пропускаємо. - Ціна ігнорування: команди витрачають 20-30% часу на функціонал, яким ніхто не користується. - YAGNI проти DRY: DRY прибирає поточне дублювання; YAGNI зупиняє спекулятивний код. - Виняток: основи безпеки та перевірені структурні патерни, як MVC-скелет. ### Швидкий приклад ```javascript // Завдання: фільтрувати користувачів за активним статусом. Більше нічого. // Порушення YAGNI - сортування і пагінація додані "на потім" function getActiveUsersBad(users, page = 1, sortBy = 'name') { return users .filter(u => u.active) // потрібно .sort((a, b) => a[sortBy].localeCompare(b[sortBy])) // ще не потрібно .slice((page - 1) * 10, page * 10); // ще не потрібно } // YAGNI: робимо рівно те, що каже специфікація function getActiveUsers(users) { return users.filter(u => u.active); } // Результат: [{ name: 'Alice', active: true }, { name: 'Bob', active: true }] ``` Погана версія це не просто зайвий код. Це код, який ніхто не тестуватиме, не підтримуватиме і, швидше за все, ніколи не викличе. ### Чому це важливо Спекулятивні фічі коштують двічі: спочатку на написання, потім на підтримку, коли реальні вимоги змінюються. Другий удар болючіший, бо ти рефакториш код, який ніколи не служив жодному користувачу. Бачив, як таблицю ролей побудували до релізу і видалили через два тижні - жоден користувач її так і не торкнувся, два дні роботи у смітник. Оцінка 20-30% витраченого часу - консервативна. Хто чистив кодову базу, повну "про запас" абстракцій, знає, наскільки гірше буває. Важливий нюанс: YAGNI не означає "ніколи не плануй наперед". Це означає: не пиши код, поки потреба не доведена. ### Коли застосовувати - Специфікація не містить фічі: пропускаємо, пишемо коли прийде тікет. - User story каже "можливо пізніше": реалізуємо мінімум, який працює зараз. - Фаза прототипу: найменше, що перевіряє гіпотезу. - Рефакторинг: додаємо фічу лише якщо метрики показують реальне вузьке місце. ### Типові помилки **Зайві параметри "на всякий випадок"** ```javascript // Неправильно - три параметри, яких ніхто не просив function filterUsers(users, active = true, minAge = 0, country = '') { return users.filter( u => u.active && u.age >= minAge && (country ? u.country === country : true) ); } // Правильно - специфікація сказала "лише активні" function filterUsers(users) { return users.filter(u => u.active); } ``` Додаючи параметри зараз, ти зобов'язуєшся писати тести для них, тримати їх у документації і пояснювати кожному новому розробнику. Додавай, коли тікет вимагатиме. **Надмірні абстракції для гіпотетичних плагінів** ```javascript // Неправильно - базовий клас для плагінів, яких не існує class UserFilter { process(users) {} // порожній метод в очікуванні "колись" } // Правильно - просто функція function filterUsers(users) { return users.filter(u => u.active); } ``` Типова ситуація: розробник пише систему плагінів у перший день, її жодного разу не розширюють, і через пів року кожна реальна фіча змушена обходити невикористану абстракцію. **Інфраструктура "для масштабування" без доведеної потреби** Redis-черга для сервісу з 10 користувачами на день дає негайні операційні витрати без жодного гарантованого виграшу. Послідовність правильна: спочатку масив у пам'яті, потім база даних, потім черга - і лише після того, як навантажувальний тест покаже необхідність. **Спекулятивні стани UI** Невикористані вкладки, відключені кнопки без специфікації, стани завантаження для фіч, яких ще немає. Все це перетворюється на мертвий код, який junior-розробники налагоджують без жодного контексту. ### Реальне застосування - React: `create-react-app` постачається з мінімальними налаштуваннями. Без TypeScript, Redux і роутингу - поки вони реально не знадобляться. - Express: починаємо з базового роутера. Rate limiting додаємо після реального аудиту безпеки, а не наперед. - Redux: actions тільки для живих фіч. Жодних "майбутніх offline mode" саг одразу. - CLI на Node.js: `fs.readFileSync` добре працює, поки профілювання не покаже вузьке місце. Тоді переходимо на async. ### Питання на співбесіді **Q:** Що таке YAGNI? **A:** Принцип, який каже: будуй лише те, що вимагає поточна специфікація. Якщо потреба не доведена, коду не існує. **Q:** Чим YAGNI відрізняється від DRY? **A:** DRY прибирає дублювання в коді, який вже існує. YAGNI зупиняє написання коду, якого взагалі не повинно бути. **Q:** Коли можна порушити YAGNI? **A:** Для перевірених патернів, як MVC-структура, або для санітизації введення. Основи безпеки застосовуються завжди, навіть до того як користувачі про це попросять. **Q:** Як зрозуміти, що фіча реально потрібна? **A:** Відстежуй тікети та метрики використання. Якщо менше 5% користувачів просять щось протягом трьох місяців, воно, мабуть, не потрапляє в наступний спринт. Senior-розробники прив'язують це до OKR. **Q:** Чи може YAGNI конфліктувати з agile-плануванням? **A:** Ні, якщо розглядати кожен спринт як MVP-цикл. Spike-сторії для реальних невідомих. Все інше потрапляє в реліз лише коли user story доводить потребу. ## Приклади ### Базовий: YAGNI в Express-ендпоінті ```javascript // Специфікація: повернути активних користувачів з валідним email. Більше нічого. app.get('/api/users', (req, res) => { const activeUsers = users.filter(u => u.active && u.email); res.json(activeUsers); }); // GET /api/users → [{ id: 1, name: 'Alice', active: true, email: 'a@test.com' }] // Без авторизації, без пагінації - специфікація поки не вимагає. ``` Цей ендпоінт робить рівно те, що каже поточна специфікація. Авторизація з'явиться, коли прийде відповідний тікет з безпеки, а не раніше. ### Середній рівень: сортування за запитом, а не наперед ```javascript // Користувачі попросили сортування після релізу. Не будуємо наперед. function UserList({ users }) { const [sortBy, setSortBy] = useState(null); // null, поки не клацнули const sorted = sortBy ? [...users].sort((a, b) => a[sortBy].localeCompare(b[sortBy])) : users; // логіка сортування не виконується без потреби return ( <div> {sorted.map(u => <div key={u.id}>{u.name}</div>)} <button onClick={() => setSortBy('name')}>Сортувати за іменем</button> </div> ); } ``` Сортування з'явилось лише тому, що користувачі реально попросили його після релізу. До цього компонент вийшов без нього. Додавання зайняло один день, а не тиждень рефакторингу заздалегідь побудованої системи.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.