X   Сообщение сайта
(Сообщение закроется через 2 секунды)

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Fluent interface (текучий интерфейс)
Djadka
сообщение 2012-04-09, 19:33
Сообщение #1
Любитель
Иконка группы

Группа: Eleanor user
Сообщений: 463
Регистрация: 2010-10-17

Репутация:   нет  
Всего: нет


Интересует вообще все за и против данного подхода в PHP, так же скорость работы и оптимальность? В Элеоноре данный подход не реализован, хотя в некоторых местах был бы очень даже хорош, например в шаблонизаторе.
Перейти в начало страницы
+Цитировать сообщение
scanread
сообщение 2012-04-09, 20:02
Сообщение #2
Любитель
Иконка группы

Группа: Пользователи
Сообщений: 227
Регистрация: 2011-07-02

Репутация:   нет  
Всего: нет


Djadka, а подетальней можно, что это такое и с чем его едят? А то обсуждать то, о чем большинство не слыхало - не имеет смысла... Какие +/- и т.д. и т.п.?
Перейти в начало страницы
+Цитировать сообщение
Skyff
сообщение 2012-04-09, 20:51
Сообщение #3
Опытный
Иконка группы

Группа: Eleanor user
Сообщений: 928
Регистрация: 2009-02-08
Из: Литва

Репутация:   нет  
Всего: 4


Ну да было бы неплохо немного информации получить.
Перейти в начало страницы
+Цитировать сообщение
Djadka
сообщение 2012-04-09, 21:11
Сообщение #4
Любитель
Иконка группы

Группа: Eleanor user
Сообщений: 463
Регистрация: 2010-10-17

Репутация:   нет  
Всего: нет


Википедия
Это общая информация, на данной технологии или подходе реализовано много ORM библиотек да и не только ОРМ. Где что читал и из хабры и ещё были какие то источники, везде мнение расходилось, кто к чему привык, а вот на счёт оптимальности использование и ресурсоёмкости не кто не что не сказал. Вот интересует мнение, кто с чем сталкивался.
Перейти в начало страницы
+Цитировать сообщение
KDesign
сообщение 2012-04-09, 23:55
Сообщение #5
Любитель
Иконка группы

Группа: Eleanor user
Сообщений: 153
Регистрация: 2009-09-18
Из: Екатеринбург

Репутация:   нет  
Всего: нет


хм..интересно,спасибо! есть повод для размышлений,
похоже,очевидно, что нагрузка будет немного больше, чем в простом ООП.
Но, я все же за обычный ООП АПИ )
Перейти в начало страницы
+Цитировать сообщение
Djadka
сообщение 2012-04-10, 0:31
Сообщение #6
Любитель
Иконка группы

Группа: Eleanor user
Сообщений: 463
Регистрация: 2010-10-17

Репутация:   нет  
Всего: нет


Бытует мнение что меньше будет нагрузка... Вот надо бы мнение бывалых.
Перейти в начало страницы
+Цитировать сообщение
Гость_wizard993_*
сообщение 2012-04-10, 17:15
Сообщение #7



Гости





scanread, Основная идея в том, чтобы возможна была такая конструкция:
$SomeObject = (new SomeClass)->Method1($params_for_func1)->Method2($params_for_func2)->...->MethodN($params_for_funcN);


Для этого должна быть реализована примерно такая архитектура класса:


class SomeClass
{
    public function __construct()
    {
        return $this;
    }

    public function Method1($params_for_func1)
    {
        /*
            Тело функции...
        */
        return $this;
    }

   public function Method1($params_for_func2)
    {
        /*
            Тело функции...
        */
        return $this;
    }
    
    /*
        ...
        Ещё какие-либо функции
        ...
    */
    public function MethodN($params_for_funcN)
    {
        /*
            Тело функции...
        */
        return $this;
    }
}


Чуть по-подробней

Тоже удивлялся, почему Александр не использовал Fluent Interface.

Если в оригинале написано так:

$Lst=Eleanor::LoadListTemplate('table-form');
		$em=$v['values']['email'] and !$v['values']['name'];
		return self::AcMenu($handlers).($v['error'] ? Eleanor::$Template->Message($v['error']) : '')
			.'<form method="post">'
			.$Lst->begin()
			.$Lst->head($lang['reminderpass'])
			.$Lst->item(array($lang['enteryl'],Eleanor::Edit('name',$v['values']['name'],array('tabindex'=>1)).'<br /><a href="#" class="small" onclick="return ChangeLogEm()">'.$lang['fogotname'].'</a>','tr'=>array('id'=>'tr-name','style'=>$em ? 'display:none' : '')))
			.$Lst->item(array($lang['enterem'],Eleanor::Edit('email',$v['values']['email'],array('tabindex'=>2)).'<br /><a href="#" class="small" onclick="return ChangeLogEm()">'.$lang['remindname'].'</a>','tr'=>array('id'=>'tr-email','style'=>$em ? '' : 'display:none'),'descr'=>$lang['notnoem']))
			.($GLOBALS['Eleanor']->Captcha->disabled ? '' : $Lst->item(array($lang['captcha'],$GLOBALS['Eleanor']->Captcha->GetCode(),'tip'=>$lang['captcha_descr'])).$Lst-></span></span></span>item($lang['c_code'],Eleanor::Edit('check','',array('tabindex'=>3))))
			.$Lst->button(Eleanor::Button('OK','submit',array('tabindex'=>4)))
			.$Lst->end()
			.'</form><script type="text/javascript">//<![CDATA[
			function ChangeLogEm()
			{
				$("#tr-email,#tr-name").toggle();
				return false;
			}
			//]]></script>';


То с использованием "текучих интерфейсов" было бы примерно так:


$Lst=Eleanor::LoadListTemplate('table-form');
		$em=$v['values']['email'] and !$v['values']['name'];
		return self::AcMenu($handlers).($v['error'] ? Eleanor::$Template->Message($v['error']) : '')
			.'<form method="post">'
			$Lst->begin()
			->head($lang['reminderpass'])
			->item(array($lang['enteryl'],Eleanor::Edit('name',$v['values']['name'],array('tabindex'=>1)).'<br /><a href="#" class="small" onclick="return ChangeLogEm()">'.$lang['fogotname'].'</a>','tr'=>array('id'=>'tr-name','style'=>$em ? 'display:none' : '')))
			->item(array($lang['enterem'],Eleanor::Edit('email',$v['values']['email'],array('tabindex'=>2)).'<br /><a href="#" class="small" onclick="return ChangeLogEm()">'.$lang['remindname'].'</a>','tr'=>array('id'=>'tr-email','style'=>$em ? '' : 'display:none'),'descr'=>$lang['notnoem']))
			.($GLOBALS['Eleanor']->Captcha->disabled ? '' : $Lst->item(array($lang['captcha'],$GLOBALS['Eleanor']->Captcha->GetCode(),'tip'=>$lang['captcha_descr'])).$Lst->item($lang['c_code'],Eleanor::Edit('check','',array('tabindex'=>3))))
			.$Lst->button(Eleanor::Button('OK','submit',array('tabindex'=>4)))
			->end()
			.'</form><script type="text/javascript">//<![CDATA[
			function ChangeLogEm()
			{
				$("#tr-email,#tr-name").toggle();
				return false;
			}
			//]]></script>';


Хотя пример довольно неудачный, я думаю, что в некоторых случаях такую технологию было бы удобно использовать.

Сообщение отредактировал wizard993 - 2012-04-10, 17:28
Перейти в начало страницы
+Цитировать сообщение
Djadka
сообщение 2012-04-10, 17:59
Сообщение #8
Любитель
Иконка группы

Группа: Eleanor user
Сообщений: 463
Регистрация: 2010-10-17

Репутация:   нет  
Всего: нет


Вот кто то пишет что скорость падает, кто то пишет что наоборот. Вот надо самому будет потестить. А то не понятно вообще.
Перейти в начало страницы
+Цитировать сообщение
Alexander
сообщение 2012-04-11, 5:12
Сообщение #9
Eleanor developer
Иконка группы

Группа: Администраторы
Сообщений: 5 261
Регистрация: 2008-11-11
Из: Николаев
Версия системы: RC5

Репутация:   нет  
Всего: 67


wizard993, я подумаю где в системе такое можно реализовать. Но пока не нахожу таких мест. Ваш пример с шаблонизатором неудачен. Объясняю почему. Каждый метод шаблонизатора возвращает шаблон. Тоесть строку, состояющую из кусочка будущей страницы. Fluent interface хорош для изменения состояния объектов, но при получении данных из них этим методом воспользоваться невозможно. Точнее, можно, но с костылем-финализатором:


$template=$Tplobj->title('Название')->body('тело')->foot('подвал')->GetHTML();


Финализатором здесь служил GetHTML, который в результате возвратит не объект. А строку.

Хотя нет. Все-же возможен вариант и без финализатора. :) Нужно будет применить этот подход. Ушел думать.

Добавлено через 2 минут, 39 секунд:

Djadka, подскажите, где еще можно реализовать данный подход.
Перейти в начало страницы
+Цитировать сообщение
Djadka
сообщение 2012-04-11, 7:44
Сообщение #10
Любитель
Иконка группы

Группа: Eleanor user
Сообщений: 463
Регистрация: 2010-10-17

Репутация:   нет  
Всего: нет


Я в ядре сделал, в классе Db, Eleanor::$Db->Query('',array(),0/*Флаг для возврата тела, для того что бы остальные компоненты были не тронутыми*/)->Fetch_assoc. Это дело в некоторых моментах компактнее, вот только вопрос, как на счёт оптимальности скорость и ресурсоёмкость??? Мне сказали что в данном случае если метод возвращает класс, то создаётся временный свой класс, но опять же в скорости в теории есть прирост. Я знаю один фраемворк он весит 70 метров и работает он только на текучки, летает он быстрее молнии, вот только в этом ли фишка.
Перейти в начало страницы
+Цитировать сообщение
Гость_wizard993_*
сообщение 2012-04-11, 12:36
Сообщение #11



Гости





Alexander, согласен, пример крайне неудачный.
Пока не представляю как реализовать без финализатора :(

Я бы написал что-то типа такого:

class Tpl
{
    private
        $html=[];

    public function Head($title)
    {
        $this->html[] = '<head><title>'.$title.'</title></head>';
        return $this;
    }

    public function Body($content)
    {
        $this->html[] = '<body>'.$content.'</body>';
        return $this;
    }

    public function Final()
    {
        return join("\n",$this->html);
    }

}

Пример обращения:

echo (new Tpl)->Head('Заголовок')->Body('Сгенерированный контент')->Final();


Если есть идеи как избавится от финализатора и/или массива $html, то пожалуйста изложите идею

Цитата (Alexander @ 2012-04-11, 5:12)
подскажите, где еще можно реализовать данный подход.

Ну, например, как вариант абстрагирования SQL-запросов. Где-то видел ваш пост, где вы писали о том, что не могли придумать красивую обёртку для SELECT'а
Ну так вот:

Допустим есть такой запрос:

Eleanor::$Db->Query('SELECT `id`,`sections`,`title_l`,`path`,`multiservice`,`file`,`files`,`user_groups` FROM `'.P.'modules` WHERE `id`='.(int)$Eleanor->modules['ids'][$m].' AND `active`=1 LIMIT 1');


А в случае Fluent Interface:

Eleanor::$Db->Select('id, sections, title_l, path, multiservice, file, files, user_groups')
            ->From(P.'modules')
            ->Where('`id`='.(int)$Eleanor->modules['ids'][$m])
            ->And(`active`=1)
            ->Limit(1);

Естественно всё это парсится, подставляются апострофы и т.п., но принцип, думаю, понятен.

В Zend Framework'е на днях копался, там примерно так и реализуется
(В версии 1.11: \ZendFramework-1.11.11\library\Zend\Db\Select.php)

P.S.
Тут пришло озарение :) В варианте без использования финализатора подразумевается шаманство с __toString() ?

Сообщение отредактировал wizard993 - 2012-04-11, 13:20
Перейти в начало страницы
+Цитировать сообщение
Alexander
сообщение 2012-04-11, 16:44
Сообщение #12
Eleanor developer
Иконка группы

Группа: Администраторы
Сообщений: 5 261
Регистрация: 2008-11-11
Из: Николаев
Версия системы: RC5

Репутация:   нет  
Всего: 67


Цитата (Djadka @ 2021-07-30 10:57)
Я в ядре сделал, в классе Db, Eleanor::$Db->Query('',array(),0/*Флаг для возврата тела, для того что бы остальные компоненты были не тронутыми*/)->Fetch_assoc.

Зачем? Там уже и так все было реализовано. Query возвращает объект Result, который без дополнительных плясок имеет метод fetch_assoc() и fetch_row();

Цитата (wizard993 @ 2021-07-30 10:57)
Ну, например, как вариант абстрагирования SQL-запросов.

Мой опыт говорит о том, что абстрагировать SELECT запросы чаще всего невозможно. Хотя этим занимаются даже разработчики IPB. Но результат блевотный. Абстрагировать можно лишь простейшие запросы, но в этом случае смысл абстрагирования для меня теряется. Попробуйте абстрагировать запрос со сложной выборкой, статическими данными в результатах, вложенном запрос (не JOIN). Интересно, как это получится? Я даже с трудом понимаю, как можно абстрагировать UPDATE запросы, когда изменяется не одна таблица, а несколько... Даже если вам и удастся абстрагировать такие запросы, я почти уверен, что к вашему подходу придется написать не одну страницу документации. Что затрудняет понимание и отбивает желание новичков. Плюс из абстракции не всегда понятно, что хотел ею добиться автор.

Цитата (wizard993 @ 2021-07-30 10:57)
Тут пришло озарение В варианте без использования финализатора подразумевается шаманство с __toString() ?

Именно. Но там еще есть пару пикантных моментов. Напишите мне на мыло - если удастся реализовать все, как я хочу - скину вам тест версию системы с реализованным Fluent interface.
Перейти в начало страницы
+Цитировать сообщение
Djadka
сообщение 2012-04-11, 18:48
Сообщение #13
Любитель
Иконка группы

Группа: Eleanor user
Сообщений: 463
Регистрация: 2010-10-17

Репутация:   нет  
Всего: нет


Вот было бы интересно сравнить скорость и ресурсоёмкость с текучкой.
Перейти в начало страницы
+Цитировать сообщение
Гость_wizard993_*
сообщение 2012-04-11, 19:16
Сообщение #14



Гости





Цитата (Alexander @ 2012-04-11, 16:44)
Мой опыт говорит о том, что абстрагировать SELECT запросы чаще всего невозможно. Хотя этим занимаются даже разработчики IPB. Но результат блевотный. Абстрагировать можно лишь простейшие запросы, но в этом случае смысл абстрагирования для меня теряется. Попробуйте абстрагировать запрос со сложной выборкой, статическими данными в результатах, вложенном запрос (не JOIN). Интересно, как это получится? Я даже с трудом понимаю, как можно абстрагировать UPDATE запросы, когда изменяется не одна таблица, а несколько... Даже если вам и удастся абстрагировать такие запросы, я почти уверен, что к вашему подходу придется написать не одну страницу документации. Что затрудняет понимание и отбивает желание новичков. Плюс из абстракции не всегда понятно, что хотел ею добиться автор.


Который раз уже говорю спасибо за разъяснения. :)

Цитата (Alexander @ 2012-04-11, 16:44)
Именно. Но там еще есть пару пикантных моментов. Напишите мне на мыло - если удастся реализовать все, как я хочу - скину вам тест версию системы с реализованным Fluent interface.

С радостью посмотрю. Напишу в пятницу. У вас, наверное, пока и так забот хватает. А пятница уже как бы разгрузочный день.

Цитата (Djadka @ 2012-04-11, 18:48)
Вот было бы интересно сравнить скорость и ресурсоёмкость с текучкой.

Djadka, постараюсь покапать интернет на недельке, если что интересное найду - отпишусь постом.

Сообщение отредактировал wizard993 - 2012-04-11, 19:21
Перейти в начало страницы
+Цитировать сообщение
Alexander
сообщение 2012-04-12, 2:47
Сообщение #15
Eleanor developer
Иконка группы

Группа: Администраторы
Сообщений: 5 261
Регистрация: 2008-11-11
Из: Николаев
Версия системы: RC5

Репутация:   нет  
Всего: 67


wizard993, все реализовал механизм по своей задумке. Стало жрать чуть меньше памяти. Кода стало так же меньше. Посмотрите потом :)
Перейти в начало страницы
+Цитировать сообщение
Гость_wizard993_*
сообщение 2012-04-12, 7:06
Сообщение #16



Гости





Alexander, написал на мыло :)
Перейти в начало страницы
+Цитировать сообщение
Djadka
сообщение 2012-04-12, 13:17
Сообщение #17
Любитель
Иконка группы

Группа: Eleanor user
Сообщений: 463
Регистрация: 2010-10-17

Репутация:   нет  
Всего: нет


А как на счёт скорость работы? Стало шустрее или нет?
Перейти в начало страницы
+Цитировать сообщение
Alexander
сообщение 2012-04-12, 18:18
Сообщение #18
Eleanor developer
Иконка группы

Группа: Администраторы
Сообщений: 5 261
Регистрация: 2008-11-11
Из: Николаев
Версия системы: RC5

Репутация:   нет  
Всего: 67


Djadka, миллисекунды не сравниваю. По-моему так же.

Добавлено через 0 минут, 19 секунд:

Могу дать архив - сами сравните. До и после.
Перейти в начало страницы
+Цитировать сообщение

Ответить в данную темуНачать новую тему
0 чел. читают эту тему (гостей: 0, скрытых пользователей: 0)
Пользователей: 0

 
RSS Текстовая версия 0.0517 сек.    11 запросов    GZIP включен    Сейчас: 2021-07-30, 9:57