Здравствуйте, lseder, Вы писали:
L>Привет, может кто-нибудь находил в инете инфу по метапрограммированию. L>Интересуют принципы выделения и организации низкоуровневой структуры, и L>методы конструирования мета-конструкций на основе предыдущего (нижнего) слоя понятий.
По моему наиболее близко на сегодняшний день, к сабжу.
Есть еще книги, "Порождающее программирование". "Фабрики разработки программ". И много много всего по паттернам, UML.
L>- Реализовать хотелось бы на javascript + sql (web kit html5), так как интересно сделать L>конструктор на чистом браузере (для тачскринов).
Здравствуйте, Undying, Вы писали:
U>Здравствуйте, WolfHound, Вы писали:
U>>>Зачем это записывать одной строчкой? У тебя число буковок в коде самоцель? WH>>У меня цель чтобы в коде небыло ни одной буквы которая не относится к решению задачи.
U>От отсутствия буковок (как и от увеличения количества слоев абстракции вообще) сущности никуда не деваются, а лишь становятся неявными. А код напичканный неявными сущностями, во-первых, сложно читать, во-вторых, если нужно сделать что-то нестандартное и требуется доступ к этим неявным сущностям, то появляются танцы с бубном и простыни кода на ровном месте.
Есть магическое слово "монада", дает ответы сразу на все вопросы, которые ты задаешь.
U>Например, если в зависимости от свойств события интервал Throttle нужно будет делать разный, то как измениться код на Rx? А если интервал будет зависеть от предшествующих событий?
Ты для начала напиши с помощью другой технологии пример что WolfHound привел. А потом найди пример, который в Rx плохо делается, а с другой технологией хорошо.
Здравствуйте, gandjustas, Вы писали:
U>>Например, если в зависимости от свойств события интервал Throttle нужно будет делать разный, то как измениться код на Rx? А если интервал будет зависеть от предшествующих событий? G>Ты для начала напиши с помощью другой технологии пример что WolfHound привел.
G>А потом найди пример, который в Rx плохо делается, а с другой технологией хорошо.
Ты на что отвечаешь вообще читаешь или умеешь только вопросом на вопрос отвечать? Я как раз и спрашиваю хорошо или плохо будет решаться на задача с нестандартным условием. Сам я ответить на этот вопрос не могу, т.к. Rx не знаю. В императивном стиле и при использовании псевдосинхронной записи код решения задачи с нестандартным условием останется тривиальным.
Здравствуйте, Undying, Вы писали:
U>Т.е. для чтения кода, использующего подобные библиотеки, нужно держать в памяти кучу мусорных знаний. Я как-то предпочитаю писать библиотеки, которые этого не требуют.
Где ты взял кучу я не понял.
Всего одно правило: Отписка от события сообщает источнику события что результат больше не нужен.
За то в твоем коде я вижу кучу мусора, который не нужен.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Undying, Вы писали:
U>От отсутствия буковок (как и от увеличения количества слоев абстракции вообще) сущности никуда не деваются, а лишь становятся неявными. А код напичканный неявными сущностями, во-первых, сложно читать, во-вторых, если нужно сделать что-то нестандартное и требуется доступ к этим неявным сущностям, то появляются танцы с бубном и простыни кода на ровном месте.
Ну давай разбираться какие у нас в этом коде есть сущности.
Начнем с того что у нас есть сущность: поток событий.
Rx делает ее явной.
var textChanged = from evt in Observable.FromEvent<EventArgs>(txt, "TextChanged")
select ((TextBox)evt.Sender).Text;
Это не слой абстракции. Это прикладная сущность.
Именно в этих терминах задача и сформулирована.
Можешь попробовать сформулировать ее по-другому.
Далее мы этот поток фильтруем:
Тут у нас два действия.
1)Глотать события пока интервал между ними не превысит секунду.
2)Глотать идущие подряд одинаковые события.
var input = textChanged
.Throttle(TimeSpan.FromSeconds(1))
.DistinctUntilChanged();
Код в точности повторяет описание того что делается.
И так далее...
U>Например, если в зависимости от свойств события интервал Throttle нужно будет делать разный, то как измениться код на Rx? А если интервал будет зависеть от предшествующих событий?
Вот тебе домашнее задание:
Реализовать то, что ты хочешь, используя эти комбинаторы.
/// <summary>
/// Records the timestamp for each value in an observable sequence.
/// </summary>
/// <param name="source">Source sequence to timestamp values for.</param>
/// <returns>An observable sequence with timestamp information on values.</returns>public static IObservable<Timestamped<TSource>> Timestamp<TSource>(this IObservable<TSource> source)
/// <summary>
/// Applies an accumulator function over an observable sequence and returns each intermediate result. The specified seed value is used as the initial accumulator value.
/// </summary>
/// <param name="source">An observable sequence to accumulate over.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="accumulator">An accumulator function to be invoked on each element.</param>
/// <returns>An observable sequence containing the accumulated values.</returns>public static IObservable<TAccumulate> Scan<TSource, TAccumulate>(this IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
/// <summary>
/// Filters the elements of an observable sequence based on a predicate.
/// </summary>
/// <param name="source">An observable sequence whose elements to filter.</param>
/// <param name="predicate">A function to test each source element for a condition.</param>
/// <returns>An observable sequence that contains elements from the input sequence that satisfy the condition.</returns>public static IObservable<TSource> Where<TSource>(this IObservable<TSource> source, Func<TSource, bool> predicate)
/// <summary>
/// Projects each element of an observable sequence into a new form.
/// </summary>
/// <param name="source">A sequence of elements to invoke a transform function on.</param>
/// <param name="selector">A transform function to apply to each source element.</param>
/// <returns>An observable sequence whose elements are the result of invoking the transform function on each element of source.</returns>public static IObservable<TResult> Select<TSource, TResult>(this IObservable<TSource> source, Func<TSource, TResult> selector)
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
U>От отсутствия буковок (как и от увеличения количества слоев абстракции вообще) сущности никуда не деваются, а лишь становятся неявными. А код напичканный неявными сущностями, во-первых, сложно читать, во-вторых, если нужно сделать что-то нестандартное и требуется доступ к этим неявным сущностям, то появляются танцы с бубном и простыни кода на ровном месте.
это все верно, но это не всё. если бы это был единственный критерий, то мы бы до сих пор писали на ассемблере и радовались...
второй и более важный и критичный критерий — это каким кол-вом проявленных сущностей в единицу времени человек может управлять осознанно.
к сожалению, это очень маленькое число — и поэтому приходится разбивать код на функции, библиотеки, вводить промежуточные абстракции и т.д.
если учитывать эти оба фактора, то задача ставится по другому: какие сущности сделать явными, а какие скрыть и сделать неявными, причем чем больше сущностей удастся скрыть, тем сильнее повысятся возможности управляемости теми сущностями, которые остались не скрытыми и прописаны явно.
если брать mainstream, то в разряд неявных сущностей переведены такие вещи как: схема размещения переменных по регистрам, генерация последовательности ассемблерных команд, управление памятью, управление потоком ошибок и т.д.
да, все это уменьшило наши возможности по управлению этими вещами. например, если в той же Java или .Net-е необходимо какая-то особенная работа с памятью, то это требует нетривиальных усилий.
но эти ограничения помогают сосредоточиться на важном: на логике программы, не увязая в мелочах.
зы
если брать Rx, то его лаконизм позволяет сосредоточиться на логике управления потоками сообщений, при этом получая минимальные оверхеды по времени отклика.
ззы U> Например, если в зависимости от свойств события интервал Throttle нужно будет делать разный, то как измениться код на Rx? А если интервал будет зависеть от предшествующих событий?
в крайнем случае, по месту придется написать свою функцию MyThrottle, расковыряв Reflector-ом стандартную функцию Throttle
Здравствуйте, Undying, Вы писали:
U>Здравствуйте, gandjustas, Вы писали:
U>>>Например, если в зависимости от свойств события интервал Throttle нужно будет делать разный, то как измениться код на Rx? А если интервал будет зависеть от предшествующих событий? G>>Ты для начала напиши с помощью другой технологии пример что WolfHound привел.
U>http://rsdn.ru/forum/philosophy/4313117.1.aspx
Трижды читал этот код, но не понял. Важный функционал скрыт в каком-то SlyFilter, зато наружу выставлены детали реализации workflow.
G>>А потом найди пример, который в Rx плохо делается, а с другой технологией хорошо.
U>Ты на что отвечаешь вообще читаешь или умеешь только вопросом на вопрос отвечать? Я как раз и спрашиваю хорошо или плохо будет решаться на задача с нестандартным условием. Сам я ответить на этот вопрос не могу, т.к. Rx не знаю. В императивном стиле и при использовании псевдосинхронной записи код решения задачи с нестандартным условием останется тривиальным.
Ну Rx поддерживает псевдосинхронную запись с помощью yield return, а в худшем случае все закончится написанием своего комбинатора, что обычно не очень сложно.
Здравствуйте, gandjustas, Вы писали:
G>Трижды читал этот код, но не понял.
Значит, у императивщиков и функциональщиков точно совершенно разные принципы мышления. Соответственно функциональщики не могут понять простейший императивный код, а императивщики наоборот. Поэтому дискуссия бессмысленна, у нас совершенно разные представления о простом и сложном.
G>Важный функционал скрыт в каком-то SlyFilter, зато наружу выставлены детали реализации workflow.
Точно также как в Rx важный функционал скрыт в функции Throttle.
Здравствуйте, Undying, Вы писали:
U>Здравствуйте, gandjustas, Вы писали:
G>>Трижды читал этот код, но не понял.
U>Значит, у императивщиков и функциональщиков точно совершенно разные принципы мышления. Соответственно функциональщики не могут понять простейший императивный код, а императивщики наоборот. Поэтому дискуссия бессмысленна, у нас совершенно разные представления о простом и сложном.
да мне как-бы пофиг, если императивно код записывается проще, то я предпочту такой стиль. Но ты показал десятки строк против трех. Причем твои десятки в разы менее понятны.
G>>Важный функционал скрыт в каком-то SlyFilter, зато наружу выставлены детали реализации workflow.
U>Точно также как в Rx важный функционал скрыт в функции Throttle.
Он предельно прост (ибо комбинатор) и для него есть документация. SlyFilter обоими достоинствам необладает.
L>Марти Фаулер. Архитектура корпоративных программных приложений.
спасибо, посмотрю. но моя задача по размерам пока не тянет на корпоративные размеры,
хотя общие принципы разработки знать необходимо.
L>По моему наиболее близко на сегодняшний день, к сабжу. L>Есть еще книги, "Порождающее программирование". "Фабрики разработки программ". И много много всего по паттернам, UML.
"Порождающее программирование" наиболее близко к теме, но книгу чарнецки в Украине купить невозможно.
L>>- Реализовать хотелось бы на javascript + sql (web kit html5), так как интересно сделать L>>конструктор на чистом браузере (для тачскринов). L>А зачем?
для iPad-а и других тачскринов.
Здравствуйте, DarkGray, Вы писали:
DG>если брать mainstream, то в разряд неявных сущностей переведены такие вещи как: схема размещения переменных по регистрам, генерация последовательности ассемблерных команд, управление памятью, управление потоком ошибок и т.д.
Обрати внимание все что ты перечислил это аппаратные, а не бизнес сущности. В бизнес логике есть, к примеру, сущность "сложение", при этом вопрос какие регистры будут задействованы и какая память использована это лишние сущности отсутствующие в логическом алгоритме. Поэтому скрывать аппаратные сущности можно и нужно. При условии, конечно, что это не приводит к критической просадке производительности на том классе задач, для решения которых предназначен язык/библиотека.
Логические сущности не являются лишними, поэтому скрывая их очень легко затруднить понимание кода и усложнить решение реальных задач. Поэтому лучшими библиотеками являются те, которые решают задачи используя минимум абстракций. Т.к. при необходимости написать обертку скрывающую неиспользуемые логические сущности под конкретную задачу проблемы не составляет, а простота доступа к логическим сущностям позволяет решать нестандартные задачи без лишних сложностей.
DG>в крайнем случае, по месту придется написать свою функцию MyThrottle, расковыряв Reflector-ом стандартную функцию Throttle
Т.е. при небольшом усложнении задачи происходит кардинальный скачок сложности решения. Это плохо, т.к. приводит к ситуациям, когда то что с точки зрения пользователя выглядит копеечной работой оказывается очень сложным в программной реализации.
DG>>если брать mainstream, то в разряд неявных сущностей переведены такие вещи как: схема размещения переменных по регистрам, генерация последовательности ассемблерных команд, управление памятью, управление потоком ошибок и т.д.
U>Обрати внимание все что ты перечислил это аппаратные, а не бизнес сущности.
во-первых, какие бизнес-сущности скрывает Rx?
во-вторых, какую аппаратную сущность скрывает, например, exception, или using, или автоматический деструктор?
также можно привести много других примеров скрытия той или иной логики: виртуальные функции, linq, wcf, wpf, com, sql и т.д.
U> В бизнес логике есть, к примеру, сущность "сложение", при этом вопрос какие регистры будут задействованы и какая память использована это лишние сущности отсутствующие в логическом алгоритме. Поэтому скрывать аппаратные сущности можно и нужно. При условии, конечно, что это не приводит к критической просадке производительности на том классе задач, для решения которых предназначен язык/библиотека.
и какую бизнес-сущность описывает, например, операция foreach или while?
U>Логические сущности не являются лишними, поэтому скрывая их очень легко затруднить понимание кода и усложнить решение реальных задач. Поэтому лучшими библиотеками являются те, которые решают задачи используя минимум абстракций. Т.к. при необходимости написать обертку скрывающую неиспользуемые логические сущности под конкретную задачу проблемы не составляет, а простота доступа к логическим сущностям позволяет решать нестандартные задачи без лишних сложностей.
перечисли, пожалуйста, хотя бы штук 30 таких логических сущностей, которые скрывать не стоит, чтобы понятно было о чем речь
DG>>в крайнем случае, по месту придется написать свою функцию MyThrottle, расковыряв Reflector-ом стандартную функцию Throttle
U>Т.е. при небольшом усложнении задачи происходит кардинальный скачок сложности решения. Это плохо, т.к. приводит к ситуациям, когда то что с точки зрения пользователя выглядит копеечной работой оказывается очень сложным в программной реализации.
и поэтому все копеечные задачи (при том что их большинство) надо решать за 100 рублей каждую?
Здравствуйте, DarkGray, Вы писали:
DG>также можно привести много других примеров скрытия той или иной логики: виртуальные функции, linq, wcf, wpf, com, sql и т.д.
Мы (кажется, с тобой) как-то дискутировали на тему, на сколько сильно можно скрыть все ненужные в данный момент сущности, при написании команды, приближенной к естественному языку. Использовался пример с принтером: надо напечатать документ. Ты говорил, что количество уточняющих деталей (например, какой именно принтер или как именно надо напечатать) не позволит легко пользоваться такими командами.
Также дискутировали и в этой теме.
Так всё таки — можно?
Не приведёт ли всё это "скрытие той или иной логики: виртуальные функции, linq, wcf, wpf, com, sql и т.д." к некоторому подобию естественного языка?
Я пытаюсь понять, где проходит граница между "можно скрыть" и "комбинаторным взрывом"?
R3>Не приведёт ли всё это "скрытие той или иной логики: виртуальные функции, linq, wcf, wpf, com, sql и т.д." к некоторому подобию естественного языка?
естественный язык очень убогий, как минимум из-за отсутствия встроенного способа описывать деревья и графы
R3>Мы (кажется, с тобой) как-то дискутировали на тему, на сколько сильно можно скрыть все ненужные в данный момент сущности, при написании команды, приближенной к естественному языку. Использовался пример с принтером: надо напечатать документ. Ты говорил, что количество уточняющих деталей (например, какой именно принтер или как именно надо напечатать) не позволит легко пользоваться такими командами.
R3>Я пытаюсь понять, где проходит граница между "можно скрыть" и "комбинаторным взрывом"?
чтобы не было комбинаторного взрыва, как раз и используется скрытие значительной части информации, которая считается верной и известной априори.
возьмем команду:
document.print()
в простейшем случае ее достаточно, если есть всем известные умолчания (и которые мы как раз и скрыли):
что print — это распечатать на принтере,
что принтер один,
что печатать надо одну копию,
настройки печати по умолчанию,
что печатается весь документ
и т.д.
но допустим принтера два: цветной и черно-белый, и вот уже хочется указывать принтер
document.print(to:color-printer)
нужно несколько копий
document.print(to:color-printer, quantity:5)
и т.д.
и это приводит к нескольким большим темам:
как описывать умолчания так, чтобы их легко можно было переопределять в уточняющем виде?
как описывать умолчания так, чтобы они были устойчивы к изменениям?
как построить язык взаимодействия, чтобы в нем легко описывались "расширяющиеся круги" уточнений?
Здравствуйте, DarkGray, Вы писали:
R3>>Не приведёт ли всё это "скрытие той или иной логики: виртуальные функции, linq, wcf, wpf, com, sql и т.д." к некоторому подобию естественного языка? DG>естественный язык очень убогий, как минимум из-за отсутствия встроенного способа описывать деревья и графы
Да, поэтому я и использовал слово "подобие". Хотя в этом "подобии" в итоге может быть использованы только буквы, цифры, пробелы и знаки пунктуации, исключая все правила.
DG>но допустим принтера два: цветной и черно-белый, и вот уже хочется указывать принтер DG>document.print(to:color-printer)
Например, в этом случае выбор принтера может следовать из свойств документа: в каком статусе документ находится (драфт или релиз), тот принтер и будет выбран.
DG>нужно несколько копий DG>document.print(to:color-printer, quantity:5)
Например, в этом случае выбор количества копий может следовать из того, для чего печатается документ. Например, для себя (в статусе драфт — сделать вычитку) достаточно одной копии, а для рассылки (релиз) — в зависимости от количества участников договора, который и содержится в этом документе.
Я к тому, что наши процессы (бизнес-процессы, процессы жизнидеятельности) уже описаны или могут быть описаны. Но мы этим не пользуемся в полной мере.
Пример:
Программист создал форму и планирует сделать на ней две кнопки: ОК и Cancel. Соответственно, он, например, в дизайнере кидает их на форму.
Но, например, у Microsoft есть документ, который описывает, как должны быть расположены эти кнопки.
Получается, что программист делает то, что уже было описано, как делать.
Почему программист не может просто, например, поставить где-то пару галочек: "форма имеет кнопку закрытия с сохранением ввода" и "форма имеет кнопку закрытия с отклонением ввода", а всё остальное будет сделано автоматически?
Следующий уровень — "форма содержит такой-то бизнес-объект".
Следующий — "приложение управляет таким-то бизнес-объектом".
Потом выяснится, что приложения не нужны. Нужны только бизнес-объекты. Данные — Действие — Результат.
Вот тогда и произойдёт следующий шаг в эволюции программирования.
DG>и это приводит к нескольким большим темам: DG>как описывать умолчания так, чтобы их легко можно было переопределять в уточняющем виде? DG>как описывать умолчания так, чтобы они были устойчивы к изменениям? DG>как построить язык взаимодействия, чтобы в нем легко описывались "расширяющиеся круги" уточнений?
Здравствуйте, DarkGray, Вы писали:
DG>во-первых, какие бизнес-сущности скрывает Rx?
Похоже скрывает даже время глотания событий, т.к. судя по ответу Wolfhound'а даже тривиальнейшее добавление условия делается не так-то просто.
DG>во-вторых, какую аппаратную сущность скрывает, например, exception, или using, или автоматический деструктор?
Логически у нас есть задачи: прервать выполнение с ошибкой и освободить ресурсы после того как объект стал ненужен. Эти логические задачи и решает то, что ты перечислил, скрывая от нас механику решения, которая с логической точки зрения является мусором.
DG>и какую бизнес-сущность описывает, например, операция foreach или while?
Логически у нас есть задачи: выполнить для каждого элемента и повторить. Эти логические задачи решаются в шарпе с помощью foreach и while.
DG>перечисли, пожалуйста, хотя бы штук 30 таких логических сущностей, которые скрывать не стоит, чтобы понятно было о чем речь
Это сущности, которые заметны или могут быть заметны для пользователя (уточню, что пользователем может быть не только человек, но и программное окружение). Например, время глотания события заметно для пользователя, т.к. от него зависит время отклика на действие, поэтому это логическая сущность. Также, к примеру, заметен размер кнопки или способ шифрации данных сервером.
Здравствуйте, Real 3L0, Вы писали:
R3>Пример: R3>Программист создал форму и планирует сделать на ней две кнопки: ОК и Cancel. Соответственно, он, например, в дизайнере кидает их на форму. R3>Но, например, у Microsoft есть документ, который описывает, как должны быть расположены эти кнопки. R3>Получается, что программист делает то, что уже было описано, как делать. R3>Почему программист не может просто, например, поставить где-то пару галочек: "форма имеет кнопку закрытия с сохранением ввода" и "форма имеет кнопку закрытия с отклонением ввода", а всё остальное будет сделано автоматически? R3>Следующий уровень — "форма содержит такой-то бизнес-объект". R3>Следующий — "приложение управляет таким-то бизнес-объектом". R3>Потом выяснится, что приложения не нужны. Нужны только бизнес-объекты. Данные — Действие — Результат. R3>Вот тогда и произойдёт следующий шаг в эволюции программирования.
Дык уже есть. Бери 1с, Dynamics, SharePoint. Там ты не пишешь приложение, там ты создаешь объекты, описываешь действия, и представления результатов.
Здравствуйте, gandjustas, Вы писали:
G>Дык уже есть. Бери 1с, Dynamics, SharePoint. Там ты не пишешь приложение, там ты создаешь объекты, описываешь действия, и представления результатов.
Ну и как "ложится" вышеприведённый пример с принтером в эти системы?
Здравствуйте, Real 3L0, Вы писали:
R3>Здравствуйте, gandjustas, Вы писали:
G>>Дык уже есть. Бери 1с, Dynamics, SharePoint. Там ты не пишешь приложение, там ты создаешь объекты, описываешь действия, и представления результатов.
R3>Ну и как "ложится" вышеприведённый пример с принтером в эти системы?
Создаешь объект "принтер", прописываешь ему свойства, задаешь действие — печатать, которое может спросить файл например.
Здравствуйте, gandjustas, Вы писали:
G>>>Дык уже есть. Бери 1с, Dynamics, SharePoint. Там ты не пишешь приложение, там ты создаешь объекты, описываешь действия, и представления результатов. R3>>Ну и как "ложится" вышеприведённый пример с принтером в эти системы? G>Создаешь объект "принтер", прописываешь ему свойства, задаешь действие — печатать, которое может спросить файл например.
А после этих действий, упомянутый тобой объект "файл" будет знать, что теперь его можно печатать? Или надо дополнительно какие-то связи прописывать?