1. Історія про компанію

Хочу розповісти вам одну історію, що демонструє, як ООП допомагає впоратися зі складністю великих систем. Це потрібно для того, щоб ви усвідомили призначення ООП.

Була собі невелика компанія, що займалася доставкою товарів у космосі…

Назвемо її Galaxy Rush. І працювало в ній 5 співробітників. Один займався фінансами, другий працював на складі, третій доставляв товари, четвертий відповідав за рекламу, а п'ятий усім керував.

Вони були дуже старанними, і все в них складалося якнайкраще. Компанія мала хорошу репутацію та заробляла багато грошей. Але з кожним роком кількість замовлень збільшувалась, тож директору довелося наймати додаткових працівників. Декілька на склад, декілька на доставку, ще одного касира та ще одного маркетолога для розширення ринку.

І тут почалися проблеми. Людей стало більше, і вони почали один одному заважати.

Маркетолог витратив усі гроші на нову рекламну кампанію, і в касі немає грошей на закупівлю товару, який треба терміново відправити.

На складі є 10 коробок із новенькими гіпердвигунами, що надходять на склад раз на місяць. Кур'єр полетів відвезти один гіпердвигун, і замовлення на 10 гіпердвигунів від іншого клієнта буде чекати цілий місяць. Перший кур'єр просто не знав про інше замовлення, яке мав виконати другий кур'єр.

Новий помічник директора відправив кур'єра на кораблі для закупівлі товару, і всі інші змушені чекати, доки з'явиться доступний корабель. Є чимало замовлень, які потрібно терміново доставити, але цей помічник керує тільки закупівлями й намагається добре виконувати свою роботу. Що краще працівник виконував свої обов'язки, то більше він заважав іншим.

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

Потрібно було щось робити, і директор вирішив розділити монолітну компанію на кілька відділів. З'явилися відділ доставки, відділ маркетингу, відділ закупівель, фінансовий відділ і відділ запасів. Тепер уже ніхто не міг просто так взяти корабель. Директор відділу доставки отримував усю інформацію про доставки й видавав корабель тому кур'єру, чиє замовлення було вигіднішим для компанії. Склад теж не дозволяв кур'єрам брати товар на свій розсуд, а натомість контролював цей процес. Фінансовий відділ міг не дати грошей на маркетинг, якщо знав, що найближчим часом планується закупівля. У кожному відділі була тільки одна публічна особа — його керівник. Внутрішній устрій окремих відділів був їхньою внутрішньою справою. Коли кур'єр хотів отримати товар, він звертався до керівника складу, а не йшов просто на склад. Усі нові заявки отримував директор відділу доставки (public person), а не кур'єр (private person).

Інакше кажучи, директор об'єднав ресурси та дії над ними в групи (відділи), а також заборонив іншим втручатися у внутрішню структуру відділів. Контактувати можна було тільки з певною особою.

З погляду ООП це не що інше, як розділення програми на об'єкти. Монолітна програма, що складається з функцій і змінних, перетворюється на програму, що складається з об'єктів. А об'єкти містять в собі змінні та функції.

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

«Розділяй і володарюй» у чистому вигляді.


2. Процес створення програм

Торкнімося ще одного важливого моменту, який розкриває додаткову перевагу ООП. Розумієте, програми скоріше схожі не на будівлі, а на тварин. Їх не будують, їх вирощують. Розробка — це постійні зміни. Для будівництва ви можете мати хороший план і чітко його дотримуватись. Що ж до розробки програм, це не так.

Дуже часто в програмуванні щось не вдається зробити в той спосіб, який було передбачено спочатку, і доводиться багато чого переробляти. Ще частіше змінюються вимоги замовника.

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

Успіх продукту призведе до того, що замовник захоче випустити його нову версію, а потім ще і ще. І, звичайно ж, потрібно буде внести лише «невеличкі зміни» в уже наявний продукт. Тому розробка продукту — це ланцюжок постійних змін. Тільки масштаб часу різний. Нова версія може випускатися щотижня, щомісяця або кожні пів року.

І який же висновок можна зробити з усього цього? Внутрішню структуру продукту потрібно підтримувати в такому стані, який дозволить вносити значні (і не дуже) зміни з мінімальними переробками.

Зв'язність об'єктів

Проте зробити це складніше, ніж сказати. Ми вже говорили, що програма складається з об'єктів, які взаємодіють між собою. Нанесімо на дошку всі об'єкти нашої програми, позначивши їх жирними точками. А потім кожний об'єкт (точку) з'єднаємо стрілками з усіма об'єктами (точками), з якими він взаємодіє.

Тепер спробуймо об'єднати об'єкти (точки) у групи. Точки слід об'єднати в групу, якщо зв'язки між ними значно інтенсивніші, ніж з іншими точками. Якщо більшість стрілок від точки з'єднує її з точками цієї ж групи, значить, розподіл на групи виконано правильно. Точки всередині однієї групи будемо називати сильно пов'язаними, а точки з різних груп — слабко пов'язаними.

Принцип слабкої зв'язності

Це називається «принцип слабкої зв'язності». Програму розділяють на кілька частин, чи то шарів, які мають сильно пов'язану внутрішню логіку й дуже слабкі зв'язки з іншими шарами (частинами). Зазвичай взаємодію між шарами суворо регламентовано. Один шар може звертатися до іншого, але використовувати тільки невелику частину його класів. Це той самий принцип «розділення на відділи», тільки в більшому масштабі.

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

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

Принцип абстракції

Вибір структури відділів і способу їх взаємодії — це «принцип абстракції». У програмуванні він використовується для визначення, на які частини краще розділити програму та як ці частини мають взаємодіяти. Цей принцип також можна застосовувати для поділу отриманих частин, доки ми не розділимо програму на окремі класи.

А приховування внутрішньої структури цих частин і жорсткі обмеження на взаємодію з іншими частинами — це інкапсуляція. Інкапсуляція + абстракція — це наріжні камені ООП. Хороша програма має відповідати цим двом принципам. Далі ми розглянемо інші принципи та їхні переваги.