Недавно спросили, могу ли на примерах обучить объектно-ориентированному программированию (ООП), что удивительно. Ведь существует так много материала по данному вопросу: видео, литература, интерактивные сайты и множество других источников, но задумался.
Ниже изложен результат размышления начиная с ответа на вопрос «Кто клиент программы?», до отчасти вымышленной истории появления ООП и в итоге вывод, что ж за толк разработчикам от использования ООП.
Кто является клиентом программы?
Программа обернута треугольником требований: компьютером, пользователем, разработчиком. Кто из них является клиентом программы?
Рис. 1 Три клиента программы: компьютер, пользователь, программист
Так для кого пишется софт?
Первично - пользователь и именно он выбирает и идет на компромисс:
- Делать вручную
- Простое ПО, мало возможностей
- Сложное ПО - мощный комп или длительное время ожидания
В прошлом вычислительные возможности компьютеров были малы и сложный, крупный софт мало кого интересовал, и, если создавался, то различными корпорациями и консорциумами. Программы, создаваемые рядовыми разработчиками, были просты, малы в объемах и «затачивались» под определенное железо.
Рис. 2 Требовательный компьютер, но недовольный пользователь
Сейчас же рынок ПО насыщен и пользователь хочет сложной логики, интерактивности, графики и самое удивительное - это часто возможно!
Рис. 3 Мощный компьютер, довольный пользователь
Вот только беда - софт стал еще крупнее, сложнее, и для разработки сколько-нибудь серьезного проекта требуется команда.
Рис. 4 Взаимодействие множества программистов через один программный код
Возникает взаимодействие Программист-программист, причем с развитостью сети, порою это взаимодействие только через программный код. Какое требование появляется? Правильно! Умение понимать чужой код и писать его, чтоб он был понятен, прост для других.
Как добиться простоты?
1. Взять простую задачу;
2. Разбить сложную на простые. С возможностью осознать логику разбиения;
3. Уменьшить количество взаимосвязей;
4. Очертить ответственность (логику разбиения);
5. Следить за эффективностью трудозатрат на изменение (убираем дублирование);
6. Быть уверенным, что программа делает то, что нужно - тестирование.
Вернемся к ООП
ООП базируется на трех основных принципах: инкапсуляция, наследование и полиморфизм.
Инкапсуляция - если вы спросите в меру разбирающегося программиста: «Что такое инкапсуляция?», то практически в 100% случаев услышите, что это сокрытие кодов и данных. Но есть немаловажная вещь: объединение того и другого, сужение контекста.
Представьте, что вы программируете на структурном языке, к примеру С. И нужен вам двусвязный список. Получится код, подобный приведенному ниже:
Обратите внимание: какое слово повторяется в имени функций? Правильно — list, с помощью него задается контекст. Также у нас есть методы добавить, очистить, найти. Представьте, что мы объявили переменную типа list и хотим добавить в нее элементы, при данном действии в списке возможных функций вылезает громадное количество функций для добавления в словарь, хэш-таблицу и еще много чего. Вы возразите, что есть пространства имен и с помощью них можно задать контекст, но пользоваться конструкциями list::add(employeeList, newEmployee); не удобно, особенно с учетом использования длинных имен в крупных проектах, когда количество типов коллекций переваливает за десяток.
В ООП объект List прекрасно определяет контекст и методы, которыми можно изменять его состояние. Написал имя переменной, нажал Ctrl+пробел — наслаждаешься кратким списком возможностей работы с данным объектом. Благодаря данному свойству ООП даже и не припомню, когда последний раз смотрел в документацию для ознакомления с возможностями класса.
Сокрытие данных и кода обрабатывающего эти данные еще один плюс. Он экономит ресурс нашего восприятия (мыслетоплево) для ознакомления с классом — посмотрели на открытые методы и знаем, что мы можем сделать с объектом класса, не надо разбираться во внутренностях, только если там ошибка или надо поменять логику.
Наследование, полиморфизм — что устраняет? Как считаете? На мой взгляд дублирование. Есть схожие сущности в предметной области, отличающиеся парой дополнительных полей и чуть-чуть другой обработкой этих данных. Как быть? В структурных языках данная задача решалась через неразмеченные или заранее зарезервированные области памяти с указателем void на них и указателями на функции.
Налицо, что в данном коде очень легко запутаться. В нужный момент в выделенной памяти может оказаться неожиданное значение.
Подведем итог
ООП — это синтаксический сахар, основанный на базовых принципах:
— сужение контекста,
— самодокументированние кода,
— устранение дублирования.
Этот сахар здорово подслащивает жизнь при разработке больших и сложных проектов.
P.S. Именно в обсуждении ООП с ребятами из моей команды всплыл момент, про который я забыл создавая данный материал — ООП дает терминологию, близкую к терминам предметной области, мы мыслим, говорим, пишем код терминами предметной области, что позволяет общаться вам на одном языке с заказчиками и командой (Абстракция).
ООП не панацея, у любого инженерного решения есть свои плюсы, минусы, и научиться их видеть можно лишь с опытом. В данной статье приведено мое видение ООП, принципов программирования. Это то, что позволяет мне, как программисту, строить системы, которые работают у Заказчика и воспринимаются другими программистами. Напишите в комментариях насколько была полезна, интересна для вас статья.
Мы увлечены программированием больших систем, ведем блог в контакте https://vk.com/itbtr Публикуем методы, принципы и разборы на сайте http://flipworldit.ru/ . Заходите, будем рады!