Здравствуйте, zelenprog, Вы писали:
Z>Значит, дожен быть еще какой-то код, который: Z>1) при появлении новой информации о ходе выполнения отслеживает "разницу" по сравнению с прошлым состоянием, и делает список выполненных действий. Z>2) каким-то образом оповещает UI и передает в UI этот список.
Список или не список, эти данные ничем не отличаются от других данных, которыми обмениваются слои программы.
На стороне бизнес логики данные формируются в некотором абстрактном виде, не заточенные под отображение в UI (т.е. без цветов, шрифтов и т.п.).
Далее данные передаются в слой UI через callback или отдельным вызовом со стороны UI.
Логика UI уже решает, где и как эти данные отобразить, в т.ч. каким цветом и т.д.
Re: Clean Architecture. Отображение в GUI процесса выполнения длительной операци
Здравствуйте, zelenprog, Вы писали:
Z>А как сделать, чтобы происходило изменение пользовательского интерфейса именно в процессе выполнения длительной бизнес-операции?
Синхронная операция возвращает значение, асинхронная — Promise, длительная с уведомлениями — асинхронный стрим событий. Примерно так:
interface AsyncStream<A> {
// возвращает промис на очередной элемент стрима или null, если элементов больше нет. Потребитель вызвывает read(), при срабатывании промиса обрабатывает элемент и вызывает read() еще раз
read(): Promise<A?>
// сообщает отправителю, что потребитель не заинтереснован в чтении элементов стрима
discard()
}
Re[5]: Clean Architecture. Отображение в GUI процесса выполнения длительной опер
Q>>На самом деле вся архитектура сводится к одной мысли: есть код который решает проблему, а есть код который позволяет этот код использовать и представляет из себя в большей части случаев рутину. Проблема в собственно в том, что у многих усилия при разработке почему-то сосредоточены на втором и все проблемы возникают там же, а не на первом. В твоем случае главный код это тот код, который представляет долго выполняющиеся задачу, а как он будет взаимодействовать с UI — это уже второстепенно.
Z>Абсолютно согласен. Z>Главный код у меня — это код, который обрабатывает данные. Он уже работает и все что надо выполняет. Z>Теперь вот и встал вопрос про "второстепенную" задачу — отобразить ход выполнения.
Z>Несмотря на то, что она второстепенная, нужно эту задачу решить грамотно. Z>Сейчас информация о ходе выполнения должна отображаться в табличке в десктопном UI. Потом потребуется чтобы все это отображалось при запуске из консоли, потом по веб-запросу. Z>И, прочитав книжку, я не смог придумать как то сделать. Z>Поэтому прошу совета\помощи — придумать решение хотя бы в общих чертах.
Есть такой универсальный шаблон Наблюдатель, долго выполняющаяся задача может генерить события при изменении своего статуса, UI будь то графический интерфейс или консоль его обрабатывают. Для UI для отображения задачи можно использовать шаблон Заместитель. Заместитель будет слушать события задачи и их визуализировать, а как задача закончится, результат будет отображать уже другой объект.
PS. Заместитель я уже использовал на практике подобным образом.
Программа – это мысли спрессованные в код
Re[8]: Clean Architecture. Отображение в GUI процесса выполн
Q>На стороне бизнес логики данные формируются в некотором абстрактном виде, не заточенные под отображение в UI (т.е. без цветов, шрифтов и т.п.). Q>Далее данные передаются в слой UI через callback или отдельным вызовом со стороны UI. Q>Логика UI уже решает, где и как эти данные отобразить, в т.ч. каким цветом и т.д.
Это понятно.
Q>Список или не список, эти данные ничем не отличаются от других данных, которыми обмениваются слои программы.
Если рассуждать вообще, то я согласен, что для общей архитектуры это неважно.
Но мы ведь должны перейти уже к конкретному решению.
Возвращаемые данные из бизнес-логики всегда имеют какой-то конкретный тип.
И тут нам надо решить: какие конкретно данные будет возвращать бизнес-логика для данного конкретного случая:
1) либо это будет просто что-то типа структуры с несколькми полями с информацией об одном конкретном выполненном действии,
2) либо это будет список (массив и т.д.) действий
Вы как считаете, какой вариант для поставленной задачи более правильный?
Выше вы писали:
В этом случае прогресс это не % выполнения, а список сделанного.
В простейшем случае — лог, список строк.
Какой механизм (архитектуру) вы имели ввиду? В каком слое будет формироваться этот прогресс? В бизнес-логике?
В каком виде это прогресс передаваться в UI?
Re[9]: Clean Architecture. Отображение в GUI процесса выполн
Здравствуйте, zelenprog, Вы писали: Z>Но мы ведь должны перейти уже к конкретному решению.
Z>Какой механизм (архитектуру) вы имели ввиду? В каком слое будет формироваться этот прогресс? В бизнес-логике? Z>В каком виде это прогресс передаваться в UI?
Как конкретно реализовать — вариантов масса.
Приведу для примера как у меня в одном из проектов сделан механизм обработки на клиенте изменений в базе на сервере (которые делают другие пользователи).
По сути от прогресса мало чем отличается. Только тут "операция" длительностью во все время жизни клиентской сессии.
При подключении к серверу клиент регистрирует себя как подписчика на изменения, получает некий id.
Под этот id на сервере создается "указатель" на общий список изменений. У каждого подписчика "указатель" свой и они могут указывать в разные места списка.
Элементы в конец общего списка изменений добавляет бизнес-логика сервера в контексте каждой клиентской сессии (документ id такой-то изменил пользователь Вася, например).
Клиент по id подписчика спрашивает сервер о новых изменениях, получает их список (от тек. положения указателя до конца списка).
При этом указатель этого подписчика на сервере перемещается в конец списка.
Все элементы списка, которые расположены до (раньше) всех имеющихся "указателей" более никому не нужны и сервер их удаляет.
Могут быть ленивые подписчики, которые не опрашивают регулярно изменения. Из-за них размер общего списка изменений может расти с хвоста и не уменьшаться с головы.
Поэтому есть некий предел количества событий, которые может содержать общий список.
При его превышении список принудительно сокращается с головы, а все указатели, находящиеся в диапазоне от старой головы до новой, переводятся в специальное состояние "overflow".
Т.е. когда клиент опрашивает сервер на предмет новых изменений, то он может получить:
1) пустой список — нет изменений, ничего обновлять не надо;
2) список из 1 или более изменений — смотрим на характер изменений и обновляем, что требуется;
3) признак "overflow" — было слишком много изменений, которые мы проспали, обновляем все.
Сам опрос изменений может быть по таймеру, по явному нажатию кнопки пользователем, по каким-то иным событиям в клиентской программе.
Если вернуться к задаче с прогрессом, то тут еще проще.
При запуске длительной операции получаем ее task id.
На стороне бизнес-логики можем привязать по task id какую-то структуру данных, например список сделанного.
Передаем этот список по мутабельной ссылке в функцию длительной операции.
Эта функция добавляет элементы в этот список по ходу своей работы.
Клиент может по task id запросить список новых элементов, при этом список на стороне бизнес-логики очищается.
По сути, получается как в предыдущем примере, только подписчик строго один и поэтому не нужен общий список и "указатели".
Если вернуться к ограничению, что все должно быть в один поток, то тут только передача callback в длительную функцию бизнес-логики.
В неких контрольных точках длительной функции надо вызывать callback и передавать туда текущий список, а потом его очищать.
Или просто дергать callback на каждый обработанный элемент и обойтись вообще без списков (это если обработка элементов не как из пулемета).
Но в таком сценарии будут проблемы с обновлением UI из стека длительной функции бизнес-логики:
1) не все элементы UI обновляются синхронно, иногда надо прокачивать сообщения, чтобы все корректно отрисовалось;
2) контрольные точки (вызов callback) должны быть достаточно частыми, иначе система сочтет, что программа "Не отвечает".
Re[10]: Clean Architecture. Отображение в GUI процесса выполн
Рискну предположить, что вы еще не доросли до архитектуры. Сначала нужно научиться писать код, потом познать боль из-за плохо написанного кода, а уже потом читать, как эти боли решаются. Иначе какой-то карго-культ получается.