19.08.2019     93

Как-то раз я делал сравнение производительности xPDO с Propel 2. Сравнение было вполне корректным, т.к. обе библиотеки используют паттерн ActiveRecord. Но использование данного паттерна, на мой взгляд, и является основной причиной проблем с производительностью xPDO.

В ActiveRecord объекты сохраняются примерно одинаково:

$object = $xpdo->newObject('modResource');
$object->set('pagetitle','Harry Potter');
$object->save()

Это выглядит очень эстетично, но только до того момента пока мы не задумываемся как это устроено внутри. Как можно догадаться, вся логика общения с базой данных при изменении и сохранении описана в этом объекте. Каждый объект в xPDO является экземпляром класса xPDOObject (xPDOSimpleObject наследуется от этого класса). Можно посмотреть сколько в этом классе строчек кода - более 2500. В 3-й версии xPDO я не заметил больших изменений. А вот в Propel 3 уже добавили Data Mapper. Кстати, разработчики Doctrine тоже давно отказались от ActiveRecord. Думаю, важной причиной перехода на Data Mapper также является то, что этот паттерн соответствует принципам SOLID.

В Data Mapper объекты сохраняются в БД примерно так:

$newUser = new User();
$newUser->setName('Ivan');
$objectManager->persist($newUser);
$objectManager->flush();

На много ли это сложнее чем в ActiveRecord? Думаю, нет. При этом логика взаимодействия с БД находится в отдельном классе, что является положительным фактором не только с точки зрения архитектуры, но и с точки зрения производительности.

Конечно, в xPDO есть возможность не использовать методы getObject() и getCollection(), которые создают тяжеловесные объекты, при выборке данных из БД. Но кроме выборки нам нужны валидация, сохранение, обновление, рендеринг и т.д., а это всё завязано на объектах xPDOObject.

Я бы не хотел, чтобы этот пост рассматривался как ещё один гвоздь в крышку гроба MODX, в котором используется xPDO. Но, думаю, разработчикам данной CMS было бы полезно подумать в этом направлении.