Буквально на каждом форуме WAPа я встречаю и продолжаю встречать вопросы вида - зачем нужен ООП когда можно жить без него? Вот и здесь, я нашел целых 3 темы, в которых, возможно, была предпринята попытка раскрытия данного вопроса, но совсем в другом русле. Вопрос отпадает сам собой, когда речь заходит о сложных системах, решающих целую группу задач со своими подзадачами. Стоит системе вырасти во что то, требующее декомпозиции задач, как на помощь приходит ООП. Я уже много писал об этой модели http://visavi.net/blog/blog.php?cid=12& (автор - Башка) и часто участвую в темах, связанных с ней, потому хотелось бы немного поговорить о данном инструменте и на этом форуме.
Для кого эта статья?
Данная статья рассчитана на программистов, знакомых как с PHP, так и с его объектным синтаксисом. Я не буду переписывать здесь что такое класс, свойства и методы, обо всем этом вы можете подробно прочитать в учебниках или в документации. Целью данной статьи является показ ОО модели несколько с другой стороны, нежели вы привыкли ее видеть. Настоятельно рекомендую вам внимательно изучить синтаксис ООП в PHP, а так же такие фундаментальные понятия, как инкапсуляция, полиморфизм, наследование и абстрагирование.
Немного о терминах
Чтобы не тратить символов далее в статье, многие термины ООП будут описаны в этой части статьи. Обращайтесь к ней если какой то термин вам покажется непонятным.
- Объект - конкретная совокупность данных, представляющих некоторую сущность системы;
- Класс - совокупность однотипных объектов, их общая структура;
- Свойство объекта - единица характеристики объекта;
- Значение свойства объекта - конкретное значение характеристики объекта;
- Состояние объекта - совокупность значений всех свойств объекта;
- Метод объекта - алгоритм, ответственный за изменение состояние объекта или получения его текущего состояния;
- Инстанцирование класса - создание экземпляра класса (объекта);
- Инкапсуляция - сокрытие реализации объекта;
- Семантика свойства - имя свойства, тип принимаемого значения, назначение свойства;
- Семантика метода - имя метода, тип возвращаемого значения, порядок, имена и типы аргументов, назначение метода;
- Семантика класса - совокупность семантик всех свойств и методов класса, назначение класса;
- Полиморфизм - различная реализация одной семантики. Данное свойство позволяет заменить два полиморфных класса друг на друга без необходимости изменения алгоритмов работы с ними;
- Наследование - повторное использование класса с возможностью его расширения. Иерархия наследования сохраняется;
- Абстрагирование - отвлечение от малозначимых данных предметной области;
- Шаблоны проектирования (паттерны проектирования) - наиболее удачное решение задачи в контексте;
- Архитектура - логическая структура системы;
- Архитектурные шаблоны (архитектурные паттерны) - наиболее удачные архитектурные решения.
В чем ошибка?
Важнейшим при понимании ОО модели является не ее синтаксис, а границы ее использования и ОО мышление программиста. Мое знакомство с ОО моделью проходило ни чуть не иначе вашего. Увидев класс для написания "Hello world" я прикрыл учебник и подзабыл об ОО на неделю другую. Hello world ОО примеры годятся разве что при изучении синтаксиса ОО модели языка, но не для понимания смысла данной модели. Смысл ОО модели не зависит от языка программирования и совершенно одинаков в любом языке. Именно по этому вам необходимо без скептицизма изучить синтаксис ООП языка PHP опираясь на "натянутые за уши" примеры, так как без понимания синтаксиса изучать ОО модель будет сложнее.
После того, как вы поняли как именно пишутся классы, определяются их свойства и методу, как выполняется инстанцирование класса, создаются и используются статичные свойства и методы, выполняется наследование и т.п. можно углубляться в основы ОО модели.
Цели и задачи ООП
Для чего же нужен этот "монстр" в программировании? Неужели нельзя обойтись при написании скриптов старыми добрыми функциями и переменными? Для ответа на эти, и другие схожие вопросы, вернемся во времена зарождения программирования и взглянем на код. Код, написанный на языке assembler сложно читать и сопровождать, с его помощью можно написать программы в 1 000 или даже 10 000 строк кода, но чем больше программа, тем сложнее ей управлять. С появление структурированных языков программирования, стало гораздо проще прослеживать сложные алгоритмы. Появление функций позволило повторно использовать код и дало толчок к декомпозиции задач (разбиению задачи на подзадачи). Сейчас сложную задачу можно разбить на функции и решить путем последовательного их вызова. Такая модель позволяет временно абстрагироваться от всего лишнего и сосредоточится только на данной подзадаче, а не на всей задаче.
Приход эры ООП направляет вектор мысли не на алгоритмы, а на данные. Если процедурное программирование ориентировалось на алгоритм (процедуры, функции), то ООП рассматривает в первую очередь данные и сущности. Для примера, при реализации модуля "Гостевая книга" матерый процедурник обратит будет рассматривать функции добавления, обновления, просмотра и удаления сообщений. Он создаст эти функции и определит входные параметры для них. Объектник же сначала посмотрит в сторону используемых данных, а именно ответит на вопрос - что использует модуль "Гостевая книга" в своей работе для решения поставленной задачи? - он так же глянет на реальный мир и попробует спроецировать его в модуль. На пример, "Гостевая книга" уже давно используется в отелях и ресторанах, но здесь используется бумажная книга, в которой может писать любой желающий. Почему бы не использовать этот же принцип для реализации? Что нам нужно для этого?
1. Сообщение пользователя - сама цель книги;
2. Автор - нужно ведь знать кто именно оставил то или иное сообщение о нашем отеле или ресторане;
3. Сама книга - где же писать как не в ней?!
Далее объектник просто реализует эти сущности в системе:
class Message{
...
}
class Autor{
...
}
class GuestBook{
...
}
Как видите, на первый план встают данные и сущности, а не алгоритмы, работающие с ними.
ОО модель позволяет легче абстрагироваться при разработке системы, а так же группировать алгоритмы и данные в объекты по их целевому назначению.
После того, как объектник выделит основные сущности, он обращается к паттернам GRASP для распределения обязанностей. Эти шаблоны описывают основные правила, позволяющие организовать работу ОО программ, а так же помогают при проектировании архитектуры.
А как же функции?
Важно понимать, что программы пишутся либо в процедурном, либо в ОО стиле! Смешение этих моделей недопустимо, так как теряется вся выгода от их использования. Присутствие в программе обоих стилей говорит о плохой архитектуре и, чаще всего, о попытке процедурника перейти на ООП. Такие "спагетти" ухудшают читаемость кода, а так же отменяют все плюсы от использования объектов. Запомните, в ООП нет понятия функций и глобальных переменных, все взаимодействия проходят на уровне объектов и их классов.
Синтаксис изучен, вектор есть, что дальше?
А дальше настоятельно рекомендую вам начать изучение существующих паттернов проектирования! Это позволит вам лучше понять смысл ОО модели и ее прелести.
Преимущества и недостатки
Начну с недостатков:
- Код больше на простых участках - часто говорят - для данной задачи ООП не нужен! - это выражение от части правильно. Если вы пишите один модуль, который имеет жесткие границы и он очень прост, можно использовать процедурный стиль, но если вся система у вас ОО, а модуль работает с ней довольно тесно, то каким бы простым он не был, пишите его объектно-ориентированно!
- Код выполняется дольше - гипер-раздутая проблема. В действительности сложная ОО программа выполняется быстрее ее же, но в процедурном стиле. Это часто связано с накладными расходами, вызванными сложными алгоритмами преобразования. Конечно процедурно-ориентированные программы выполняются быстрее, но выигрыш в скорости настолько мал, что сравним с экономией символов в именах переменных для сокращения объема данных при их интерпретации.
А теперь о преймуществах:
- Проектировать сложные программы становится проще - благодаря абстрагированию, гораздо проще держать в голове сложные задачи;
- Масштабирование и сопровождение программ упрощается - инкапсуляция, полиморфизм и наследование позволяют изменять программу без необходимости изменения кода. Чаще всего ОО программисты стремятся именно к этому результату;
- Удобное повторное использование кода - функции хорошо подходят для повторного использования алгоритма, а объекты и классы, для повторного использования всей системы и ее модулей. Здесь можно выделить следующие уровни:
* Функция;
* Класс;
* Модуль - набор классов, решающих одну задачу;
* Пакет - набор модулей, решающих одну группу задач;
* Система - набор пакетов, решающих группы задач пользователей;
* Агрегатная система - набор систем, решающих группы мало связанных задач большого числа пользователей.
Когда же переходить на ООП?
Почему бы не прямо сейчас? Прочитайте учебник и изучите синтаксис ОО модели в PHP. Прочитайте о паттернах проектирования в соответствующих учебниках. Выберите любой существующий у вас модуль и попытайтесь переписать его в ОО стиле. Используйте IDE вместо текстового редактора, это поможет вам.
Заключение
Множество примеров использования ООП взамен процедруного стиля приведено в указанном мною в начале темы блоге. Я понимаю, что пока мои аргументы недостаточны, для того, чтобы программисты перешли на ОО стиль, но целью данной статьи была попытка уберечь вас от неверного пути в изучении данной модели!