Надеюсь материалы опубликованные в данной статье не покажутся слишком очевидными или покушением на оскорбление чувств «верующих», и уж тем более никто не воспримет название статьи слишком буквально как «ориентированное программирование». В любом случае данная статья это попытка поделиться личным опытом, а не пропаганда своей точки зрения.
Немного предыстории: я человек консервативный, все изменения я принимаю «в штыки», но если преимущества очевидны, то охладив пыл я стараюсь свыкнуться с «новшеством». Так было и с ООП когда в процессе освоения PHP я с ним столкнулся. Сперва я воспринял классы и создание объектов как чистый оверхэд (и не сказать что это было ошибкой), но в процессе знакомства та «структурированность» и «порядок», которые давало ООП сделали из меня религиозного фанатика ООП (и MVC, но сейчас не об этом).
Примерно в то же время я сменил работу и попал в команду разработчиков где многофункциональный портал компании был написан на чистом PHP (без использования фреймворков), и каждый воротил как может. Безусловно там были разработчики высокого уровня, но времени на рефакторинг существующего кода давали очень мало, основное время уходило на расширение функционала, и тем более речи быть не могло об изменении структуры и о том чтобы переписать все с нуля. Там были и примеры «плохого ООП», например в клиентском коде (некоторое подобие контроллера, если проводить аналогию с MVC) в самом начале создавались абсолютно все объекты которые будут задействованы в коде (еще и предварительно инклудились, без какой либо надежды на автолоадер), и что немаловажно, к ним применялось некоторое подобие шаблона делегирования: создавался объект mysqli и присваивался свойству sql каждого объекта. Можно только представить сколько лишних действий в пустую и какой перерасход оперативной памяти происходит.
Вот мой базовый пример:
class A{
public function __construct(){
}
public function doSomething(){
}
public static function someStatic(){
}
}
class B{
public function __construct(){
}
public function doSomething(){
}
public static function someStatic(){
}
}
echo((memory_get_usage()/1024)."Kb"); //результат: 211.90625Kb
Эти замеры только чтобы оценить вес «пустой страницы», то есть тут мы еще не создали ни один объект и не воспользовались ни одним методом из класса.
Теперь давайте посмотрим чего нам будет стоить создание таких «бесполезных» объектов и вызова их методов:
$a=new A;
$a->doSomething();
$b=new B;
$b->doSomething();
echo((memory_get_usage()/1024)."Kb"); //результат: 214.15625Kb
Как видим разница не впечатляющая, но это при условии что и объект и метод по сути ничего не делают вообще. Как известно, в PHP есть статические методы и свойства которые принадлежат классу, в отличие от обычных методов и свойств которые принадлежат объекту данного класса. Наши классы содержат как раз такие методы (совпадение? — не думаю), функционал у них точно такой же как и у обычных методов этого класса, поэтому фактически мы можем сделать те же действия минуя создание класса:
A::someStatic();
B::someStatic();
echo((memory_get_usage()/1024)."Kb"); //результат: 212.6171875Kb
Наверно сравнение на «сверхмалых» числах не дает полной картины, но это тот самый оверхэд от которого можно отказаться. Я не люблю создавать объекты, и именно об этом эта статья, я стараюсь по максимуму использовать статические методы и свойства. Причина не любви к работе с объектом (при передаче другому методу), в том что у меня есть фобия что он не тот за кого себя выдает, конечно Вы можете проверить его на принадлежность к тому или иному классу через instanceof, но чтобы не было непредвиденных результатов лучше проверить его содержимое, что может оказаться муторной работой, и проще собирать нужную структуру по ходу исполнения скрипта (дальше прошу отнестись с пониманием) используя преимущества структурированной системы классов, но не создавая объектов в клиентском коде, по сути в псевдопроцедурном стиле. Но вернемся к коду.
Если Вас волнует вопрос выполнения функционала конструктора, то это реализуется через self:
class A{
public $prop;
public function __construct(){
$this->prop='test';
}
public function doSomething(){
}
public static function someStatic(){
return new self();
}
}
$a=new A();
echo $a->prop; //test
echo((memory_get_usage()/1024)."Kb"); //результат: 211.9140625Kb
echo A::someStatic()->prop; //test
echo((memory_get_usage()/1024)."Kb"); //результат: 211.5703125Kb
Самые внимательные и находчивые конечно предложат, что то типа (и будут правы):
echo ((new A())->prop); //test
echo((memory_get_usage()/1024)."Kb"); //результат: 211.53125Kb
Но это лишь из-за того что примеры исполнения слишком утрированы, а какой-то реализации в подобной схеме можно добиться лишь если метод возвращает этот объект ($this).
Весь этот ход мыслей только для того чтобы объяснить что не обязательно создавать объекты в ООП, и можно обходиться без них экономя память (как в принципе без любых лишних присвоений), если конечно это не оправдано архитектурой приложения, или паттерном, и конечно не стоит даваться в крайности, если Вам нужен объект — создайте объект, иногда без этого не обойтись. Но если результатом каких то действий является объект, то почему бы сразу не начать с ним работать?