Pull to refresh

ООП без «О»

Reading time3 min
Views9.4K

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


Немного предыстории: я человек консервативный, все изменения я принимаю «в штыки», но если преимущества очевидны, то охладив пыл я стараюсь свыкнуться с «новшеством». Так было и с ООП когда в процессе освоения 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).


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

Tags:
Hubs:
-28
Comments66

Articles