Профессиональная разработка Web-приложений.  
Боишься нашего дизайна?
Новости
PDF журнал
Участники проектa
Сотрудничество
Ссылки
Карта сайта
Комментарии
Комментарии к статье
Добавить комментарий
Обсудить на форуме
Информация об авторе
Оценка статьи

Выбираем лучший инструмент: Объектно-ориентированное и процедурное программирование в PHP

Оригинал находится по адресу http://www.zend.com/zend/art/oo-proc.php

Перепечатка материалов разрешается при условии ссылки (для интернет-изданий - гиперссылки) на сайт phpclub.ru/detail

Предполагаемая аудитория

Эта статья рассчитана на начинающих PHP-программистов, которые желают получить представление об объектно-ориентированном и процедурном подходах написания программ.

Предполагается, что читатели владеют основными знаниями в области PHP и классов.

Вступление

"Настоящий гений проявляет себя в умении обрабатывать неточную и противоречивую информацию" (Уинстон Черчиль)

В отличие от большинства других языков, PHP предоставляет возможность использовать при программировании как объектно-ориентированный, так и процедурный подходы. Большинство PHP-программистов по умолчанию используют последний, поскольку сами веб-страницы обрабатываются именно в процедурном подходе (одни тег, затем другой, затем следующий и т.д.). Код, написанный в процедурном подходе, гораздо проще комбинируется с HTML и, как следствие, программисты зачастую вырабатывают свой собственный стиль, основанный на таком подходе.

Если вы новичок в PHP, то, скорее всего, единственный способ программирования, которым вы пока пользовались - это процедурное. Тем не менее, если вы уже исследовали ресурсы, посвященные PHP, в поисках новых решений и приемов, вы наверняка сталкивались с сообщениями на тему "распухших объектов" (object bloat), или находили различные руководства по написанию объектно-ориентированного кода на PHP. Возможно, вы скачивали библиотеки, которые использовали классы, учились создавать объекты и вызывать их методы. При этом, вполне возможно, что вы никогда до конца не осознавали почему в том или ином случае имеет смысл применять объектно-ориентированный подход.

У обоих подходов есть свои преимущества и недостатки, заставляющие их приверженцев обмениваться незамысловатыми репликами вида "Объекты - это плохо!" или "Объекты - это хорошо!". Данная статья не является попыткой склонить читателя в сторону того или иного подхода, а призваны исследовать преимущества и недостатки каждого.

Вот пример процедурного кода, выводящего строку

<?php 

print "Hello, world."

?> 

Вот пример объектно-ориентированного кода, который делает то же самое:

<?php 

class helloWorld 
  function 
myPrint() { 
    print 
"Hello, world."
  } 

$myHelloWorld = new helloWorld(); 
$myHelloWorld->myPrint(); 

?> 

Сразу отметим, что эта статья не является попыткой дать определение объектно-ориентированному программированию как программированию с использованием классов. Для получение начальных сведений о принципах ООП рекомендуется воспользоваться Googlе. На данный момент существует достаточное количество хороших (и немного плохих) статей, посвященных этой теме.

Кто пишет подобный код?

Для того, чтобы понять каким образом рассматриваемая тема стала причиной многочисленных "религиозных войн" давайте изучим пару экстремальных примеров с обоих сторон. Вначале мы взглянем на "Процедурного Фанатика", а затем на "Объектного Фанатика". Возможно кто-то из этих двоих покажется знакомым и самому читателю.

"Процедурный Фанатик"

"Процедурный Фанатик" всегда подвергается критики со стороны своего учителя по информатики за плохое использование абстрактного подхода при выполнении своих заданий. Приводимый в оправдание аргумент: "Но ведь оно работает!" так и не улучшает его отметок. В дальнейшем, такой программист избирает в качестве предметной области такие задачи как написание драйверов, файловых систем и других низкоуровневых программ, где его акцент на скорости и лаконичности приносит ему признание.

Экстремальными примерами "Процедурного Фанатика" являются полное отрицание объектов и критика абстракции как таковой. Такие программисты всегда хотят сделать свой код быстрым, не заботясь особенно о тех, кто будет его читать позднее. Очень часто они рассматривают процесс программирования как соревнование, а не командную разработку. Они любят участвовать в заковыристых конкурсах по написанию кода. Их любимыми языками наравне с PHP являются C и Assembler. В PHP они могут заниматься написанием модулей PECL, способствуя тому, чтобы код был рациональным и эффективным.

"Объектный фанатик"

Объектный фанатик совсем недавно открыл для себя ООП и теперь готов применять его везде! Он не до конца осознает проблему производительности при используемом им подходе. Иногда кажется, что концепции абстрактного дизайна для него гораздо важнее самого кода. Возможно такой програмист имеет хорошие шансы на карьеру менеджера проектов или технического писателя.

Объектные фанатики очень любят упрекать процедурных в том, что без абстракций мир до сих пор программировал бы с помощью нулей и единиц. Они известны так же тем, что говорят на псевдокоде. Экстремальным примером таких программистов являются люди, использующие объекты, забывая о производительности и не щадящие элегантности и даже читаемости собственного кода. Их любимыми языками программирования помимо PHP являются Java и Smaltalk. В PHP сообществе они как правило занимаются разработками модулей PEAR, создавая хорошо документированный и легко сопровождаемый код.

"Эти двое никогда не встретятся"

Почему страницы форумов забиты предвзятыми высказываниями? Дело в том, что уникальный опыт, накапливаемый вами в процессе работы над проектом и, как следствие, выработанная им "ваша философия" предопределяют путь поиска новых идей. Как программисты, мы должны постоянно остерегаться подобных предубеждений, оставаясь открытыми для изучения новых вещей. Как информатики (computer scientists) мы должны уметь отбрасывать эти предубеждения, чтобы находить лучшие методы решения проблемы в конкретной ситуации.

Каковы ваши цели?

Задумайтесь на мгновенье над тем, какие цели стоят перед вами при написании той или иной PHP программы. Часто эти цели выражаются очень туманно, иногда указываются в задании. Вы можете придерживаться этих целей в любом из своих проектов. Одна из них, за которую особо ратует автор этой статьи - элегантность. Определение элегантности не будет дано здесь, так как эта тема скорее подходит для отдельной статьи. Есть и другие более абстрактные цели, которые не всегда сопоставимы с теми решениями, которые хороши для проекта - для конкретных задач, стоящих перед вами. Фактически, такие цели могут быть в данном случае теми самыми предубеждениями, о которых говорилось ранее.

Абстрактные цели

  • Предложить решение, содержащее как можно меньше строчек кода
  • Думать о проблеме на уровне проблемы

Звучит великолепно, не правда ли? Но что понимается под выражением "как можно меньше строчек кода"? Учитываются ли комментарии? Должны ли мы соединять весь код в одну строчку, разбивая ее точками с запятой? А как насчет фигурных скобок? Некоторые любят оставлять для них отдельную строку. Судя по поставленной цели, все это будет прямыми нарушениями задания. Как насчет "решения на уровне проблемы"? Означает ли это, что для каждой концепции, используемой в решении, мы должны создавать класс? Или нам необходимо размещать каждую подзадачу в отдельный файл и создавать сложное дерево, отображающее реальную структуру? Вот оно - файл и класс на каждую мысль!

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

Практические цели

Решением проблемы является такой подход, при котором в первую очередь рассматриваются практические цели, стоящие перед проектом. Каковы же цели конкретного проекта? Вот несколько вариантов:

  • Писать это быстро, выпускать (release) часто.
  • Заставить это работать настолько быстрее, насколько возможно.
  • Сделать это простым в сопровождении, распространении и расширении
  • Опубликовать программный интерфейс (API)

Первые две цели больше тяготеют к процедурному подходу, тогда как последние две - к объектно-ориентированному.

Какой подход наиболее правильный?

Теперь давайте попробуем оценить практические преимущества каждого метода.

Процедурный подход

Основным аргументом в пользу процедурного подхода является тот факт, что PHP является интерпретатором. Это означает, что в отличие от многих других языков он не компилируется в бинарный код для исполнения, а интерпретируется и исполняется "на лету". Это язык сценариев и каждый сценарий хранится как обычный текст (естественно, за исключением инструментов компилирования Zend).

Еще одним аргументов против использования объектно-ориентированного подхода в PHP4 является тот факт, что подобная функциональность не была полностью продумана в этой и более ранних версиях. Если послушать Расмуса (Расмус Лердорф - автор первых версий PHP), то получается, что поддержка ООП была добавлена уже после окончания основных работ над ядром языка. Из этого следует, что использование объектов в PHP4 не настолько рационально и эффективно, как могло бы быть. Как бы то ни было, эта ситуация должна измениться с выходом новой версии PHP5.

С использованием процедурного подхода написаны такие популярные приложения как osCommerce и phpMyAdmin. Они появились достаточно быстро и обладают относительно высокой скоростью работы. Оба проекта сильно привязаны к HTML, который без ограничений комбинируется с PHP.

osCommerce

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

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

phpMyAdmin

phpMyAdmin напрямую использует только один класс: Mimer SQL Validator, который в случае phpMyAdmin зависит от PEAR пакетов Mail_Mime, Net_DIME и SOAP. Такое решение скорее всего было основано на убеждении: "оно хорошо служит своей цели - давайте его используем". Во всем остальном, похоже, что код приложения написан в процедурном стиле и вновь мы имеем тесное связывание HTML и PHP.

phpMyAdmin - это инструмент, который используется ежедневно. Более того, для простых модификаций, автор статьи поощряет своих клиентов в использовании phpMyAdmin как системы администрирования контента (естественно при соответственном ограничении их прав). phpMyAdmin работает очень хорошо и, учитывая то, что ему приходится делать, он работает очень быстро. Автор часто расширяет phpMyAdmin для некоторых приложений, делая его системой администрирования, усиливая такие его свойства как избранные запросы, для того чтобы клиенты могли быстро и просто создавать выборки и редактировать их. Сам же код должен быть достаточно хорошо сопровождаемым, поскольку с каждым выходом новой версии рассматриваемый продукт развивается все в более и более практичный инструмент.

Процедурный подход - заключение

Процедурные части обоих приложений хорошо документированы. В случае osCommerce, предоставление определенного каркаса для разработки расширений также способствует поддержке и расширению этого продукта. Однако не существует никакого подобия программного интерфейса (API), позволяющего расширить продукт до чего-либо серьезно отличающегося от оригинала.

Потребуется очень много усилий, чтобы превратить osCommerce в бухгалтерское приложение и еще больше, чтобы превратить phpMyAdmin в настраиваемую систему администрирования контента. Тем не менее, ту работу, для которой изначально были созданы эти оба продукта - они выполняют очень хорошо.

Объектный подход

Одним из основных аргументов в пользу объектно-ориентированного подхода является расширяемость и модульность полученного кода. Сам по себе факт программирования в объектно-ориентированом стиле не сможет закомментировать код или создать документацию, но он может подвигнуть вас к этому действию. И однажды стремление к расширяемости создаваемого вами кода может привести вас к написанию настоящего программного интерфейса (API) для вашего приложения.

PHP5 обещает сделать процесс объектно-ориентированного программирования гораздо более приятным. С известной долей иронии можно сравнивать новую версию с выходом "Java 2", поскольку она включает в себя ряд таких свойств, как интерфейсы, ссылочная модель объектов и структуры try/catch, уже зарекомендовавших себя в мире Java. Но даже для PHP4 и более ранних версий можно найти примеры удачного применения объектов.

Одним из самых удачных автор статьи считает Smarty - систему шаблонов, позволяющих отделять код PHP от контента. Другим полезным примером является свободно распространяемый генератор PDF, полностью написанный на PHP и получивший название FPDF. Оба программных продукта практикуют подход при котором HTML код отделяется от PHP. Особенно важно отметить тот факт, что обе программы могут быть расширены до других полезных приложений.

Smarty

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

 [navigation horizontal separated by " | "

на сайте появится горизонтальный блок навигации, разделенной между собой символами "|". Поскольку Smarty уже обладает очень развитым механизмом отображения данных, содержащихся в переменных, описанный процесс подразумевает всего лишь отображение сложных тегов Smarty в простые директивы для оформления.

Более подробно об этом можно прочесть на http://simpletags.sourceforge.net и http://simplequiz.sourceforge.net/.

Поскольку Smarty представляет собой класс и все его методы хорошо документированы, то его функциональность можно легко расширять. Кроме того

Smarty предоставляет уровень отделения области видимости прочих переменных, используемых в PHP тем, что заставляет передавать шаблоном только те переменные, которые вы собираетесь использовать. Такого рода "экологический надзор за переменными" позволяет создать надежную рабочую связь между дизайнерами, создающими шаблоны и программистами, которые предоставляют для них данные.

FPDF

FPDF - отличный инструмент. Если вы разочаровались в постоянно изменяющемся API к pdflib и не хотите платить за хорошо поддерживаемое приложение, если вы не можете управлять расширениями на той версии PHP, с которой работаете (как это бывает в случае хостинга с общими ресурсами) - задумайтесь над использованием этого свободно распространяемого, полностью написанного на PHP PDF-генератора.[1].

Этот класс хорошо документирован, включая массу приятных примеров того как создавать и располгать в документе текст и графику. Для уже упомятуго сайта онлайнового обучения автор использовал FPDF для динамического создания сертификатов окончания курсов, с использованием шрифтов семейтсва True Type и графики с разрешением 300 dpi. Те дополнительные секунды, требующиеся для вызова класса и исполнения операций с PDF практически не заметны на фоне того, что сам PDF-файл иногда требует нескольких минут для скачивания. Ввиду этого, на низкоскоростных соединениях дополнительное время, затраченное на создание и отправку PDF-файла порой оказывается меньше, чем скачивание статического аналога.

Кроме того, поскольку FPDF основана на объектно-ориентированном подходе - она может быть расширена. Многие методы до конца не реализованы и просто существуют в качестве структуры, которая может быть расширена вами, например для создания собственных колонтитулов (шапок) в отдельном классе.

Объектный подход - заключение

Как Smarty так и FPDF предоставляют хорошо документированный интерфейс для расширения их основного класса. Заключение всех методов и данных в класс в данном случае является хорошо продуманным решением. Подобной функциональности можно было бы достичь, используя обычные функции и глобальные переменные, но ее трудно было бы расширить впоследствии. Кроме того невозможно было бы создавать несколько сущностей с одинаковой функциональностью, как это можно делать с объектами. Такие объекты могут задавать стиль PDF или HTML документа, который вы создаете. Таким образом вы можете публиковать одни и те же данные в различных форматах.

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

Когда и что применять?

Мы рассмотрели примеры применения робких подходов для разных целей и познакомились с эффективными примерами применения этих подходов в реальных приложениях. Что же делать если ваши цели требуют обоих подходов?

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

Кроме всего прочего, распределите ваши цели по степени приоритета. Взвесьте их. Если вы будете использовать практический подход от проекта к проекту для определения эффективности объектно-ориентированного или процедурного кода, вам гарантировано непредвзятое и подкрепленное вашим опытом решение. И помните: используя PHP, у вас всегда есть шанс. Вы всегда сможете комбинировать оба подхода.

Почему оба подхода необходимы?

Возвращаясь к фанатам объектного и процедурного подходов, мы не забудем отметить и их заслуги.

  • Поблагодарим "объектных" программистов за практичность и расширяемость Smarty и FPDF
  • Поблагодарим "процедурных" программистов за быстроту и надежность функционирующие osCommerce и phpMyAdmin.

На самом деле эти признания идут гораздо дальше - к основам PHP.

Как PECL так и PEAR уже снискали себе достаточно славы и критики. Оба проекта могут служить хорошей иллюстрацией различий между процедурным и объектно-ориентированным программированием.

PECL предоставляет расширения для PHP, написанные на C, с использованием процедурного подхода и ориентированные на скорость и лаконичность кода. Зачастую это перенос существующих приложений с лицензией LGPL (Lesser General Public License). Таким способом за несколько лет в PHP была добавлена масса интересных функций. Кроме того, не стоит забывать, что и сам PHP написан на C.

PEAR способствовал появлению массы полезных и интересных классов, начиная от создания Excel-таблиц и заканчивая изменением DNS-записей. Используя библиотеки PEAR, вы экономите себе массу времени и можете создавать функциональность, которая способна заставит вас воскликнуть: "Я даже не знал, что PHP может такое!"

Заключение

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


For comment register here
   2004-08-07 22:13
Думать надо прежде всего о производительности программиста, а не программы.
А писать об объектах, как автор, это все равно, что делить скрипты на использующие ассоциативные массивы и не использующие.

Большинство задач веб-приложений имеет линейный характер.
запрос->внутренние преобразования данных->создание страницы результата,
процедурный подход хорошо справляется с подобными задачами в простых случаях.

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

   2004-10-26 13:04
Хорошая статья!
Я, собственно, искал программистов для переделки oscommerce и натскнулся случайно на эту статью.
Ну что же, согласен автором, но собственно это не секрет что оба подхода имееют право на жизнь. Тем более что оба хорошо себя зарекомендовали в PHP.
Хотелось бы более тонкой аналитики для конкретных решений.
Очень частно перед программистами встает вопрос и выборе метода программирования, и ошибка в таком выборе чревато большими потерями как ресурсов так и времени. Как я уже сказал, оба метода хороши, но уметь использовать их вместе, умело разделяя их в контексте конкретного проекта, это уже из области искуства.
Удачи всем!

   2004-11-03 09:04
На мой взгляд, дело даже не в скорости работы скрипта (в конечном итоге, на PHP не пишутся действительно сложные системы, требующие больших затрат ресурсов), а в том, будет ли впоследствии расширяться продукт или нет.

Если бы я делал систему, которая, будучи создана, никонда не будет изменяться и останется в первоначальном виде, я бы выбрал процедурный подход.
Если же я не уверен в этом и преполагаются солидные изменения как в HTML-коде, так и в скриптах, то я выберу объектный подход с использованием шаблонов.

То есть, на мой взгляд, главная задача, которую надо ставить при выборе подхода, - это дальнейшая судьба проекта.

Описание преимуществ и недостатков объектно-ориентированного и процедурного подходов. Объекты, ООП, процедуры, объектный подход, процедурный подход, преимущества, недостатки, примеры, применение объектов, объектная модель

 
 
 
    © 1997-2008 PHPClubTeam
[]