Обʼєктно-орієнтоване програмування — найпоширеніша парадигма в розробці. Про цю концепцію знає кожен девелопер, а про застосування принципів питають на кожній співбесіді, проте в комʼюніті є чимало помилкових упереджень на цю тему. Чи можна розробити якісну підтримувану архітектуру без ООП? Якою була початкова ідея ООП та наскільки вона трансформувалася у сучасній розробці? Що не так з інкапсуляцією та як не ускладнити код надмірними інтерфейсами? Дмитро Гринець, co-CEO та співзасновник компанії PlantIn з екосистеми Genesis, спростував найпоширеніші міфи.
PlantIn — застосунок-помічник для догляду за різними видами рослин з використанням ШІ.
МІФ №1
ООП гарантує якість коду. Тільки з цією парадигмою можна розробити архітектуру і підтримувати її, не витрачаючи зайвих ресурсів
ООП вважається найбільш зрозумілою та простою парадигмою програмування. Функціональний та процедурний методи побудовані на функціях, які обробляють дані без збереження стану. ООП орієнтоване на об'єкти, які мають стан і поведінку, що відповідає природному способу мислення людини. Це дає спеціалістам цілісну картину продукту, який вони створюють, значно спрощує розробку і розуміння коду. Загальна ідея ООП полягає в полегшенні взаємодії різних частин коду, можливості перевикористовувати їх, не змінювати те, що непотрібно, та фокусуватися на головному, наприклад, що виконує певний клас чи функція.
Водночас ООП не є магічною формулою, яка автоматично розв'язує всі проблеми програмування. Спагеті-код можна створити будь-якою мовою чи парадигмою — написати погано структуровані класи, що некоректно працюють з даними, чи використати функцію, яка має побічні ефекти або виконує безліч різних дій.
Так само хороша архітектура можлива з будь-якою парадигмою. Є чимало прикладів якісних програм, написаних за допомогою С — популярною раніше процедурною мовою, з якою розробники чудово справлялись і будували класні системи. Отже, жодна парадигма програмування не гарантує якості та не звільняє від помилок. Це лише інструмент, використання якого залежить від розробника та його досвіду.
МІФ №2
Початкова концепція ООП була сильно перекручена
Чимало розробників переконані, що від початкової концепції ООП, коли об'єктам надсилаються повідомлення, які також є об'єктами, залишився лише виклик методу, що принципово мало відрізняється від процедурного програмування.
Певне спрощення концепції справді відбулося — і це цілком природно. Метод зʼявився як експериментальна концепція у 1960-х роках — в часи, коли код писали на перфокартах. Принципи ООП дозволили швидше створювати складніші системи та знизити поріг входу до програмування. З того часу зʼявилося безліч мов, фреймворків, напрямів програмування, стрімко розвинулися технології. Сьогодні принципи ООП набули ширшого застосування і водночас використовуються менш прискіпливо. Наприклад, принцип наслідування з часом відійшов на другий план, давши дорогу композиції, і вже досить рідко можна зустріти в коді багаторівневу структуру наслідування.
Розробники нерідко застосовують принципи ООП помилково. Наприклад, фокусуються на викликах розрізнених методів, які можна було просто написати функціями. Тобто в коді немає поточного стану обʼєкту, взаємодії чи, скажімо, інкапсуляції. Виходить, це простий виклик функції, який можна було б написати й без ООП. Невірне застосування принципів ООП трапляється часто, але це залежить передусім від розробників. Сама концепція ООП не змінилася — метод залишається важливим у сучасному програмуванні, розвивається та адаптується до нових викликів і потреб.
МІФ №3
Бізнес-потреби заважають будувати якісну продуману ООП-архітектуру, зокрема на етапі MVP
Бізнес і справді не хвилює, яка парадигма використовується в коді, як побудована архітектура чи структура класів, чи якою є технічна реалізація бізнес-ідеї. Проте це не є проблемою, адже програмування покликане розв'язувати завдання бізнесу, а не навпаки. Отже, інженери мають побудувати архітектуру, враховуючи обмеження та цілі компанії.
Етап MVP — створення першого версії продукту з обмеженим функціоналом. Його мета — швидко протестувати гіпотезу, не витрачаючи багато ресурсів. Звідси сформувалося упередження, що на цьому етапі немає часу та можливості заморочуватися питаннями архітектури. Якщо ідея злетить, код можна переписати.
Найвідоміший успішний кейс — Slack, який було переписано з нуля. Проте часто підхід переписування буває невдалим: можна витратити чимало часу, а новий код міститиме нові помилки та проблеми. Тому ефективніше рішення — подбати про якісну архітектуру на етапі MVP та надалі допрацьовувати її, і переписуючи лише окремі фрагменти. Насправді досвідченому розробнику не так складно написати якісну продуману архітектуру на етапі MVP з першого разу.
МІФ №4
Задля безпеки системи потрібно інкапсулювати дані та методи з усіх класів
Інкапсуляція — один з найскладніших принципів, який часто застосовують неправильно. Основна проблема полягає в тому, розробники часом занадто ускладнюють її, ховаючи усе, що бачать. Їхній мотив — подбати про безпеку, зокрема проєктів з чутливими даними. Тоді посилання на дрібні інкапсульовані обʼєкти розростаються вибуховими темпами, та інкапсуляція виглядає як навала незграбних взаємопереплетених методів, що викликають один одного. Якщо складність інкапсуляції двигуна платіжної системи ще можна виправдати, то надмірне використання в інших кейсах лише погіршує код.
Визначаючи ступінь інкапсуляції розробник має балансувати між безпекою та гнучкістю. Для малих та простих об'єктів може бути прийнятним більше відкритого доступу до даних і методів, але важливо зберігати інкапсуляцію там, де це необхідно для забезпечення цілісності та безпеки програми. Якщо коректно застосовувати цей принцип, він не ускладнить код та не заважатиме доступу до даних і методів класів.
МІФ №5
Інтерфейси завжди спрощують тестування, підтримку коду та забезпечують консистентність
Фактично є два підходи до інтерфейсів в ООП: або їх взагалі не використовують, або застосовують всюди, де тільки можна. В чому їхній сенс, та чи потрібні вони в коді — поширена тема для дискусій серед розробників.
Інтерфейси є важливою концепцією в об'єктно-орієнтованому програмуванні. Це елемент абстракції, який визначає набір методів без їхньої конкретної реалізації. Інтерфейс вказує, які операції можуть бути викликані для об'єктів, але не накладає обмежень на саму реалізацію методів. Вони мають конкретне завдання, і їх потрібно застосовувати тоді, коли розумієш, що у процесі роботи з цією частиною коду, може зʼявитися необхідність змінити реалізацію. Наприклад, спосіб кешування обʼєктів: зараз ми кешуємо у пам'ять програми, а згодом можемо робити це через Redis. Цю проблему можна передбачити, використавши інтерфейс взаємодії. Тоді зміна реалізації буде безболісною, а кінцеві користувачі цього навіть не помітять. Водночас це зручно розробнику: працюючи з кодом, він не фокусується на конкретній організації кешування, а планує загальну реалізацію, яку потім можна змінити в будь-який час.
Якщо ж певна реалізація не буде змінюватися, писати інтерфейс немає сенсу. В Java та її фреймворку Spring все пишеться через інтерфейси — кожен клас та сервіс, який ти використовуєш. Якщо їхня реалізація не змінюється протягом десятиліть розробки цієї програми, в чому тоді полягав сенс? Це просто марне витрачання часу і коду.
МІФ №6
ООП застаріло, прийшов час для нової парадигми
У 2015-2020 роках періодично зʼявлялася низка критичних статей відомих науковців та розробників — Річарда Столмана, Едсгера Дейкстри, Алана Кея та інших. Вони детально описували, що не так з ООП у сучасному програмуванні та наводили переваги інших парадигм. Ймовірно, це було спробою розширити межі комʼюніті, змінити домінування ООП-first мов та привернути увагу до альтернативних технологій. Це мало сенс, адже сьогодні люди часто приходять в ІТ, випадково обирають ООП-мову, та перше, про що вони дізнаються на лекції — що таке ООП. Потім вони починають програмувати та навіть не знають, що існують інші парадигми, які насправді в певних ситуаціях працюють ефективніше. Наприклад, для завдань Machine Learning чи Data Science ООП взагалі не підходить.
Проте зміни домінування ООП так і не відбулося. Насправді нові парадигми зʼявляються не так часто. В останні десятиліття класична наука про інформацію (Computer Science), коли науковці займалися фундаментальною теорією, розробкою мов та систем, перейшла до суто практичного застосування. Розробкою нової парадигми зараз глобально просто не займаються. Можливо розвиток ШІ призведе до появи нового методу. Як варіант — трансформується саме поняття парадигми та конкретної мови, і розробники ставитимуть завдання звичайними словами, або зміниться саме поняття програми.
Варто памʼятати, що ООП може інтегруватися з іншими парадигмами програмування для створення більш потужних і гнучких програмних рішень. Ця парадигма може існувати поруч і взаємодіяти з функціональним, реактивним, процедурним та іншими методами програмування. Вибір конкретної парадигми або їх комбінації залежить передусім від потреб проєкту та завдань, які ви намагаєтеся вирішити.