Прекрасно, когда есть из чего выбрать. Мне фломастеры из rxdart-коробки больше по душе, потому что я так или иначе последние три года пользуюсь ReactiveX в составе RxJava, RxQt, RxCpp в той или иной степени, с их подкупающей мощью обработки данных посредством цепочек операторов, и поэтому я убиваю двух зайцев, используя rxdart как управление состоянием UI и для работы с данными.
Ну, во-первых, насколько часто нам приходится писать счетчики? Начиная даже самый простой проект, потихоньку приходишь к усложнению. А вот представьте, Вам потребовалось вставить обратный отсчет для блокировки кнопки между нажатиями. Обойдетесь без фонового потока? А если нет, как будете реализовывать?
Позвольте представить решение в рамках концепции данной статьи:
/// делаем задержку в 3 секунды, с уведомлением через каждую секунду.
class _Counter {
int _count;
/// Счетчик обратного отсчета
int _countdown = 0;
int get count => _count;
_Counter(this._count)
: this.onCounterUpd = BehaviorSubject<int>.seeded(_count),
this.onCountdownUpd = BehaviorSubject<int>.seeded(0);
final BehaviorSubject<int> onCounterUpd;
/// Евент обратного отсчета
final BehaviorSubject<int> onCountdownUpd;
/// Вынесем инкремент за пределы виджета, добавим генерацию события.
Future incrementCounter() async {
if(_countdown <= 0) {
onCounterUpd.add(++_count);
/// Запуск таймера, с вочдогом и генерацией евентов.
_countdown = 3;
onCountdownUpd.add(_countdown);
Observable
.periodic(Duration(seconds: 1), (_) => --_countdown)
.take(3)
.listen((e) => onCountdownUpd.add(_countdown));
}
}
}
Приходится повторяться специально для Вас, что мне не нравится раздутость кода, в которое обернуты оба решения, и я не применяю MVI в том виде, в котором он есть. Вы не вчитываетесь, а видимо, просто еще на утреннем автовзводе от общения в telegram.
Я бы с удовольствием увидел Ваши решения счетчика на BLoC, MVU, и сравнить количество строк, при одинаковом результате. Попробуйте принять, как данность, что это статься просто про другой подход к решению задач программирования. Пожалуйста. Спасибо.
Да я в курсе и нет, я не против. Каждый выбирает для себя. Я за стиль, простоту, изящество решений, по мне так этому всему отвечает именно ReactiveX. Он закрывает для меня почти все вопросы по взаимодействию и с View и между всеми слоями архитектуры с минимумом кода и максимумом выразительности. Это я еще не беру в расчет мощь его цепочек операторов.
Я честно наваял часть проекта на MVU, но потом убился о количество кода, которое надо добавлять. Да, можно было написать генератор, но код-то никуда бы ни делся и болтался, мозоля глаза, да и хороший генератор писать тоже надо дофига времени на отладку.
MVI я не использую в чистом виде по этой же причине, но мне импонирует immutable-way, и передача упакованного состояния в одном флаконе. Позже я черкану статью о своей реализации.
Дело в том, что реактивщина не только про стейты. Ведь она позволяет обмениваться событиями между любыми объектами, и невизуальными в бизнес-слое, и все это в едином стиле. Кроме того, мощь reactive-way проявляется и в потоковой обработке данных, используя операторы. Внося реактивность в проект даже на стадии обмена сообщениями, можно впоследствии постепенно начинать применять ее все шире.
Думаю да, опечатка, я вроде аккуратно переводил. Возможно, для автора английский не совсем прям, как родной.
Два момента:
Опыт, который упоминается в статье — это опыт не мой, а автора. Но, ссылаясь на лично свой, то для примера выделение слоев абстракций для работы с БД, файловыми системами помогло мне лишь однажды из 10+ проектов. Так что да — в моем случае это была лишняя работа. Особенно это касается работы с Android приложениями, где локально sqlite вообще безальтернативна.
На самом деле эта статься интересна, как стартовая для описания dart-библиотеки rx_command, и после утомительного boilerplate InheritedWidgets & BLoC для меня это действительно находка. Вот, на днях переведу остальное.
Ну, автор высказывается по поводу избыточного вертикального «расслоения», а эта библиотека — фундамент для Managers, другими словами, разделение архитектуры по горизонтали.
Вдогон к предыдущему комментарию.
Вы знаете, а ведь я вспомнил, что Фотошоп был очень прожорлив по памяти, так вот скоре всего тяжелые операции с битмапами для скорости маппировались там прямо в память.
Интересно. В этом что-то есть. Я вдруг подумал, что парочка дополнительных евентов для UndoWatcher: cmdAdded/cmdRemoved позволила бы очень элегантно реализовать что-то вроде этого. В принципе, и сейчас можно, но достаточно коряво. Думаю, пойдет в wish-list.
Наверное, следует рассматривать разные подходы. Делать профилирование каждой операции. Некоторые можно заменить "действиями", а где-то возможно, придется сбрасывать 20 метров на диск. Сразу так и не скажешь. Специфика в том, битмапы, это не векторая графика, тут после ряда undo/redo можно такое на выходе получить…
На первый взгляд, все-таки лучше сохранять действия — выглядит так, словно это будет компактнее и быстрее загружаться.
К примеру
BlurUndo: сохраняет процент размытия. Redo() — накладывает маску (слой) с размытием на текущий битмап, Undo() — удаляет маску (слой)
StretchUndo: с растягиваниями уже посложнее, Undo() вряд ли вернет прежнее качество
Я бы поинтересовался на профильных форумах, присмотрелся к Фотошопу. Не пользуюсь им уже более 10 лет, со времен Photoshop v.6. Там довольно шустро все было.
Вы верно отметили, Qt-шный фреймворк был для меня стартовой точкой, с ним я работал лет пять, наверное. Отличное решение, я в него добавлял сериализацию (так для ясности я назову store/restore) для проектов нашей группы, а так же версионность. Макросы там реализованы неправильно, имхо. Пришлось поправлять.
Именно это все я собрал воедино в Java, так как на сегодня Java/JavaFx/Android — мое направление развития. UndoWatcher всего лишь qt-шные signals/slots, реализованные средствами Java. Это read-only информация о происходящем со стеком. QUndoStack, раз уж Вы его упомянули, именно так сигналит клиентам о своем состоянии.
А так-то да, на вкус и цвет, как говорится.
Прекрасно, когда есть из чего выбрать. Мне фломастеры из
rxdart
-коробки больше по душе, потому что я так или иначе последние три года пользуюсь ReactiveX в составеRxJava
,RxQt
,RxCpp
в той или иной степени, с их подкупающей мощью обработки данных посредством цепочек операторов, и поэтому я убиваю двух зайцев, используяrxdart
как управление состоянием UI и для работы с данными.Ну, во-первых, насколько часто нам приходится писать счетчики? Начиная даже самый простой проект, потихоньку приходишь к усложнению. А вот представьте, Вам потребовалось вставить обратный отсчет для блокировки кнопки между нажатиями. Обойдетесь без фонового потока? А если нет, как будете реализовывать?
Позвольте представить решение в рамках концепции данной статьи:
после чего делаем FAB реактивным,
и добавляем рекативное же упоминание
Приходится повторяться специально для Вас, что мне не нравится раздутость кода, в которое обернуты оба решения, и я не применяю MVI в том виде, в котором он есть. Вы не вчитываетесь, а видимо, просто еще на утреннем автовзводе от общения в
telegram
.Я бы с удовольствием увидел Ваши решения счетчика на BLoC, MVU, и сравнить количество строк, при одинаковом результате. Попробуйте принять, как данность, что это статься просто про другой подход к решению задач программирования. Пожалуйста. Спасибо.
Да я в курсе и нет, я не против. Каждый выбирает для себя. Я за стиль, простоту, изящество решений, по мне так этому всему отвечает именно ReactiveX. Он закрывает для меня почти все вопросы по взаимодействию и с View и между всеми слоями архитектуры с минимумом кода и максимумом выразительности. Это я еще не беру в расчет мощь его цепочек операторов.
Я честно наваял часть проекта на MVU, но потом убился о количество кода, которое надо добавлять. Да, можно было написать генератор, но код-то никуда бы ни делся и болтался, мозоля глаза, да и хороший генератор писать тоже надо дофига времени на отладку.
MVI я не использую в чистом виде по этой же причине, но мне импонирует immutable-way, и передача упакованного состояния в одном флаконе. Позже я черкану статью о своей реализации.
в процессе. Есть прикольная архитектура MVI, я ее применяю и в процессе слегка модернизирую. Вот спустя месяцок накидаю статью с реальным примером.
Да, согласен, косяк. Даже два.
Дело в том, что
реактивщина
не только про стейты. Ведь она позволяет обмениваться событиями между любыми объектами, и невизуальными в бизнес-слое, и все это в едином стиле. Кроме того, мощьreactive-way
проявляется и в потоковой обработке данных, используя операторы. Внося реактивность в проект даже на стадии обмена сообщениями, можно впоследствии постепенно начинать применять ее все шире.Обратите внимание, это для простоты восприятия. Никто не мешает вам сделать класс, и убрать его в business-слой.
Спасибо, добавлю. К сожалению, нет возможности проверить, могу только положиться на Вашу информацию.
удачи!
Да, просто добавьте строки
В i18n.dart появится
и можно использовать
Думаю да, опечатка, я вроде аккуратно переводил. Возможно, для автора английский не совсем прям, как родной.
Два момента:
sqlite
вообще безальтернативна.InheritedWidgets
&BLoC
для меня это действительно находка. Вот, на днях переведу остальное.Вдогон к предыдущему комментарию.
Вы знаете, а ведь я вспомнил, что Фотошоп был очень прожорлив по памяти, так вот скоре всего тяжелые операции с битмапами для скорости маппировались там прямо в память.
Интересно. В этом что-то есть. Я вдруг подумал, что парочка дополнительных евентов для
UndoWatcher
:cmdAdded/cmdRemoved
позволила бы очень элегантно реализовать что-то вроде этого. В принципе, и сейчас можно, но достаточно коряво. Думаю, пойдет в wish-list.Наверное, следует рассматривать разные подходы. Делать профилирование каждой операции. Некоторые можно заменить "действиями", а где-то возможно, придется сбрасывать 20 метров на диск. Сразу так и не скажешь. Специфика в том, битмапы, это не векторая графика, тут после ряда undo/redo можно такое на выходе получить…
На первый взгляд, все-таки лучше сохранять действия — выглядит так, словно это будет компактнее и быстрее загружаться.
К примеру
CropUndo
: хранит координаты прямоугольника обрезки.Redo()
— применяет обрезку, сохраняя обрезанное,Undo()
— возвращает обрезанное, совершая операцию "склеивания"BlurUndo
: сохраняет процент размытия.Redo()
— накладывает маску (слой) с размытием на текущий битмап,Undo()
— удаляет маску (слой)StretchUndo
: с растягиваниями уже посложнее,Undo()
вряд ли вернет прежнее качествоЯ бы поинтересовался на профильных форумах, присмотрелся к Фотошопу. Не пользуюсь им уже более 10 лет, со времен Photoshop v.6. Там довольно шустро все было.
В части "О дизайне библиотеки" я как раз об этом пишу, делая отсыл на вики.
Вы верно отметили, Qt-шный фреймворк был для меня стартовой точкой, с ним я работал лет пять, наверное. Отличное решение, я в него добавлял сериализацию (так для ясности я назову store/restore) для проектов нашей группы, а так же версионность. Макросы там реализованы неправильно, имхо. Пришлось поправлять.
Именно это все я собрал воедино в Java, так как на сегодня Java/JavaFx/Android — мое направление развития.
UndoWatcher
всего лишь qt-шные signals/slots, реализованные средствами Java. Это read-only информация о происходящем со стеком.QUndoStack
, раз уж Вы его упомянули, именно так сигналит клиентам о своем состоянии.А так-то да, на вкус и цвет, как говорится.