1. История о компании

Хочу рассказать вам одну историю, которая демонстрирует как ООП помогает бороться со сложностью больших систем. Это необходимо, чтобы вы поняли назначение ООП.

Жила-была небольшая компания, которая занималась доставкой товаров в космосе...

Назовем ее Galaxy Rush. И работало в ней 5 человек. Один занимался финансами, второй работал на складе, третий выполнял доставку, четвертый руководил рекламой, а пятый управлял всем этим.

Они были очень старательными, и все у них получалось. У компании была хорошая репутация, и она зарабатывала много денег. Но с каждым годом заказов было все больше, так что директору пришлось нанимать дополнительных сотрудников. Несколько на склад, несколько на доставку, еще одного кассира и рекламщика для расширения рынка.

И тут начались проблемы. Людей стало больше, и они начали друг другу мешать.

Маркетолог тратит все деньги на новую рекламную кампанию, и в кассе нет денег на закупку товара, который надо срочно отправлять.

На складе есть 10 коробок с новенькими гипер-двигателями, которые поставляют раз в месяц. Курьер полетел отвозить один гипер-двигатель, и заказ на 10 гипер-двигателей от другого клиента вынужден ждать еще месяц. Первый курьер просто не знал о другом заказе, который выполняет второй курьер.

Новый помощник директора отправляет курьера на корабле для закупки товара, и все остальные ждут, пока появится доступный корабль. Есть куча срочных доставок, но этот помощник заведует только закупками и старается хорошо выполнять свою работу. Чем лучше человек выполнял свои обязанности, тем больше он мешал остальным.

Пытаясь проанализировать ситуацию, директор понял, что такие важные ресурсы, как корабль, наличность и товар расходуются не оптимально, а по принципу «кто первый встал — того и тапки». Любой мог взять нужный всем ресурс для своей работы, поставив при этом под удар остальных сотрудников, да и всю компанию в целом.

Нужно было что-то делать, и директор решил разделить монолитную компанию на несколько отделов. Появился отдел доставки, отдел маркетинга, отдел закупок, финансовый отдел и отдел запасов. Теперь уже никто не мог просто так взять корабль. Директор отдела доставки получал всю информацию о доставках и выдавал корабль тому курьеру, чей заказ был выгоднее для компании. Склад тоже не разрешал любому курьеру взять любой товар, а контролировал этот процесс. Финансовый отдел мог не дать денег на маркетинг, если знал, что скоро будет закупка. У каждого отдела было одно публичное лицо — его начальник. Внутреннее устройство каждого отдела было его внутренним делом. Если курьер хотел получить товар, он шел к начальнику склада, а не на склад. Если появлялась новая заявка, ее получал директор отдела доставки (public person), а не курьер (private person).

Другими словами, директор объединил в группы (отделы) ресурсы и действия над ними, а также запретил другим вмешиваться во внутреннюю структуру отделов. Контактировать можно было строго с определенным лицом.

С точки зрения ООП, это не что иное, как разбиение программы на объекты. Монолитная программа, состоящая из функций и переменных, превращается в программу, состоящую из объектов. А объекты содержат в себе переменные и функции.

Проблема была в том, что любой сотрудник мог бесконтрольно работать с любым ресурсом и отдавать команды любому человеку. Мы ввели небольшое ограничение, но получили больше порядка. А также смогли лучше контролировать все это.

Разделяй и властвуй в чистом виде.


2. Процесс создания программ

Хотелось бы затронуть еще один важный момент, который раскрывает еще одно преимущество ООП. Видите ли, программы больше напоминают не строения, а животных. Их не строят, их выращивают. Разработка — это постоянные изменения. В строительстве вы можете иметь хороший план и четко ему следовать. В случае с разработкой программ это не так.

Очень часто в программировании что-то нельзя сделать тем способом, который ты себе наметил вначале, и приходится многое переделывать. Еще чаще меняются требования заказчика.

А если заказчик проекта дал очень точную его спецификацию? Тогда все еще хуже. Взгляните на ситуацию с продуктом во времени.

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

И какой вывод можно сделать из всего этого? Внутреннюю структуру продукта нужно поддерживать в таком состоянии, которое позволит внести значительные (и не очень) изменения с минимальными переделками.

Связность объектов

Но сделать это сложнее, чем решить сделать. Мы уже говорили, что программа состоит из объектов, которые взаимодействуют между собой. Давайте нанесем на доску все объекты нашей программы, обозначив их жирными точками. И проведем от каждого объекта (точки) стрелочки ко всем объектам (точкам), с которыми он взаимодействуют.

Теперь мы будем объединять объекты (точки) в группы. Точки должны быть объединены в группу, если связи между ними гораздо интенсивнее, чем с остальными точками. Если большинство стрелочек от точки идет к точкам ее же группы, тогда разбиение на группы произошло правильно. Точки внутри одной группы мы будем называть сильно связанными, а точки из разных групп — слабо связанными.

Принцип слабой связности

Это называется «принцип слабой связности». Программа разбивается на несколько частей, часто слоев, логика которых сильно завязана на их внутреннем устройстве и очень слабо — на других слоях/частях. Обычно взаимодействие слоев очень регламентировано. Один слой может обращаться ко второму и использовать только небольшую часть его классов. Тот же принцип «разделения на отделы» только в большем масштабе.

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

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

Принцип Абстракции

Выбор структуры отделов и способа их взаимодействия — это «принцип Абстракции». В программировании он используется для определения, на какие части лучше разбить программу, и как эти части должны взаимодействовать. Данный принцип также можно применять к разделению полученных частей, пока мы не разобьем программу на отдельные классы.

А сокрытие внутренней структуры этих частей и жёсткие ограничения на взаимодействие с другими частями — это Инкапсуляция. Инкапсуляция + Абстракция — это краеугольные камни ООП. Хорошая программа обязана следовать этим двум принципам. В дальнейшем мы рассмотрим остальные принципы и поймем, какие преимущества они дают.