Блог человека, который 18-ть лет программирует на Delphi. И 25 лет программирует вообще. VCL, UML, MDA, тесты. Это не "учебник", это - "заметки на полях".
«"Шедевр"» -- А что не понравилось? IMHO, очень удобно с помощью текучих интерфейсов формировать рекурсивные структуры данных, обходясь без промежуточных переменных. Разумеется, текучие интерфейсы безопасно можно применить только для интерфейсов (для объектов э то не так), но пользоваться - очень удобно...
«"совсем молодая методика" - этой "совсем молодой методике" - сто лет в обед :-(» -- Честно говоря, я не вполне понял, что Вы имеете ввиду. Обращаться к свойствам объектов через точку можно было со времён появления записей. Метод мог возвращать ссылку на объект со времён появления ООП. Текучие интерфейсы стало возможным *промышленно* использовать со времён появления подсчёта ссылок и прочих механизмов автоматического управления освобождением памяти. Мартин Фаулер (Martin Fowler) ввёл термин "текучий интерфейс" в 2005 году (http://martinfowler.com/bliki/FluentInterface.html). Вы находите, что это случилось "сто лет в обед"? - Ну... Вероятно, Вы правы... В мире всё так ускорилось... ;-)
«Я начал пользоваться подобными методиками ЗАДОЛГО до Фаулера.. И видел их и у ДРУГИХ людей..» -- Завидую. Я познакомился с текучими интерфейсами приблизительно два года назад. Год у меня ушёл на осознание достоинств схемы и определения границ её применимости. Несколько месяцев назад мы впервые попытались применить этот подход в Delphi, и сразу обнаружили "много интересного", в результате чего возникли отдельные рекомендации о методике применения. Вы говорите, что использовали подобную технику "задолго до Фаулера", а Фаулер дал технике название в 2005 году (разумеется, она существовала до этого момента). Скажите: 1. Для решения каких задач Вы её использовали (используете)? 2. В fluent-стиле Вы работали с объектами или с интерфейсами? 3. Можно взглянуть на соответствующий код? Думаю, это безопасно, поскольку вне контекста Вы не передадите никаких know-how. 4. Вы ссылаетесь на "других людей". Интересен контекст (вопросы 1-3) применения fluent-техники у них.
Мои вопросы совершенно не праздны, поскольку у меня сложилось устойчивое ощущение, что текучие интерфейсы можно использовать в Delphi с осторожностью.
>>Несколько месяцев назад мы впервые попытались применить этот подход в Delphi, и сразу >>обнаружили "много интересного", в результате чего возникли отдельные рекомендации о >>методике применения.
Очень интересны Ваши эти "отдельные рекомендации". Как люди, вовлечённые в коммуникативный процесс, мы должны понимать. Если ты НЕ ДАЁШЬ информацию, то ты НЕ В ПРАВЕ требовать. Сами свои "бриллиантовые" рекомендации держите в тайне, а Александра спрашиваете.
>>Скажите: >>...
Я не удивлюсь, что Александр Вам ничего не скажет. И я пойму Александра. Разговор похож на допрос, причём Александру приходится почему-то доказывать, что он прав.
Такое впечатление, что Вы как-то связаны с преподаванием. Шаблоны Ваших сообщений достаточно неизменны.
а) немного собственного "я"-конья б) немного тривиальных мыслей в) попытка позадавать вопросы в недружеской форме с целью информационно подпитаться
Расскажу, как обычно происходят защиты диссертации. Выступает молодой талантливый аспирант. Докладывает новые прорывные результаты. Встаёт член учёного совета.
1) Я этой темой занимался давно. Еще 20 лет назад, когда создавал .... для ... (за что получил впоследствии .... героя труда. 2) Уже тогда мне было ясно, что то, чем Вы занимаетесь - есть мелкая часть большой проблемы, которую я решил. 3) >> результате чего возникли отдельные рекомендации о методике применения. (даже цитату сделал) 4) А теперь ответьте на вопросы (опять цитаты): >> Для решения каких задач Вы её использовали? >> Можно взглянуть на.... хотя цены это не представляет (типа не хочу одалживаться) ....
Воу-воу, палехче :) Кто здесь что от кого требует? Какой допрос? Что именно приходится доказывать Александру? По-моему, в этом топике люди делятся своими впечатлениями от работы с текучим интерфейсом в Дельфи. Хоть я уже и не использую этот язык, но мне тоже интересно где у вас принято использовать эту технику. Пока ни от Вас, ни от Александра я не услышал ничего вразумительного (в рамках NDA, конечно). Если не обмен знаний/умений, то зачем вообще было создавать эту тему?
>>Пока ни от Вас, ни от Александра я не услышал ничего вразумительного
Да Вы просто гений общения!
>>Кто здесь что от кого требует?
Перечитайте список вопросов в форме: >>1. Для решения каких задач Вы её использовали (используете)? >>2. В fluent-стиле Вы работали с объектами или с интерфейсами? >>3. Можно взглянуть на соответствующий код? Думаю, это безопасно, поскольку вне контекста Вы не передадите никаких know-how. >>4. Вы ссылаетесь на "других людей". Интересен контекст (вопросы 1-3) применения fluent-техники у них.
Давайте я Вам верну в такой же форме: 1. Виктор, кто Вы? Кто Вас звал? Зачем Вы пришли? 2. На каком основании Вы позволяете себе комментировать уровень вразумительности? 3. Почему Вы диктуете автору блога, какие темы блога ему создавать?
1. Я пришёл потому что мне интересна эта тема (см. выше) 2. Возможно, потому что каждый человек имеет прав на своё ИМХО. 3. Это в каком месте? Автор создаёт успешно создаёт интересные темы, которые мы здесь обсуждаем.
Видимо, Вы не уяснили суть моего предыдущего комментария :) Здесь никто ничего ни от кого не требует. Есть желание поделиться - пишите в комментах, нет (или не можете) - так и скажите. NameRec задал вопросы, которые его интересуют. Если Вы боитесь распространять свои знания, прикройтесь NDA - Вас все поймут.
>Текучие интерфейсы стало возможным *промышленно* использовать со времён появления подсчёта ссылок и прочих механизмов автоматического управления освобождением памяти. Каким, интересно, боком здесь автоматическое управление памятью? >Мартин Фаулер (Martin Fowler) ввёл термин "текучий интерфейс" в 2005 году Это не мешало пользоваться сей тривиальной и _не_заслуживающей_столь_пристального_внимания_ "фичей". >Год у меня ушёл на осознание достоинств схемы и определения границ её применимости. Год? О_О
Ваши времена давно прошли. Если в универе не говорить "я - не вполне умный", то так им и останешься. Неужели признание того факта, что Вы чего-то не знаете, Вас как-то задевает? Мне казалось, что люди ещё в школе избавляются от этого стереотипа.
>Год у меня ушёл на осознание достоинств схемы и определения границ её применимости. Возможно, NameRec имел ввиду, что год они пытались применять текучий интерфейс. Узнали его плюсы и минусы для разных ситуаций, научились с утечками памяти бороться и пр.
>Возможно, NameRec имел ввиду, что год они пытались применять текучий интерфейс. Узнали его плюсы и минусы для разных ситуаций, научились с утечками памяти бороться и пр. Звучит так, будто они что-то серьёзное изучали. Ну, если кому то для такой тривиальщины нужен год - то, видимо, это слишком далеко от моего понимания.
«Звучит так, будто они что-то серьёзное изучали. Ну, если кому то для такой тривиальщины нужен год - то, видимо, это слишком далеко от моего понимания.» -- Знакомство состоялось в контексте JOOQ (http://www.jooq.org/) в контексте борьбы с текстовым представлением SQL в исходном коде на Delphi. Поскольку немедленных действий по этому вопросу не планировалось (мы находились на этапе накопления фактов для последующего анализа проблемы) тема применения текучих интерфейсов "варились" в головах, мы периодически к ней возвращались, обсуждали, где и как можно было бы использовать эту технику. Вскрылось очевидное противоречие с техникой освобождения ресурсов, принятой в Delphi. Рассмотрим такой код: {code} _ expr := _ _ TSQLExpression.Create() _ _ _ .Columns([ _ _ _ _ TSQLColumn.Create('Surname', 'Фамилия'), _ _ _ _ TSQLColumn.Create('Name', 'Имя'), _ _ _ _ TSQLColumn.Create('Patronymic', 'Отчество'), _ _ _ _ TSQLColumn.Create('BornDate', 'Дата рожд.')]) _ _ _ .From('PERSONS'); {/code} Обратите внимание, что если при построении экземпляров TSQLColumn произойдёт исключение после успешного создания первого элемента открытого массива, то мы получим утечку памяти. В Java такого не случится, поскольку там за освобождением памяти следит сборщик мусора, в Delphi же в указанной ситуации придётся не строить объекты посредством конструктора, а вызывать соответствующую фабричную функцию, возвращающую не объект, а интерфейс.
«Даже в вашем примере ничего fluent-специфичного в плане утечек памяти не происходит. Это характерно для дельфи вообще, fluent здесь не причём.» -- Я вообще не говорил о fluent-специфике "в плане утечек памяти". Я упомянул, что fluent-технику следует использовать в Delphi с учётом того, что память придётся освобождать вручную, а не так, как принято в языках, где эта техника часто используется. Или использовать интерфейсы. Лично для меня приемлемым оказался только вариант с использованием интерфейсов, о чём я и сказал.
Интересно, как "текучий интерфейс" (если его прикрутить к стандартным компонентам) изменит код (сейчас представлю). "Детские" примеры не интересны. Хорошо бы поработать с агрегацией.
Это же очевидно: var Label : TLabel; begin Label := TLabel.Create(self).Parent(Panel1).Font(Color=clBlack).Position(X=10).Text('New Label'); Не помню, правда, можно ли в дельфи именованные параметры так передавать.
«Давайте зададим один простой вопрос - "а зачем всё это"?» -- В специальных случаях упростить построение структуры данных, элементами которой являются объекты, посредством задания свойств этих объектов без использования промежуточных переменных. В Delphi мне известен только один случай, когда применение техники текучих интерфейсов оправдано - построение структуры SQL-запроса в стиле JOOQ или QueryDSL, ссылки на которые я приводил.
«Какая мотивация?? Что экономим? Строки кода? Или что? В ДАННОМ конкретном случае.» -- В данном конкретном случае (построение и настройка крнтейнеров VCL) я не вижу смысла в использовании техники текучих интерфейсов, о чём сказал выше. Это окажется дорого, поскольку придётся создавать интерфейсы для учёта специфики каждого класса, а выигрыш будет совершенно незначительным. Кроме того, лично я считаю, что строить компоненты VCL "вручную" следует только в крайних случаях. А для таких случаев можно обойтись и промежуточными переменными.
IMHO применение fluent-техники уместно в ситуациях, когда разнообразие классов невелико (10-20 штук), а основной вариант использования - построение объектов в коде, что тоже - редкость. В эти рамки ложится пока только SQL, причём только в случае, если есть причины не указывать его текстовом виде, а описывать в терминах объектов.
«Label := TLabel.Create(self).Parent(Panel1).Font(Color=clBlack).Position(X=10).Text('New Label');» -- Ну да, где-то так... Но применительно к Delphi IMHO лучше так: {code} control := NewLabel(self) .SetParent(Panel1) .SetFontProps(['color', clBlack, 'bold', True]) .SetPosition('x', 10) .SetText('New Label'); {/code} NewLabel возвращает интерфейс ILabel, любой метод которого является функцией и возвращает ссылку на себя же (т.е. на интерфейс, чей метод вызван). В Java и прочих языках с GC так можно работать и с классами. В Delphi следует использовать интерфейсы, чтобы не столкнуться утечками памяти при передаче объектов в открытых массивах. Для доступа к свойствам агрегированных объектов (Font) придётся реализовать, как минимум, соответствующий метод, в противном случае "текучая" цепочка вызовов разорвётся или станет хуже читаемой. IMHO формально «прикручивать» fluent-интерфесы к "чему угодно" не стоит, поскольку из обозначенного мною выше следует, что эта техника подразумевает относительно тщательное продумывание последующего применения. В некоторых случаях, вроде обозначенного Вами, я вообще не вижу в этом смысла, особенно если учесть наличие проработанных решений на этот счёт, избавляющих от массового построения объектов вручную.
«? Есть апологеты "текучести"? Или уже "утекли"?» -- Текучие интерфейсы — это техника, относительно недавно завоевавшая популярность. Есть ситуации, когда её применение весьма уместно — Виктор кратко их обозначил. Быть апологетом... Мне представляется, что трудно быть апологетом отвёртки или штангенциркуля. Таким образом, или Вы не озаботились выяснить смысл «ввёрнутого» Вами слова, или в очередной раз неуклюже пошутили. Вообще же, Всеволод, я думаю, этот блог не место для провокаций и выяснения отношений. Впрочем, его автор меня может поправить.
Ну наконец-то разговор перешёл в практическое русло :) А что, в Delphi до сих пор нет словарей? Они сами просятся в метод setFonts. Кстати, а на практике, может, лучше не создавать "текучий" метод SetFontProps? IMHO, в наглядности он очень сильно теряет. А генерацию SQL таким образом пробовали реализовать? Например, что-то типа $user = Yii::app()->db->createCommand() ->select('id, username, profile') ->from('tbl_user u') ->join('tbl_profile p', 'u.id=p.user_id') ->where('id=:id', array(':id'=>$id)) ->queryRow(); Честно говоря настолько удобная СУБД-независимая штука, что отказаться от неё очень сложно.
«А что, в Delphi до сих пор нет словарей? Они сами просятся в метод setFonts.» -- Начиная с версии 2009 (если не ошибаюсь) в Delphi появились обобщённые типы (generics). Так что, можно сказать, словари есть. Но словарь, сам по себе будет классом, на объекты которого распространяется необходимость освобождения. Так что, так изящно, как в Python, боюсь, не получится, хотя я и не думал всерьёз об этом.
«Кстати, а на практике, может, лучше не создавать "текучий" метод SetFontProps? IMHO, в наглядности он очень сильно теряет.» -- Почему? По-моему, нормально. Кстати, доступ к агрегированным объектам через текучий интерфейс везде приводит к необходимости одного из двух: * Вынести соответствующий метод настройки в агрегируЮЩИЙ класс (его я и применил в примере) * Добавить метод, возвращающий ссылку на агрегируЮЩИЙ в агрегируЕМЫЙ Но возможно, я выделил не все артефакты применения текучих интерфейсов в контексте Delphi.
«А генерацию SQL таким образом пробовали реализовать?» -- Да, где-то так оно и получается :-) Ну, по модулю специфики Delphi, разумеется. Кстати, в блоке WHERE удалось сделать строже, чем в Вашем примере. Строже в том смысле, что запись условий, в которых может проявляться специфика СУБД оформляется в виде объектов соответствующих типов. Получилось ближе к QueryDSL (http://www.querydsl.com/) :-)
Хм, мне казалось, что в этом примере генерации SQL специфика СУБД не должна учитываться. Это более низкоуровневое понятие относительно запроса, и оно должно быть скрыто внутри db->createCommand.
> Но словарь, сам по себе будет классом, на объекты которого распространяется необходимость освобождения. Всё-таки прелести в GC есть :)
Я думаю, Виктор имел ввиду не GC в чистом виде, а парадигму автоматического управления освобождением объектов. Для прикладного программиста в сущности безразлично, чем будет обеспечено то, что он не обязан расставлять множество try..finally, загораживая ими описываемую бизнес-логику.
«А что, в Delphi до сих пор нет словарей? Они сами просятся в метод setFonts. Кстати, а на практике, может, лучше не создавать "текучий" метод SetFontProps?» -- Виктор, прошу прощения - только сейчас до меня дошло, что Вы имели ввиду :-) Помог Александр. Мне же показалось, что Вы против самого добавления метода SetFontProps. Этот способ (добавление отдельного метода) мне видится единственным простым выходом для настройки свойств агрегированного объекта. Разумеется, форма может быть другой. Я не стал бы настаивать на решении передавать ключи и значения элементов словаря в общем списке - такая форма указана мною в примере только для простоты.
«Это типа с какой стороны хорошо?» -- В том виде, в каком Вы это записали (с учётом смысла и формы) - ни с какой. Преимущества проявятся, если у Вас не открытый к расширению, а относительно фиксированный набор классов или скрипт-язык с утиной типизацией. Вы не с того начали (начали мысленно "прикручивать" fluent-технику к построению компонентов VCL) отсюда и проблемы на каждом шагу. Вместо этого можно было бы изучить саму технику, понять, на чём она основана, определить границы её применимости и только после этого решать: подходит ли инструмент (fluent-техника) к данной конкретной задаче или нет. Пост Фаулера того же проглядеть (я давал на него ссылку), посмотреть success story (JOOQ и QueryDSL - ссылки я тоже давал). Я уже сказал выше, что к описанию структуры компонентов в контейнерах Delphi (формы, фреймы, модули данных, и т.п.) эта техника не подходит и "прикручивать" её смысла нет. Если Вам интересно, *почему* я делаю такой вывод - спросите, я постараюсь подробно ответить, что именно мешает. Но задавая вопросы, умерьте пожалуйста собственный апломб, поскольку в выбранном Вами ключе мне разговаривать с Вами неприятно.
Ну и чтобы меня не считали там каким-то "злыднем" и "приставалой", процитирую и соглашусь с (блин) Анонимными Имяреком (ну надо же так стесняться своего ФИО, какое-то просто неуважение по отношению к родителям. Ну или неуверенность в собственных мыслях вплоть до не-подписывания их).
>>Это окажется дорого, поскольку придётся создавать интерфейсы для учёта специфики каждого класса, а выигрыш будет совершенно незначительным.
ОТЛ! Можете под этой мыслью подписаться мной, чтобы она не выглядела анонимной.
>>Кроме того, лично я считаю, что строить компоненты VCL "вручную" следует только в крайних случаях.
Что стоит "я считаю"? Вы никогда не писали динамические интерфейсы, генерируемые по мета-данным БД? Рано или поздно каждый Р-БД разработчик приходит к необходимости писать свои мета-данные и некий "конфигуратор".
Более того - я прям-таки бил бы по рукам (голове) линейкой (ногами) дельфистов. Не порочьте честь и достоинство ООП-разработчиков! Знайте и умейте применять голенький ООП. Своих учеников я всегда заставлял сначала на голой форме создавать интерфейс динамически. И только потом - WYSIWYG. И не только в Delphi, но и в Visual Studio.
>>IMHO применение fluent-техники уместно в ситуациях, когда разнообразие классов невелико (10-20 штук),
Отл. Т.е. начав использовать "текучесть" мы уже не можем масштабировать систему? О-как! Я бы тогда изначально бы не стал использовать fluent, т.к. я - оптимист, желаю своей системе роста и процветания, конечно, не ограничив её 20 классами. Респект! Вы доказали неэффективность "текучести".
>>а основной вариант использования - построение объектов в коде, что тоже - редкость.
Не.
>>В эти рамки ложится пока только SQL, причём только в случае, если есть причины не указывать его текстовом виде, а описывать в терминах объектов.
«Кроме того, лично я считаю, что строить компоненты VCL "вручную" следует только в крайних случаях. -- Что стоит "я считаю"? Вы никогда не писали динамические интерфейсы» -- Это и есть означенный крайний случай :-) Есть ещё некоторые ситуации, когда компоненты приходится создавать "вручную". В остальных случаях IMHO лучше "нарисовать" в дизайнере (не в дизайнере IDE Delphi, если быть точным) необходимый фрагмент, загрузить его в коде и вставить в нужное место.
«IMHO применение fluent-техники уместно в ситуациях, когда разнообразие классов невелико (10-20 штук), -- Отл. Т.е. начав использовать "текучесть" мы уже не можем масштабировать систему? О-как!» -- Почти правильно. Лучше смотреть на fluent-технику как на некий DSL, расширение которого производится по определённым правилам. Например, в язык добавляется функция (класс, метод класса), после чего становится возможным его использование. Подобно этому следует действовать с fluent-техникой. Лучше пояснить это на примере, но если неинтересно, я не хочу тратить время. Если интересно - спрашивайте, я постараюсь развёрнуто ответить. Прощу принять во внимание, что системного описания "теории" fluent-DSL я не встречал (за исключением толковой статьи Фаулера), поэтому могу изложить только своё понимание, которое появилось в течение того самого года, который вызвал у Вас приступ веселья.
«Я бы тогда изначально бы не стал использовать fluent, т.к. я - оптимист, желаю своей системе роста и процветания, конечно, не ограничив её 20 классами.» -- Я это уже понял :-) Я же оценил его плюсы и ограничения и использую его как DSL.
«Респект! Вы доказали неэффективность "текучести".» -- Благодарю за "респект", но с сожалением возвращаю его Вам :-) Это Вы сами "доказали" себе его "неэффективность" неверно определив область, где эта техника действительно может принести заметную пользу.
«а основной вариант использования - построение объектов в коде, что тоже - редкость. -- Не.» -- А Вы убеждены, что понимаете, с чем спорите? ;-)
«В эти рамки ложится пока только SQL, причём только в случае, если есть причины не указывать его текстовом виде, а описывать в терминах объектов. -- Это Вы часом не склейку строк имеете ввиду?» -- Нет.
Кстати, один из примеров удачного применения текучего интерфейса: q3 = Job.objects.filter(pub_date__gte=datetime(2006, 1, 1)) if bla_bla: q3 = q3.filter(location__city__exact="Cleveland", location__state__exact="Ohio")
Извиняйте, что на питоне - я сейчас руководство по Django читаю.
NameRec:
ОтветитьУдалить«"Шедевр"»
-- А что не понравилось?
IMHO, очень удобно с помощью текучих интерфейсов формировать рекурсивные структуры данных, обходясь без промежуточных переменных.
Разумеется, текучие интерфейсы безопасно можно применить только для интерфейсов (для объектов э
то не так), но пользоваться - очень удобно...
Поддерживаю со стороны скриптовых языков (PHP, Python). ОЧень удобная штука, в частности для генерации SQL-запроса.
Удалить"совсем молодая методика"
Удалить- этой "совсем молодой методике" - сто лет в обед :-(
Поправьте меня, если ошибаюсь...
Удалитьcoun << "Hello, man" << "you're number" << 16 << "in the list of less than " << 100.5 << endln;
Кстати 2 цента в "Хабровский диспут".
TStringBuilder применяется НЕ для красоты, а для скорости.
первая правка пришла
Удалитьcout (автоматом пальцы выбросили count, потом стёр не тот символ)
NameRec:
ОтветитьУдалить«"совсем молодая методика"
- этой "совсем молодой методике" - сто лет в обед :-(»
-- Честно говоря, я не вполне понял, что Вы имеете ввиду.
Обращаться к свойствам объектов через точку можно было со времён появления записей.
Метод мог возвращать ссылку на объект со времён появления ООП.
Текучие интерфейсы стало возможным *промышленно* использовать со времён появления подсчёта ссылок и прочих механизмов автоматического управления освобождением памяти.
Мартин Фаулер (Martin Fowler) ввёл термин "текучий интерфейс" в 2005 году (http://martinfowler.com/bliki/FluentInterface.html).
Вы находите, что это случилось "сто лет в обед"? - Ну... Вероятно, Вы правы... В мире всё так ускорилось... ;-)
Ну что же... Я начал пользоваться подобными методиками ЗАДОЛГО до Фаулера.. И видел их и у ДРУГИХ людей... Считайте меня занудой...
УдалитьNameRec:
Удалить«Я начал пользоваться подобными методиками ЗАДОЛГО до Фаулера.. И видел их и у ДРУГИХ людей..»
-- Завидую.
Я познакомился с текучими интерфейсами приблизительно два года назад.
Год у меня ушёл на осознание достоинств схемы и определения границ её применимости.
Несколько месяцев назад мы впервые попытались применить этот подход в Delphi, и сразу обнаружили "много интересного", в результате чего возникли отдельные рекомендации о методике применения.
Вы говорите, что использовали подобную технику "задолго до Фаулера", а Фаулер дал технике название в 2005 году (разумеется, она существовала до этого момента).
Скажите:
1. Для решения каких задач Вы её использовали (используете)?
2. В fluent-стиле Вы работали с объектами или с интерфейсами?
3. Можно взглянуть на соответствующий код? Думаю, это безопасно, поскольку вне контекста Вы не передадите никаких know-how.
4. Вы ссылаетесь на "других людей". Интересен контекст (вопросы 1-3) применения fluent-техники у них.
Мои вопросы совершенно не праздны, поскольку у меня сложилось устойчивое ощущение, что текучие интерфейсы можно использовать в Delphi с осторожностью.
>>Несколько месяцев назад мы впервые попытались применить этот подход в Delphi, и сразу
Удалить>>обнаружили "много интересного", в результате чего возникли отдельные рекомендации о
>>методике применения.
Очень интересны Ваши эти "отдельные рекомендации".
Как люди, вовлечённые в коммуникативный процесс, мы должны понимать. Если ты НЕ ДАЁШЬ информацию, то ты НЕ В ПРАВЕ требовать.
Сами свои "бриллиантовые" рекомендации держите в тайне, а Александра спрашиваете.
>>Скажите:
>>...
Я не удивлюсь, что Александр Вам ничего не скажет. И я пойму Александра. Разговор похож на допрос, причём Александру приходится почему-то доказывать, что он прав.
Такое впечатление, что Вы как-то связаны с преподаванием. Шаблоны Ваших сообщений достаточно неизменны.
а) немного собственного "я"-конья
б) немного тривиальных мыслей
в) попытка позадавать вопросы в недружеской форме с целью информационно подпитаться
Расскажу, как обычно происходят защиты диссертации. Выступает молодой талантливый аспирант. Докладывает новые прорывные результаты. Встаёт член учёного совета.
1) Я этой темой занимался давно. Еще 20 лет назад, когда создавал .... для ... (за что получил впоследствии .... героя труда.
2) Уже тогда мне было ясно, что то, чем Вы занимаетесь - есть мелкая часть большой проблемы, которую я решил.
3) >> результате чего возникли отдельные рекомендации о методике применения. (даже цитату сделал)
4) А теперь ответьте на вопросы (опять цитаты):
>> Для решения каких задач Вы её использовали?
>> Можно взглянуть на.... хотя цены это не представляет (типа не хочу одалживаться)
....
Так что вот так это выглядит со стороны.
Воу-воу, палехче :)
УдалитьКто здесь что от кого требует? Какой допрос? Что именно приходится доказывать Александру?
По-моему, в этом топике люди делятся своими впечатлениями от работы с текучим интерфейсом в Дельфи. Хоть я уже и не использую этот язык, но мне тоже интересно где у вас принято использовать эту технику. Пока ни от Вас, ни от Александра я не услышал ничего вразумительного (в рамках NDA, конечно). Если не обмен знаний/умений, то зачем вообще было создавать эту тему?
>>Пока ни от Вас, ни от Александра я не услышал ничего вразумительного
УдалитьДа Вы просто гений общения!
>>Кто здесь что от кого требует?
Перечитайте список вопросов в форме:
>>1. Для решения каких задач Вы её использовали (используете)?
>>2. В fluent-стиле Вы работали с объектами или с интерфейсами?
>>3. Можно взглянуть на соответствующий код? Думаю, это безопасно, поскольку вне контекста Вы не передадите никаких know-how.
>>4. Вы ссылаетесь на "других людей". Интересен контекст (вопросы 1-3) применения fluent-техники у них.
Давайте я Вам верну в такой же форме:
1. Виктор, кто Вы? Кто Вас звал? Зачем Вы пришли?
2. На каком основании Вы позволяете себе комментировать уровень вразумительности?
3. Почему Вы диктуете автору блога, какие темы блога ему создавать?
Вот, как-то так. Понравилось?
1. Я пришёл потому что мне интересна эта тема (см. выше)
Удалить2. Возможно, потому что каждый человек имеет прав на своё ИМХО.
3. Это в каком месте? Автор создаёт успешно создаёт интересные темы, которые мы здесь обсуждаем.
Видимо, Вы не уяснили суть моего предыдущего комментария :) Здесь никто ничего ни от кого не требует. Есть желание поделиться - пишите в комментах, нет (или не можете) - так и скажите. NameRec задал вопросы, которые его интересуют. Если Вы боитесь распространять свои знания, прикройтесь NDA - Вас все поймут.
>Текучие интерфейсы стало возможным *промышленно* использовать со времён появления подсчёта ссылок и прочих механизмов автоматического управления освобождением памяти.
ОтветитьУдалитьКаким, интересно, боком здесь автоматическое управление памятью?
>Мартин Фаулер (Martin Fowler) ввёл термин "текучий интерфейс" в 2005 году
Это не мешало пользоваться сей тривиальной и _не_заслуживающей_столь_пристального_внимания_ "фичей".
>Год у меня ушёл на осознание достоинств схемы и определения границ её применимости.
Год? О_О
>> Год? О_О
Удалить+100500
Вообще, как-то люди перестали гордиться своим интеллектом. В мои времена было стыдно писать "я не вполне понимаю" означало "я - не вполне умный".
Ваши времена давно прошли. Если в универе не говорить "я - не вполне умный", то так им и останешься. Неужели признание того факта, что Вы чего-то не знаете, Вас как-то задевает? Мне казалось, что люди ещё в школе избавляются от этого стереотипа.
Удалить>Год у меня ушёл на осознание достоинств схемы и определения границ её применимости.
Возможно, NameRec имел ввиду, что год они пытались применять текучий интерфейс. Узнали его плюсы и минусы для разных ситуаций, научились с утечками памяти бороться и пр.
>Возможно, NameRec имел ввиду, что год они пытались применять текучий интерфейс. Узнали его плюсы и минусы для разных ситуаций, научились с утечками памяти бороться и пр.
УдалитьЗвучит так, будто они что-то серьёзное изучали. Ну, если кому то для такой тривиальщины нужен год - то, видимо, это слишком далеко от моего понимания.
NameRec:
Удалить«Звучит так, будто они что-то серьёзное изучали. Ну, если кому то для такой тривиальщины нужен год - то, видимо, это слишком далеко от моего понимания.»
-- Знакомство состоялось в контексте JOOQ (http://www.jooq.org/) в контексте борьбы с текстовым представлением SQL в исходном коде на Delphi.
Поскольку немедленных действий по этому вопросу не планировалось (мы находились на этапе накопления фактов для последующего анализа проблемы) тема применения текучих интерфейсов "варились" в головах, мы периодически к ней возвращались, обсуждали, где и как можно было бы использовать эту технику.
Вскрылось очевидное противоречие с техникой освобождения ресурсов, принятой в Delphi.
Рассмотрим такой код:
{code}
_ expr :=
_ _ TSQLExpression.Create()
_ _ _ .Columns([
_ _ _ _ TSQLColumn.Create('Surname', 'Фамилия'),
_ _ _ _ TSQLColumn.Create('Name', 'Имя'),
_ _ _ _ TSQLColumn.Create('Patronymic', 'Отчество'),
_ _ _ _ TSQLColumn.Create('BornDate', 'Дата рожд.')])
_ _ _ .From('PERSONS');
{/code}
Обратите внимание, что если при построении экземпляров TSQLColumn произойдёт исключение после успешного создания первого элемента открытого массива, то мы получим утечку памяти.
В Java такого не случится, поскольку там за освобождением памяти следит сборщик мусора, в Delphi же в указанной ситуации придётся не строить объекты посредством конструктора, а вызывать соответствующую фабричную функцию, возвращающую не объект, а интерфейс.
Даже в вашем примере ничего fluent-специфичного в плане утечек памяти не происходит. Это характерно для дельфи вообще, fluent здесь не причём.
УдалитьNameRec:
Удалить«Даже в вашем примере ничего fluent-специфичного в плане утечек памяти не происходит. Это характерно для дельфи вообще, fluent здесь не причём.»
-- Я вообще не говорил о fluent-специфике "в плане утечек памяти".
Я упомянул, что fluent-технику следует использовать в Delphi с учётом того, что память придётся освобождать вручную, а не так, как принято в языках, где эта техника часто используется. Или использовать интерфейсы.
Лично для меня приемлемым оказался только вариант с использованием интерфейсов, о чём я и сказал.
Интересно, как "текучий интерфейс" (если его прикрутить к стандартным компонентам) изменит код (сейчас представлю). "Детские" примеры не интересны. Хорошо бы поработать с агрегацией.
ОтветитьУдалитьvar
Label : TLabel;
begin
Label := TLabel.Create(self);
Label.Parent := Panel1;
Label.Font.Color := clBlack;
Label.Position.X := 10;
Label.Text := 'New Label';
? Есть апологеты "текучести"? Или уже "утекли"?
Это же очевидно:
Удалитьvar
Label : TLabel;
begin
Label := TLabel.Create(self).Parent(Panel1).Font(Color=clBlack).Position(X=10).Text('New Label');
Не помню, правда, можно ли в дельфи именованные параметры так передавать.
Уважаю Всеволода и его вопрос.
УдалитьУважаю его оппонентов, которые отвечают.
Но! Мужчины!
Давайте зададим один простой вопрос - "а зачем всё это"?
Какая мотивация?? Что экономим? Строки кода? Или что?
В ДАННОМ конкретном случае.
NameRec:
Удалить«Давайте зададим один простой вопрос - "а зачем всё это"?»
-- В специальных случаях упростить построение структуры данных, элементами которой являются объекты, посредством задания свойств этих объектов без использования промежуточных переменных.
В Delphi мне известен только один случай, когда применение техники текучих интерфейсов оправдано - построение структуры SQL-запроса в стиле JOOQ или QueryDSL, ссылки на которые я приводил.
«Какая мотивация?? Что экономим? Строки кода? Или что?
В ДАННОМ конкретном случае.»
-- В данном конкретном случае (построение и настройка крнтейнеров VCL) я не вижу смысла в использовании техники текучих интерфейсов, о чём сказал выше.
Это окажется дорого, поскольку придётся создавать интерфейсы для учёта специфики каждого класса, а выигрыш будет совершенно незначительным.
Кроме того, лично я считаю, что строить компоненты VCL "вручную" следует только в крайних случаях. А для таких случаев можно обойтись и промежуточными переменными.
IMHO применение fluent-техники уместно в ситуациях, когда разнообразие классов невелико (10-20 штук), а основной вариант использования - построение объектов в коде, что тоже - редкость.
В эти рамки ложится пока только SQL, причём только в случае, если есть причины не указывать его текстовом виде, а описывать в терминах объектов.
«Label := TLabel.Create(self).Parent(Panel1).Font(Color=clBlack).Position(X=10).Text('New Label');»
ОтветитьУдалить-- Ну да, где-то так...
Но применительно к Delphi IMHO лучше так:
{code}
control := NewLabel(self)
.SetParent(Panel1)
.SetFontProps(['color', clBlack, 'bold', True])
.SetPosition('x', 10)
.SetText('New Label');
{/code}
NewLabel возвращает интерфейс ILabel, любой метод которого является функцией и возвращает ссылку на себя же (т.е. на интерфейс, чей метод вызван).
В Java и прочих языках с GC так можно работать и с классами. В Delphi следует использовать интерфейсы, чтобы не столкнуться утечками памяти при передаче объектов в открытых массивах.
Для доступа к свойствам агрегированных объектов (Font) придётся реализовать, как минимум, соответствующий метод, в противном случае "текучая" цепочка вызовов разорвётся или станет хуже читаемой.
IMHO формально «прикручивать» fluent-интерфесы к "чему угодно" не стоит, поскольку из обозначенного мною выше следует, что эта техника подразумевает относительно тщательное продумывание последующего применения.
В некоторых случаях, вроде обозначенного Вами, я вообще не вижу в этом смысла, особенно если учесть наличие проработанных решений на этот счёт, избавляющих от массового построения объектов вручную.
«? Есть апологеты "текучести"? Или уже "утекли"?»
-- Текучие интерфейсы — это техника, относительно недавно завоевавшая популярность.
Есть ситуации, когда её применение весьма уместно — Виктор кратко их обозначил.
Быть апологетом... Мне представляется, что трудно быть апологетом отвёртки или штангенциркуля. Таким образом, или Вы не озаботились выяснить смысл «ввёрнутого» Вами слова, или в очередной раз неуклюже пошутили.
Вообще же, Всеволод, я думаю, этот блог не место для провокаций и выяснения отношений. Впрочем, его автор меня может поправить.
"Вообще же, Всеволод, я думаю, этот блог не место для провокаций и выяснения отношений. Впрочем, его автор меня может поправить."
УдалитьЛЮБОЕ информационное пространство - "не место для провокаций".
ИСКРЕННЕ так считаю.
К сожалению " наш век интернетов" - мы ВСЕ забываем об этом.
Не считаю написанное Всеволодом ПРОВОКАЦИЕЙ.
Хотя о ФОРМЕ - я бы лично - подумал бы.
Без обид. Это совет - ВСЕМ.
И МНЕ - в первую очередь.
Про "трудно быть апологетом отвёртки или штангенциркуля" - три три раза - ХА ХА... ОТЛИЧНАЯ метафора. Правда! Я запишу её в свой словарь. Отличная!
Вот ДАЙ БОГ - нам ВСЕМ примерять её на себя :-)
"или в очередной раз неуклюже пошутили"
Удалить-- вот ЧТО БЫ НИ НАПИСАЛ Всеволод, но я бы не стал бы писать такое и в такой форме...
Хотя и я - небезгрешен....
"Вообще же, Всеволод, я думаю, этот блог не место для провокаций и выяснения отношений. Впрочем, его автор меня может поправить."
Удалитья (как автор) - предлагаю ВСЕМ - "пожать руки" и вернуться в русло "технологических проблем". Обсуждать друг друга - глупо. Особенно мужчинам в 40+
Ну наконец-то разговор перешёл в практическое русло :) А что, в Delphi до сих пор нет словарей? Они сами просятся в метод setFonts. Кстати, а на практике, может, лучше не создавать "текучий" метод SetFontProps? IMHO, в наглядности он очень сильно теряет. А генерацию SQL таким образом пробовали реализовать? Например, что-то типа
ОтветитьУдалить$user = Yii::app()->db->createCommand()
->select('id, username, profile')
->from('tbl_user u')
->join('tbl_profile p', 'u.id=p.user_id')
->where('id=:id', array(':id'=>$id))
->queryRow();
Честно говоря настолько удобная СУБД-независимая штука, что отказаться от неё очень сложно.
NameRec:
Удалить«А что, в Delphi до сих пор нет словарей? Они сами просятся в метод setFonts.»
-- Начиная с версии 2009 (если не ошибаюсь) в Delphi появились обобщённые типы (generics).
Так что, можно сказать, словари есть. Но словарь, сам по себе будет классом, на объекты которого распространяется необходимость освобождения.
Так что, так изящно, как в Python, боюсь, не получится, хотя я и не думал всерьёз об этом.
«Кстати, а на практике, может, лучше не создавать "текучий" метод SetFontProps? IMHO, в наглядности он очень сильно теряет.»
-- Почему? По-моему, нормально.
Кстати, доступ к агрегированным объектам через текучий интерфейс везде приводит к необходимости одного из двух:
* Вынести соответствующий метод настройки в агрегируЮЩИЙ класс (его я и применил в примере)
* Добавить метод, возвращающий ссылку на агрегируЮЩИЙ в агрегируЕМЫЙ
Но возможно, я выделил не все артефакты применения текучих интерфейсов в контексте Delphi.
«А генерацию SQL таким образом пробовали реализовать?»
-- Да, где-то так оно и получается :-)
Ну, по модулю специфики Delphi, разумеется.
Кстати, в блоке WHERE удалось сделать строже, чем в Вашем примере. Строже в том смысле, что запись условий, в которых может проявляться специфика СУБД оформляется в виде объектов соответствующих типов.
Получилось ближе к QueryDSL (http://www.querydsl.com/) :-)
Хм, мне казалось, что в этом примере генерации SQL специфика СУБД не должна учитываться. Это более низкоуровневое понятие относительно запроса, и оно должно быть скрыто внутри db->createCommand.
Удалить> Но словарь, сам по себе будет классом, на объекты которого распространяется необходимость освобождения.
Всё-таки прелести в GC есть :)
"Всё-таки прелести в GC есть "
Удалить-- вот не считаю так.
Ну ARC - ещё - "куда ни шло". Но именно - "куда ни шло".
Лучше всего всё же Smart-Pointer'ы в стиле C++.
На мой вкус.
NameRec:
УдалитьЯ думаю, Виктор имел ввиду не GC в чистом виде, а парадигму автоматического управления освобождением объектов.
Для прикладного программиста в сущности безразлично, чем будет обеспечено то, что он не обязан расставлять множество try..finally, загораживая ими описываемую бизнес-логику.
«А что, в Delphi до сих пор нет словарей? Они сами просятся в метод setFonts. Кстати, а на практике, может, лучше не создавать "текучий" метод SetFontProps?»
ОтветитьУдалить-- Виктор, прошу прощения - только сейчас до меня дошло, что Вы имели ввиду :-)
Помог Александр. Мне же показалось, что Вы против самого добавления метода SetFontProps.
Этот способ (добавление отдельного метода) мне видится единственным простым выходом для настройки свойств агрегированного объекта.
Разумеется, форма может быть другой. Я не стал бы настаивать на решении передавать ключи и значения элементов словаря в общем списке - такая форма указана мною в примере только для простоты.
Label := TLabel.Create(self).Parent(Panel1).Font(Color=clBlack).Position(X=10).Text('New Label');
ОтветитьУдалитьЭто типа с какой стороны хорошо?
NameRec:
Удалить«Это типа с какой стороны хорошо?»
-- В том виде, в каком Вы это записали (с учётом смысла и формы) - ни с какой.
Преимущества проявятся, если у Вас не открытый к расширению, а относительно фиксированный набор классов или скрипт-язык с утиной типизацией.
Вы не с того начали (начали мысленно "прикручивать" fluent-технику к построению компонентов VCL) отсюда и проблемы на каждом шагу.
Вместо этого можно было бы изучить саму технику, понять, на чём она основана, определить границы её применимости и только после этого решать: подходит ли инструмент (fluent-техника) к данной конкретной задаче или нет.
Пост Фаулера того же проглядеть (я давал на него ссылку), посмотреть success story (JOOQ и QueryDSL - ссылки я тоже давал).
Я уже сказал выше, что к описанию структуры компонентов в контейнерах Delphi (формы, фреймы, модули данных, и т.п.) эта техника не подходит и "прикручивать" её смысла нет.
Если Вам интересно, *почему* я делаю такой вывод - спросите, я постараюсь подробно ответить, что именно мешает. Но задавая вопросы, умерьте пожалуйста собственный апломб, поскольку в выбранном Вами ключе мне разговаривать с Вами неприятно.
Ну и чтобы меня не считали там каким-то "злыднем" и "приставалой", процитирую и соглашусь с (блин) Анонимными Имяреком (ну надо же так стесняться своего ФИО, какое-то просто неуважение по отношению к родителям. Ну или неуверенность в собственных мыслях вплоть до не-подписывания их).
ОтветитьУдалить>>Это окажется дорого, поскольку придётся создавать интерфейсы для учёта специфики каждого класса, а выигрыш будет совершенно незначительным.
ОТЛ! Можете под этой мыслью подписаться мной, чтобы она не выглядела анонимной.
>>Кроме того, лично я считаю, что строить компоненты VCL "вручную" следует только в крайних случаях.
Что стоит "я считаю"? Вы никогда не писали динамические интерфейсы, генерируемые по мета-данным БД? Рано или поздно каждый Р-БД разработчик приходит к необходимости писать свои мета-данные и некий "конфигуратор".
Более того - я прям-таки бил бы по рукам (голове) линейкой (ногами) дельфистов. Не порочьте честь и достоинство ООП-разработчиков! Знайте и умейте применять голенький ООП.
Своих учеников я всегда заставлял сначала на голой форме создавать интерфейс динамически. И только потом - WYSIWYG. И не только в Delphi, но и в Visual Studio.
>>IMHO применение fluent-техники уместно в ситуациях, когда разнообразие классов невелико (10-20 штук),
Отл. Т.е. начав использовать "текучесть" мы уже не можем масштабировать систему? О-как!
Я бы тогда изначально бы не стал использовать fluent, т.к. я - оптимист, желаю своей системе роста и процветания, конечно, не ограничив её 20 классами.
Респект! Вы доказали неэффективность "текучести".
>>а основной вариант использования - построение объектов в коде, что тоже - редкость.
Не.
>>В эти рамки ложится пока только SQL, причём только в случае, если есть причины не указывать его текстовом виде, а описывать в терминах объектов.
Это Вы часом не склейку строк имеете ввиду?
NameRec:
Удалить«Кроме того, лично я считаю, что строить компоненты VCL "вручную" следует только в крайних случаях.
-- Что стоит "я считаю"? Вы никогда не писали динамические интерфейсы»
-- Это и есть означенный крайний случай :-)
Есть ещё некоторые ситуации, когда компоненты приходится создавать "вручную".
В остальных случаях IMHO лучше "нарисовать" в дизайнере (не в дизайнере IDE Delphi, если быть точным) необходимый фрагмент, загрузить его в коде и вставить в нужное место.
«IMHO применение fluent-техники уместно в ситуациях, когда разнообразие классов невелико (10-20 штук),
-- Отл. Т.е. начав использовать "текучесть" мы уже не можем масштабировать систему? О-как!»
-- Почти правильно.
Лучше смотреть на fluent-технику как на некий DSL, расширение которого производится по определённым правилам. Например, в язык добавляется функция (класс, метод класса), после чего становится возможным его использование.
Подобно этому следует действовать с fluent-техникой.
Лучше пояснить это на примере, но если неинтересно, я не хочу тратить время.
Если интересно - спрашивайте, я постараюсь развёрнуто ответить.
Прощу принять во внимание, что системного описания "теории" fluent-DSL я не встречал (за исключением толковой статьи Фаулера), поэтому могу изложить только своё понимание, которое появилось в течение того самого года, который вызвал у Вас приступ веселья.
«Я бы тогда изначально бы не стал использовать fluent, т.к. я - оптимист, желаю своей системе роста и процветания, конечно, не ограничив её 20 классами.»
-- Я это уже понял :-)
Я же оценил его плюсы и ограничения и использую его как DSL.
«Респект! Вы доказали неэффективность "текучести".»
-- Благодарю за "респект", но с сожалением возвращаю его Вам :-)
Это Вы сами "доказали" себе его "неэффективность" неверно определив область, где эта техника действительно может принести заметную пользу.
«а основной вариант использования - построение объектов в коде, что тоже - редкость.
-- Не.»
-- А Вы убеждены, что понимаете, с чем спорите? ;-)
«В эти рамки ложится пока только SQL, причём только в случае, если есть причины не указывать его текстовом виде, а описывать в терминах объектов.
-- Это Вы часом не склейку строк имеете ввиду?»
-- Нет.
Кстати, один из примеров удачного применения текучего интерфейса:
Удалитьq3 = Job.objects.filter(pub_date__gte=datetime(2006, 1, 1))
if bla_bla:
q3 = q3.filter(location__city__exact="Cleveland", location__state__exact="Ohio")
Извиняйте, что на питоне - я сейчас руководство по Django читаю.
Да хоть на "языке ада".
УдалитьОдно дело "пишу на своём языке - потому, что на вашем не умею". А другое - "пишу на своём, потому что он - лучше". :-)