Re[6]: В поисках Грааля каждые 16 минут на Земле ...
От: maxkar  
Дата: 18.03.15 23:03
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>делает то же самое что и у тебя как я понимаю. Только кроме того еще binding с UI:

CS>Без binding c UI я так понимаю это всё смысла не имеет.

Не знаю Sciter, но да, вроде бы это самое и делает.
UI нужен в обязательном порядке. Ради него все и затевается. У меня по историческим причинам (внедрялась первая версия на AS3 под Flash) все построение UI делается кодом. Для твоего примера (плюс мои определеня ранее) оно будет примерно так:

// elt будет element
var elt = UI.form(
  UI.label('X'), UI.input(x, x.set),
  UI.label('Y'), UI.input(y, y.set),
  UI.text('Z1: '), UI.text(z1), UI.text(" and Z2 "), UI.text(z2)
);

// Можно использовать и короткую версию для ввода:
UI.input(x) === UI.input(x, x.set)


Многие вещи вроде text — всеядные. Т.е. можно кормить как значение T, так и Behavior[T]. Разнесение read/set в input (и прочих двухсторонних биндингах) в некоторых экзотических случаях удобнее. Например, completion на нем чуть более естественно выглядит. Там вместо x.set пойдет вызов функции, которая запускает загрузку completion и вызывает x.set. Некоторые фильтрации можно так же делать. Через слушателей на x мне это не очень нравится. Какой смысл слушать изменения модели и "исправлять" ее, если можно предотвратить такое изменение?

К html ни разу не пробовал биндинги писать. Если хочется html-шаблоны, нужно будет что-то придумывать.

А вообще я не уверен, что для веба (html) нужно что-то тяжелое. Лично мне кажется, что для веба удобнее что-то обычное многостраничное но с поддержкой работы в большом количестве вкладок (а также закладок). Там по необходимости через тот жe jquery дополнительную функциональность подключать. В этом плане Sciter как раз интересный пример. Если я правильно понимаю, он в основном "однооконный" по модели взаимодействия с пользователем (не предполагается, что пользователь все ссылки/переходы будет делать в новую вкладку), так что некоторые вещи можно делать не так, как в чистом web.
Re[5]: В поисках Грааля каждые 16 минут на Земле ...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 19.03.15 12:48
Оценка:
Здравствуйте, maxkar, Вы писали:

M>>>Всякие мелочи удобно реализуются. Тот же человекообразный Async на Behavior (вместо страшных promise в CPS будет Async.apply(fn, args...)). Желающие могут посмотреть реализацию async у меня.


I>>Покажи простецкий кейс — выполнить долгий аджакс запрос + несколько подготовительных в начале + несколько заключительных в конце. Все выполняется последовательно.

M>
M>var group = Async.group();
M>


Ужос. У тебя весь флоу раскидан непойми по чем. В любом месте самое главное находится где то еще.

I>>Вся эта цепочка должна поддерживать отмену, прогресс и очень хочется легкой, прозрачной отладки.


M>С отладкой все просто. Можно на нужные функции ставить брекпоинты и внутри них все отлаживать. Обработку ошибок вся цепочка берет на себя (если что-то упадет, все остальное тоже упадет).


В случае сложного сценария это приведет к тому, что бряки нужно ставить по самым разным файлам вместо одного. Я думаю ты вспотеешь пыль глотать.

M>А вот с отменой и прогрессом все не так просто как кажется. Здесь проблема именно в постановке задачи. Один из примеров (с group) я привел. Но дело в том, что это не всегда удобно. Например, у меня была задача


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


>>> Но пишется меньше, чем за неделю.

I>>Это сказки. Чтото реактивное можно и за неделю. А чтото концептуальное, годное для продакшна в JS, пишется долго и мучительно. За примерами см например bacon.js и подобные либы.

M>В каком смысле концептуальное? Что-то в духе неомодернистского абстракционизма? Так оно же неудобное!


Ну вот у тебя и вышло такой вот неомодернизм, красивый в теории, но неудобный на практике.

M>А вот по поводу "годное для продакшна" — это не сказки. Это реальность. Я делал это своими руками и выпускал на базе реактивного программирования реальные проекты (и большие, и учебные). Как ни странно, в реальных приложениях не так много различных UI-компонентов.


У меня в реальном проекте целая куча UI, рукопашного кода около 10мб, и там всё асинхронное-асинхронное-асинхронное.

M>Итого. К концу первого двухнедельного спринат я получаю все ядро


Если ты в отрыве от команды, то запросто. А если есть команда, то её нужно научить всем твоим приседаниям.
И вот реально проще взять обычные промисы, которые уже нативные чуть не всюду, и спокойно писать асинхронный код.
А в следующей версии JS можно будет убрать цепочки then в yield:

var cancel = new Cancel();
var progress = createProgress([5, 60, 25, 10], parentProgress);
var status = yield ajax('HEAD', url, cancel, progress[0]);

if(status.isValid())
   return Promise.reject(status.toError());

var archive = yield ajax('GET', url, cancel, progress[1]);
var content = yield unpack(archive, progress[2]);
var checksum = yield sha1.get(content, progress[3]);

return Promise.resolve({content:content, checksum:checksum});


Здесь кроме промисов совсем тонкий апи для отмены, прогреса и аджакса, самый мизер, прозрачнее некуда, бряки ставь куда хочешь прямо здесь.
Re[6]: В поисках Грааля каждые 16 минут на Земле ...
От: maxkar  
Дата: 23.03.15 14:57
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Ужос. У тебя весь флоу раскидан непойми по чем. В любом месте самое главное находится где то еще.

Это где это? Все идет так же последовательно. Ну ровно так же как в твоем примере с yield (и переписывается он туда механически). А group обычным программистам знать не нужно, это детали реализаций. Точно так же, как и детали реализации promise.


M>>С отладкой все просто. Можно на нужные функции ставить брекпоинты и внутри них все отлаживать. Обработку ошибок вся цепочка берет на себя (если что-то упадет, все остальное тоже упадет).

I>В случае сложного сценария это приведет к тому, что бряки нужно ставить по самым разным файлам вместо одного. Я думаю ты вспотеешь пыль глотать.
Да нет, не особо. Как-то так получается, что почти все нужные функции находятся в одном файле. А то, что находится в другом, обычно уже работает.

M>>А вот с отменой и прогрессом все не так просто как кажется. Здесь проблема именно в постановке задачи. Один из примеров (с group) я привел. Но дело в том, что это не всегда удобно. Например, у меня была задача

I>А это уже не интересно. На конкретной задаче вышло все не так удобно, как ты говорил. Отмена и прогресс это очень трудоемкие в отладке задачи, здесь хочется иметь максимум контроля.
А как же твой пример с Cancel? Где там максимум контроля? Где parent.cancel, например? Еще у меня есть претензии к parentProgress. Вот нет у меня такого и быть не может. Потому, что, например, метод getDepartmentState(deptId) может быть вызван из нескольких мест. И возвращает этот метод один и тот же промис для всех (ибо незачем одно и то же грузить 10 раз). Что там будет с progress? И не надо мне предлагать "все-таки запустить операцию два раза". Не хочу я под ограничения вашей технологии плясать.

Ты просто берешь некоторый "уже готовый" API и говоришь, что "вот как все просто с ним на задачах, подходящих для него". Это да, хорошо, если оно подходит под задачу. А если нет? Я не буду свои хотелки под API подгонять, я буду API подгонять под хотелки. Так что важен именно вопрос "хотелок". Реализация под них — дело чисто механическое.


M>>В каком смысле концептуальное? Что-то в духе неомодернистского абстракционизма? Так оно же неудобное!

I>Ну вот у тебя и вышло такой вот неомодернизм, красивый в теории, но неудобный на практике.
Пользовался. Удобный. Мне удобнее аппликативный вид чем промисы. Команда потихоньку к этому же склоняется


M>>А вот по поводу "годное для продакшна" — это не сказки. Это реальность. Я делал это своими руками и выпускал на базе реактивного программирования реальные проекты (и большие, и учебные). Как ни странно, в реальных приложениях не так много различных UI-компонентов.

I>У меня в реальном проекте целая куча UI, рукопашного кода около 10мб, и там всё асинхронное-асинхронное-асинхронное.

Ну и? Проблема в чем? Мы оцениваем вроде бы объем библиотечного кода. Это точно "библиотечные" 10мб? Какая разница, будут они использовать promise или мой async? И вдруг на моем async там всего 8мб получится?

M>>Итого. К концу первого двухнедельного спринат я получаю все ядро

I>Если ты в отрыве от команды, то запросто. А если есть команда, то её нужно научить всем твоим приседаниям.

Ну как сказать. Команду я научу за 2 часа реактивному программированию (это даже много, я презенташки проводил уже). На реактивщину у нас уже грамотный народ хочет слезть с ангуляра. На applicative api вокруг промисов есть задачи в трекере. Изучение UI api и набора базовых глаголов (типа той же сети) от используемого API не зависит. Нужно отдельный проект придумать, на котором его показать (ибо бюрократия и все такое, на реальном проекте приходится жрать кактус).

I>И вот реально проще взять обычные промисы, которые уже нативные чуть не всюду, и спокойно писать асинхронный код.

I>А в следующей версии JS можно будет убрать цепочки then в yield:
Ну посмотрел.
var group = Async.group();
var status = call(url, 'HEAD', group, 5);
var statusValue = group.apply(function(status) {
  if (status.isValid())
     throw status.toError();
  return status;
})

var archive = group.applyAsync(call, [url, 'HEAD', group', 60, statusValue]);
var content = group.apply(unpack, [archive], 25);
var checksum = group.apply(sha1.get, [content], 10);

return groupeapply(function(content, checksum) {
  return {content:content, checksum:checksum};
}, [content, checksum], 0);


Ну и какая принципиальная разница с yield? Ну чуть-чуть по-другому пишется. Async.apply используется вместо yield. Но какой-то концептуальной разницы я не вижу. Причем Aysnc работает уже сейчас и не нужно ждать, пока достаточно пользователей переедет на браузеры, которые поддерживают promise.

А что будет, если нужно выполнить несколько асинхронных действий параллельно. Причем с недетерминированным порядком ожидания. Т.е. "кто раньше готов исполняться, тот и выполняется".
var op1 = startOp1();
var op2 = startOp2();
var op3 = startOp3();

var opA = Async.applyAsync(doAsyncGood, [op1, op2]);
var opB = Async.applyAsync(doAsyncEvil, [op3, op2]);

return Async.apply(combineGoodAndEvil, [opA, opB]);


В зависимости от порядка завершения op1/op3 будет изменяться и порядок запуска doAsyncGood/doAsyncEvil. Это читаемо на yield/then будет? Обрати внимание, что случай одного/многих аргументов ничем не отличается. И для функций, возвращающих promise и возвращающих значение разница тоже не большая. И, кстати, что там с progress будет в этом сценарии?

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

А вот у меня про твой пример вопрос. sha1.get — это синхронная или асинхронная функция? И если синхронная, то как ее последний аргумент обрабатывается? Обрабатывается ли он yield или это все внутри функции происходит и она обязана за "weight" следить? И каждая асинхронная функция тоже обязана за переданным weight следить? Как-то накладно получается.

С бряками да, нужно ставить на функции. Но я ведь могу поменять Async.apply(smth, [...]) на Async.apply(function() { return smth.apply(null, arguments); }, [...]) и ставить бряки в ней. Но на моей практике это если и было нужно, то очень редко. А параллельное (менее детерминированное) выполнение в последовательном виде все равно не пишется (а если пишется, там все те же проблемы с брекпоинтами и недетерминированностью).

В общем, у меня Async API тоже тонкая прослойка над reactive. Включая отмену, прогресс и все остальные вызов (ajax обычно еще одним уровнем обкладывается ради выполнения требований). И я могу много разных API сделать. Только ты давай сначала показывай желаемый API или желаемые задачи. Потому что без этого дискуссия будет неконструктивная. Я могу собрать разные API для асинхронности, которые хорошо подходят под конкретный проект. И для любого API я могу подобрать требования, под которые этот API очень плохо подходит. Поэтому дискуссия "Покажи что-нибудь. А нет, это все сложно, вот мой API и у меня все просто" без предварительного описания требований особого смысла не имеет. Я в таком случае могу только показать, как на своей "элементной базе" я могу собирать разные API под разные задачи. И потом использовать эти API а не допиливать все по-месту.

P.S. Я не говорю, что Promises совсем отстой. Они удобны в некоторых классах задач. Только вопрос в том, что же это за классы. И второй вопрос: что делать, когда реальная задача не попадает ни в один из них?
Re[7]: В поисках Грааля каждые 16 минут на Земле ...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 24.03.15 09:50
Оценка: +1
Здравствуйте, maxkar, Вы писали:


I>>Ужос. У тебя весь флоу раскидан непойми по чем. В любом месте самое главное находится где то еще.

M>Это где это? Все идет так же последовательно. Ну ровно так же как в твоем примере с yield (и переписывается он туда механически). А group обычным программистам знать не нужно, это детали реализаций. Точно так же, как и детали реализации promise.

Я не вижу никакого "ровно так же". У тебя весь флоу, т.е. конкретная цепочка задается в функции. Последовательное выполнение это вобщем редкость. Часто бывают ветвления, итерации и тд и тд и тд. Вот, скажем, аджакс запрос может сфейлиться трижды. Опаньки — добавляем изменения в сам флоу. Потом, оказывается, ошибка должна браться не последняя, а самая первая — снова изменения в сам флоу. Как это у тебя будет — не ясно.

I>>В случае сложного сценария это приведет к тому, что бряки нужно ставить по самым разным файлам вместо одного. Я думаю ты вспотеешь пыль глотать.

M>Да нет, не особо. Как-то так получается, что почти все нужные функции находятся в одном файле. А то, что находится в другом, обычно уже работает.

А хочется все бряки поставить ровно в одной функции.


I>>А это уже не интересно. На конкретной задаче вышло все не так удобно, как ты говорил. Отмена и прогресс это очень трудоемкие в отладке задачи, здесь хочется иметь максимум контроля.

M>А как же твой пример с Cancel? Где там максимум контроля?

А что не так ? Все что нужно — доставить колбек отмены до всех точек вниз по цепочке вызовов.

>Где parent.cancel, например? Еще у меня есть претензии к parentProgress. Вот нет у меня такого и быть не может. Потому, что, например, метод getDepartmentState(deptId) может быть вызван из нескольких мест. И возвращает этот метод один и тот же промис для всех (ибо незачем одно и то же грузить 10 раз). Что там будет с progress? И не надо мне предлагать "все-таки запустить операцию два раза". Не хочу я под ограничения вашей технологии плясать.


Если тебе прогресс не нужен, значит у тебя другой кейс. Если твоя либа удобна только для твоих кейсов, так и пиши.

M>Ты просто берешь некоторый "уже готовый" API и говоришь, что "вот как все просто с ним на задачах, подходящих для него". Это да, хорошо, если оно подходит под задачу. А если нет? Я не буду свои хотелки под API подгонять, я буду API подгонять под хотелки. Так что важен именно вопрос "хотелок". Реализация под них — дело чисто механическое.


Я не брал никакой специальный апи. Я взял самый базовый уровень — аджакс, промисы и тд, то есть. Вот например в Cordova/Phonegap добавляется файловое апи и кое какое другое, все ровно то же — минимум приседаний.

I>>Ну вот у тебя и вышло такой вот неомодернизм, красивый в теории, но неудобный на практике.

M>Пользовался. Удобный. Мне удобнее аппликативный вид чем промисы. Команда потихоньку к этому же склоняется

Если команда 'потихоньку склоняется', значит дело не в удобстве а в чем то еще.

M>Ну и? Проблема в чем? Мы оцениваем вроде бы объем библиотечного кода. Это точно "библиотечные" 10мб? Какая разница, будут они использовать promise или мой async? И вдруг на моем async там всего 8мб получится?


А почему вдруг именно библиотечный код надо оценивать ? Вот его объем как раз не важен.

I>>Если ты в отрыве от команды, то запросто. А если есть команда, то её нужно научить всем твоим приседаниям.


M>Ну как сказать. Команду я научу за 2 часа реактивному программированию (это даже много, я презенташки проводил уже).


Это сказки. Реактивное программирование само по себе требует довольно большого опыта, т.к. это фактически полноценная кооперативная многозадачность. Не такая урезаная, как на промисах, а с кучей подводных камней.

I>>И вот реально проще взять обычные промисы, которые уже нативные чуть не всюду, и спокойно писать асинхронный код.

I>>А в следующей версии JS можно будет убрать цепочки then в yield:
M>Ну посмотрел.

M>Ну и какая принципиальная разница с yield? Ну чуть-чуть по-другому пишется. Async.apply используется вместо yield. Но какой-то концептуальной разницы я не вижу. Причем Aysnc работает уже сейчас и не нужно ждать, пока достаточно пользователей переедет на браузеры, которые поддерживают promise.


У тебя не просто по другому, у тебя везде косвенные вызовы. Это значит, что дебугером ты сначала будет ходить по кишкам твоей либы, а уже потом попадешь куда надо.
С учетом того, что аппликативно-реактивные либы сами по себе дебри, вариантов с отладкой нет — только мотаться по коду и ставить бряки то там, то здесь.

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


M>В зависимости от порядка завершения op1/op3 будет изменяться и порядок запуска doAsyncGood/doAsyncEvil. Это читаемо на yield/then будет? Обрати внимание, что случай одного/многих аргументов ничем не отличается. И для функций, возвращающих promise и возвращающих значение разница тоже не большая. И, кстати, что там с progress будет в этом сценарии?


Разумеется, будет абсолютно читабельно. Большей частью нужны не такие примитивные приседания, а более сложные вещи, их проще делать с внятными эвентами и тд и тд. Скажем, может понадобиться не просто отмена по месту, а полноценный пул операций, с отменой, прогрессом, восстановлением, повтором и тд и тд и тд. От твоей реактивщины здесь вообще никакого толку, а вот скажем внятный автомат с эвентами взлетит гораздо раньше.

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

M>А вот у меня про твой пример вопрос. sha1.get — это синхронная или асинхронная функция? И если синхронная, то как ее последний аргумент обрабатывается? Обрабатывается ли он yield или это все внутри функции происходит и она обязана за "weight" следить? И каждая асинхронная функция тоже обязана за переданным weight следить? Как-то накладно получается.

Асинхронная разумеется. Следить ни за чем не надо, createProgress создаёт список из прогрессов, сиречь колбеков.

M>С бряками да, нужно ставить на функции. Но я ведь могу поменять Async.apply(smth, [...]) на Async.apply(function() { return smth.apply(null, arguments); }, [...]) и ставить бряки в ней. Но на моей практике это если и было нужно, то очень редко. А параллельное (менее детерминированное) выполнение в последовательном виде все равно не пишется (а если пишется, там все те же проблемы с брекпоинтами и недетерминированностью).


У тебя все равно получаются косвенные вызовы на ровном месте.

M>В общем, у меня Async API тоже тонкая прослойка над reactive.


Которая, в свою очередь, очень толстая обертка вокруг колбеков-эвентов.

>Только ты давай сначала показывай желаемый API или желаемые задачи. Потому что без этого дискуссия будет неконструктивная.


Я уже показал, вполне достаточно

M>P.S. Я не говорю, что Promises совсем отстой. Они удобны в некоторых классах задач. Только вопрос в том, что же это за классы. И второй вопрос: что делать, когда реальная задача не попадает ни в один из них?


Я сильно сомневаюсь, что реактивщина может решать более широкий класс задач. Издержки просто конские. Более того — даже в менее ресурсоемких платформах, навроде дотнета или джавы, реактивщина все равно распыляет ресурсы за просто так.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.