Как стать автором
Обновить

Комментарии 33

> если метод не возвращает функционально необходимый результат, пусть вернет $this.
Да, это стало популярно, особенно после JQuery =) Аналогично и я делаю.

А конфиги храню в обычных массивах, т.к. для каждого такого массива потом можно будет сгенерировать форуму для изменения через браузер. И сохранять в массив через var_export() можно.

Подгружаю так:

public function configure($id)
{
if(isset($this->_config['components'][$id]))
{
foreach ($this->_config['components'][$id] as $k => $v)
{
$this->_components[$id]->$k = $v;
}
unset($this->_config['components'][$id]);
}

}
С объектом удобнее работать, как правило, плюс в переопределенные методы можно навешать дополнительную логику, да и вообще выглядит эстетичнее, вроде как.
Да, в этом плане удобнее, но я предпочитаю никакой логики в конфиг не вводить =) А то какой же это конфиг тогда =) Но на вкус и цвет все фломастеры разные =)
Тем кто ставит минусы: я не храню все настройки в массивах =) В них только базовые вещи: логин/пароль к БД, дефольный контроллер, пути.
Мда, DSL на пхп выглядит весьма удручающе.
Как говорится, а что на нем выглядит иначе?
Щас Вам накидают говнеца, знайте.

А вааще real hard guru поиксу на чём у него DSL. DSL — это концепция, которая как раз позволяет ездить по дорогам языков на своём удобном велосипеде с удобнейшим сиденьем — у кого-то седушка, а у кого-то и массажёр простаты.

Я тут на досуге осознал, что и BAT-ники под DOS`ом можно писать с IF`ами и с типа переменными и даже циклами, но это к делу не относится :)

Эта же концепция близка в Literate Programming by тов. Кнут, но по мнению тов. МакКонелла она не всех вставляет.
Real Programmer can write Fortran programs in any language, ага.
Прочитал название вашей группы, как «ТерАкт» )
наверное имелось в виду

$config = new Config_DSL_Builder()->load('config.php');

?
или у нас есть

class Config_DSL
{
  public static function Builder()
  {
    return new Config_DSL_Builder();
  }

}
Да, так и есть (там еще на самом деле есть список параметров со значениями по умолчанию), у каждого модуля определен соответствующий класс, в нем, как правило, фабричные методы и, иногда, упрощенный процедурный фасад (как в perl).
Статические фабричные методы, кстати говоря, тем еще хороши, что позволяют создать объект и вызвать его метод в одном выражении (по крайней мере в 5.2 «new Config_DSL_Builder()->load('config.php');» не сработает, а «Config_DSL::Builder()->load()» — сработает).

В этом смысле по соотношению объем кода/полезность лидирует функция:

function with($x) { return $x; }


Тогда можно:

with(new Config_DSL_Builder())->load(...);
а что делает for? Вроде цикл, но непонятно какой…
В каком примере?
for_campaign($campaign_id)->
это, видимо не цикл, а элемент ассоциативного массива…
было бы полезно добавить удобные методы в статью, если не лень конечно.
Кстати посмотрите мой перевод описания Phemto — библиотеки для Dependency Injection, тоже удобный подход для API:

часть1: habrahabr.ru/blogs/php/64061/
часть2: habrahabr.ru/blogs/php/64078/
Это не DSL, это «мы все запихнули в chaining, и автоматически получили новый язык. Он правда не короче РНР, но зато chaining».

Особенно «end()->end()->end()» доставляют.
DSL не должен подменять базовый язык, он должен его расширять.
Ну, исходный язык такой, что особо не размахнешься, увы. В случае Google AdWords получается, тем не менее, реально короче, там для многих типовых задач альтернатива — написание длинных унылых скриптов с большим количеством промежуточных объектов. Применять, разумеется, следует в очень разумных пределах.

Для расширения языка есть, к сожалению, крайне мало возможностей, в 5.3 получше за счет переопределения статических методов, но все равно это не радикально лучше. Игрушечный язык — игрушечные DSL, как то так :(
Посмотрите Phemto, на который вам дали ссылку. Это DSL. Они не пытаются все запихнуть в одну цепочку. Они, о боже, используют присваивания. :)
Ничего не имею против присваиваний. Я же не призываю _все_ приложение так писать.

Теперь по поводу DI. Это немного из другой оперы, как мне кажется. В случае DI у нас есть некий интерфейс и различные его реализации, контейнер позволяет управлять тем, какая конкретная реализация используется в том или ином случае. Собственно, поэтому это так востребовано в Java: стандартная спецификация определяет интерфейсы и все им следуют, в т.ч. различные вендоры. В случае PHP, кстати, никаких общих интерфейсов, кроме SPL, как то особенно и не сложилось.

Мы же просто строим систему связанных экземпляров объектов, реализация которых однозначна, во многих случаях это несложные value objects с минимальной логикой. Мы же не будем описывать схему роутинга адресов страниц, например, с помощью Dependency Injection.
Я не про DI, я про Phemto, как пример хорошего DSL.
Имхо, вы перестарались. И с конфигом (конфиг можно сделать массивом, .ini-, YAML- или если вы фанат, XML-файлом), и со вторым примером — появляется ненужное усложнение, к тому же, если не знаешь внутреннего устройства объектов, то вообще ничего не понять. Короче, одни недостатки.

Переписывать foreach () через методы объекта  — нафига??? В php уже есть foreach(). К тому же в вашем foreach() можно вызывать только методы своего же объекта, в отличие от нормального (сделали бы тогда уж через коллбеки/замыкания). Хотите сделать foreach() — используйте итераторы или массивы, не изобретайте велосипед.

Выглядит мерзко (не обижайтесь), к тому же напрягает иcпользование __get()/__Set()/__call() (которые, я считаю, не стоит использовать кроме особо крайних случаев).

И еще неоправданное использование ob_*() (что естественно, тоже зло) заметил я в коде.
1. ini, XML и YAML — полностью статичны, иногда выгодно иметь возможность что-то в конфиге вычислить. Кстати, встроенному парсингу ini-файлов в PHP вообще ничего нельзя доверить :);

2. Второй пример — там полное практически делегирование вызовов конструируемым объектам, этот набор можно создать и традиционным образом, API допускает использование и без билдера, вообще использование билдеров — всегда опциональная надстройка над традиционным API;

3. ob_* — перестраховка от лишнего текста в конфиге, можно и не использовать, вообще говоря;

4. foreach — это не переписывание штатного foreach, это выполнение дочерних задач в контексте родительской. Альтернатива — длинные скрипты с большим количеством промежуточных присваиваний и циклов foreach, выглядит довольно уныло.

5. Про __get(), __set() и __call() — почему вы так считаете?
1. Ну если строго подходить, на то он и конфиг, чтобы ничего в нем не вычислять.

2. При чем тут делегирование, выглядит-то страшно и запутанно, ошибку и не заметишь. Парсер предупредит о незакрытой скобке, а о пропушенном end()?

3. Что значит перестраховка от лишнего текста? Откуда он там возьмется?

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

Значит ваши объекты кривые, раз их нельзя нормально использовать без извратов. Итераторы зачем придуманы? Замыкания?

> Про __get(), __set() и __call() — почему вы так считаете?

Потому что мощный инструмент, стоит использовать с осторожностью, а не всюду без разбора. Потому что усложняет понимание, когда у объекта нет метода или свойства, а к нему обращаются. И кстати, если отказаться от вашего DSL, делегирование, и эти методы окажутся ненужными :)
По поводу __get() etc — я думал вы про производительность скажете.

Что касается отсутствия свойства у объекта — у нас это решается наличием стандартных интерфейсов для объектов, которые поддерживают динамические свойства. Называется Core_PropertyAccessInterface, его поддержка гарантирует одновременную реализацию __get, __set, __isset и __unset, реализация интерфейса также подразумевает следование определенной модели обработки этих свойств, в частности, генерацию исключений, если это нужно.

На и по поводу последнего тезиса — если это мощный инструмент, чего ж его не использовать? В случае PHP он закрывает массу вопросов, как минимум:

1. честную инкапсуляцию свойств свойств объекта без необходимости реализации массы тупых методов доступа типа get{Property}/set{Property};
2. поддержку read-only свойств опять же без get{Property};
3. вычисляемые свойства.

Можно, в принципе, писать на PHP как на классической Java — с access-методами, бинами и т.д., но тогда лучше сразу на Java, где все стандартно, строго типизировано и не надо ничего изобретать. Посмотрите исходники Shindig, например, такой стиль выбран намеренно (портировали с Java) — на это без слез не взглянешь.
Вы знаете более удачные методы реализации рефлексии в PHP? Быть может, поведаете?

А по поводу foreach меня захватил сильнейший приступ смеха. Скажите об этом людям, которые изучают функциональное программирование, и они покажут вам традиционный жест с пальцем у виска. Это map. А замыкания (я надеюсь) автор не использовал в целях обратной совместимости. Хотя можно было бы и перегрузку сделать.
> Скажите об этом людям, которые изучают функциональное программирование, и они покажут вам традиционный жест с пальцем у виска.

Php это язык функционального программирования? Это изврат, имитировать таким образом отсутсвующий функционал, не дай бог кому такой код разбирать придется, что он скажет, а? А ошибку или пропущенный метод в огромном chain слабо найти?

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

В PHP в этом смысле вообще весело, от опечаток может гарантированно защитить только 100% покрытие юнит-тестами :)
Хорошая, годная статья. До этого ещё надо дорасти, поэтому не держите зла на людей, которые здесь подымают флейм. Когда-нибудь они тоже поймут.

Кстати, я какбы намекну, что jQuery, наверное самый известный в интернетах chaining pattern, появился не случайно.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий