Pull to refresh

ООП-билдер «массивных» параметров

Reading time 3 min
Views 8.8K
Многие фреймворки любят магию и сложные многоуровневые массивы для передачи параметров. Что первое, что второе — зло с точки зрения истинно-ленивого программера, который любит IDE и доки всегда под рукой, а не тыкать в интернет/тело вызываемого метода. Мы можем победить это, как образец взяв параметры метода из одного фреймворка и создав ООП-билдер.

Что такое «массивный» параметр?


Это параметр, который определённая система форсит нас, чтобы он был в виде массива определённой структуры. Это не YAML и не XML, а именно associative array определённой сложной структуры.

Зачем?


Дёготь «массивных» параметров

Мы не имеем документации здесь и сейчас. Мы можем ошибиться в написании ключа и не поймём это сразу. Для того, чтобы добавить ключ, который мы не знаем/забыли, надо открывать доки. Мы же не используем голый SQL, где его вполне легко можно заменить AR`ами или теми же query builder`ами в 90% случаев банальных CRUD-операций? В общем и целом голые массивы более компьютеро-ориентированы, нежели удобны для сопровождения людьми.

Откуда они подлецы вообще появляются?

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

Авторитеты говорят в тему
Пишите программы в первую очередь для людей и лишь во вторую — для компьютеров.
Стив Макконнелл
Что в итоге повышает нам понятность, облегчает изменения и отладку. Даже когда мы работаем в одном проекте — переключение контекстов имеет место быть.

А как же оверхэд на все эти ваши ООПы?

Вы конечно же скажете — а нафик нам на продакшене оверхед? Явно же голый массив быстрее чем некий билдер. На это можно ответить, что люди изобрели кэширование, tmpfs, билды и прочее — это не есть настоящая проблема. Например, мало кто в здравом уме отдаёт непожатые js/css или не использует opcode cache на загруженном ресурсе. Так что и здесь вполне возможны различные хуки деплоймента, которые генерят готовые файлы или кэширования в стиле:

$result = $someConfig->getFromCache(__FILE__ . __LINE__) or $result = $someConfig->...->get();

И всё таки

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

Как выглядит?


// Ручной режим -- так ожидает некий метод в системе
$conditions = array(
    'conditions' => array(
        'Model.field' => 123,
        'Model.field5 BETWEEN ? AND ?' => array(5, 5),
        'Model.field8 NOT LIKE' => '%8%',
    ),
    'recursive'  => 1,
    'fields'     => array('Model.field1', 'DISTINCT Model.field2'),
    'order'      => array('Model.created', 'Model.field3 DESC'),
    'group'      => array('Model.field'),
    'limit'      => 100,
    'page'       => 1,
    'offset'     => 10,
    'callbacks'  => true,
);

// ООП-массив-билдер -- даёт точно тот же результат, но мы получаем описание всего здесь же на месте
$conditions = $this->findParams
    ->conditions
        ->is('Model.field', 123)
        ->between('Model.field5', 5, 5)
        ->notLike('Model.field8', '%8%')
        ->up()
    ->recursive(1)
    ->fields('Model.field1', 'DISTINCT Model.field2')
    ->order('Model.created', 'Model.field3 DESC')
    ->group('Model.field')
    ->limit(100)->page(1)->offset(10)
    ->callbacks(true)
    ->get()
;


Рис. 1. В авто-дополнении мы видим все возможные параметры и здесь же — их описания. В yaml`ах, xml`ях, raw-массивах у нас этого всего нет.

Как устроено и где пощупать?


Исходники на гитхабе: главный модуль и модуль для CakePHP. Пример для CakePHP взят просто как первый попавшийся. Это не query-builder, а именно array-param-builder. Что-то типа wrapper`а над монструозным параметром одного из методов.
Примеры кода в тестах, которые можно запустить phpunit`ом из корня проектов:

Расширение возможно для любой предметной области — см. CakePHP-модуль как образец. Текущие версии далеки от production-качества и являются больше концепцией, нежели готовым инструментом. Однако инфраструктура и точки расширения присутствуют.

Changelog


title: Конфиг с человеческим лицом? Билдер! ООП-билдер «массивных» параметров
content: Ввёл понятие «массивный» параметр, убрал понятие «конфиг»
Tags:
Hubs:
+9
Comments 33
Comments Comments 33

Articles