Здравствуйте, 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[3]: Clean Architecture. Отображение в GUI процесса выполнения длительной опер
Q>>Почитал бы книжку: Чистая архитектура она того стоит и кстати, там есть про то, что перебарщивать в архитектуре не стоит без явной в этом необходимости.
Z>Я ее как раз сейчас читаю. Z>Только в книжке там все просто и простые примеры. Но вот что касается длительных операций там нифига не описано.
На самом деле вся архитектура сводится к одной мысли: есть код который решает проблему, а есть код который позволяет этот код использовать и представляет из себя в большей части случаев рутину. Проблема в собственно в том, что у многих усилия при разработке почему-то сосредоточены на втором и все проблемы возникают там же, а не на первом. В твоем случае главный код это тот код, который представляет долго выполняющиеся задачу, а как он будет взаимодействовать с UI — это уже второстепенно.
Программа – это мысли спрессованные в код
Re: Clean Architecture. Отображение в GUI процесса выполнения длительной операци
Z>Стараюсь написать программу с "хорошей" архитектурой.
На моей памяти уж года 3 как стараешься. А мог бы просто за это время набить шишек, поняв где и как стоит делать, а где – нет, плюс заодно прокачаться, поднять свой скилл и уже чуть ли не интуитивно понимать, где как стоит и не стоит делать. А ты вместо этого надрач ищешь идеальный рецепт "хорошей" программы.
Сорян, что поломаю розовые очки: такого рецепта нет никакого "правильного" варианта написания архитектуры. Везде будут изъяны, недочеты и где-то что-то впоследствии захочется переделать.
Welcome to the real world!
Ну или да, можно всю жизнь тренироваться на кошечках, писать хеллоу ворлды в вакууме и натягивать сов на глобусы разных цветов размеров.
PS простите, наболело от однообразия твоих постов.
PS2 не ошибаясь и не пробуя, а зарываясь лишь в теорию ты из zelenprog-ера в seniorprog-ера не превратишься
Патриот здравого смысла
Re: Clean Architecture. Отображение в GUI процесса выполнения длительной операци
Здравствуйте, zelenprog, Вы писали:
Z>Читал про Чистую архитектуру: Z>https://habr.com/ru/articles/499078/
Z>Объясните, пожалуйста. Z>Если можно — покажите какой-нибудь подходящий пример кода.
Ну я бы задал вопрос там, где можно найти апологетов того подхода, который вы пытаетесь использовать.
Так что, имхо, наиболее продуктивно — задавать вопросы под статьей, на которую вы привели ссылку.
Re[7]: Clean Architecture. Отображение в GUI процесса выполн
Здравствуйте, zelenprog, Вы писали:
Z>Значит, дожен быть еще какой-то код, который: Z>1) при появлении новой информации о ходе выполнения отслеживает "разницу" по сравнению с прошлым состоянием, и делает список выполненных действий. Z>2) каким-то образом оповещает UI и передает в UI этот список.
Список или не список, эти данные ничем не отличаются от других данных, которыми обмениваются слои программы.
На стороне бизнес логики данные формируются в некотором абстрактном виде, не заточенные под отображение в UI (т.е. без цветов, шрифтов и т.п.).
Далее данные передаются в слой UI через callback или отдельным вызовом со стороны UI.
Логика UI уже решает, где и как эти данные отобразить, в т.ч. каким цветом и т.д.
Clean Architecture. Отображение в GUI процесса выполнения длительной операции
Как я понял, в соответствии с Чистой архитектурой, выходные данные ResponseModel бизнес-операции (UseCase Interactor) после ее завершения "возвращаются" в вызывающий слой через интерфейс OutputPort.
Интерфейс OutputPort реализуется в вызывающем слое как объект Presenter.
Но ведь OutputPort "возвращается" только при завершении бизнес-операции, через OutputPort возвращаются результаты выполнения.
А как сделать, чтобы происходило изменение пользовательского интерфейса именно в процессе выполнения длительной бизнес-операции?
Например.
Бизнес-операция — это обработка вложенных файлов и папок. Обработка каждой папки достаточно длительная.
Нужно, чтобы при выполнении этой операции в окне отображалась таблица с колонками.
При начале обработки новой папки\подпапки в таблице должна появляться новая строка и в первой колонке "Имя папки" таблицы отображается имя папки.
По ходу обработки папки (при обработке очередного файла в этой папки) во второй колоке "Файл" должна появиться строка "обрабатывается файл ххххх". После обработки всех файлов в колонке таблицы "Результат" должен появиться результат обработки папки.
В общем-то по смыслу ничего сложного.
Но как это реализовать, придерживаясь принципов Clean Architecture?
Как вызывающий слой должен вызвать UseCaseInteractor?
Что должна сделать процедура бизнес-операции, чтобы "сработали" все эти OutputPort, Presenter и т.д., и чтобы в итоге пользователь видел процесс заполнения таблицы?
Объясните, пожалуйста.
Если можно — покажите какой-нибудь подходящий пример кода.
Re[2]: Clean Architecture. Отображение в GUI процесса выполнения длительной опер
МР>Ну я бы задал вопрос там, где можно найти апологетов того подхода, который вы пытаетесь использовать. МР>Так что, имхо, наиболее продуктивно — задавать вопросы под статьей, на которую вы привели ссылку.
В этом подходе нету ничего особенного. Я думаю, что любой программист в том или ином виде применяет этот подход.
Этот подход — это просто описание принципа SRP, который необходимо использовать в любой программе, применительно к архитектуре ПО.
Просто автор "Чистой архитектуры" дал своеобразные названия классам: Controller, Presenter, InputPort, OutputPort, UseCaseInteractor.
Вопрос у меня возник как применить всё это к длительной операции.
Re[3]: Clean Architecture. Отображение в GUI процесса выполнения длительной опер
Здравствуйте, zelenprog, Вы писали: Z>Вопрос у меня возник как применить всё это к длительной операции.
Длительную операцию надо разбить на отдельные составляющие.
Например, пользователь запускает вычисление где-то на сервере.
Это первая субоперация. Возврат ее — вычисления успешно начаты или ошибка (например, входные параметры неправильные).
Далее по логике UI можно опрашивать статус вычислений (например, по таймеру).
Эта субоперация вернет прогресс, признак завершения или ошибку.
И плюс еще можно добавить субоперацию отмены вычислений.
Если взаимодействие UI с остальной системой носит не односторонний характер (клиент-сервер),
то можно организовать подписки на различные события. Компоненты UI смогут регистрировать себя в качестве слушателей на то, что для них требуется.
Re[4]: Clean Architecture. Отображение в GUI процесса выполнения длительной опер
Здравствуйте, qaz77, Вы писали:
Q>Здравствуйте, zelenprog, Вы писали: Z>>Вопрос у меня возник как применить всё это к длительной операции.
Q>Длительную операцию надо разбить на отдельные составляющие.
Q>Например, пользователь запускает вычисление где-то на сервере.
И получает Id начатой операции.
Q>Это первая субоперация. Возврат ее — вычисления успешно начаты или ошибка (например, входные параметры неправильные).
Q>Далее по логике UI можно опрашивать статус вычислений (например, по таймеру).
Q>Эта субоперация вернет прогресс, признак завершения или ошибку.
Q>И плюс еще можно добавить субоперацию отмены вычислений.
Q>Если взаимодействие UI с остальной системой носит не односторонний характер (клиент-сервер), Q>то можно организовать подписки на различные события. Компоненты UI смогут регистрировать себя в качестве слушателей на то, что для них требуется.
Программа – это мысли спрессованные в код
Re: Clean Architecture. Отображение в GUI процесса выполнения длительной операци
Здравствуйте, zelenprog, Вы писали:
Z>Здравствуйте!
Z>Стараюсь написать программу с "хорошей" архитектурой. Z>Читал про Чистую архитектуру: Z>https://habr.com/ru/articles/499078/
Z>Как я понял, в соответствии с Чистой архитектурой, выходные данные ResponseModel бизнес-операции (UseCase Interactor) после ее завершения "возвращаются" в вызывающий слой через интерфейс OutputPort. Z>Интерфейс OutputPort реализуется в вызывающем слое как объект Presenter. Z>Но ведь OutputPort "возвращается" только при завершении бизнес-операции, через OutputPort возвращаются результаты выполнения.
Z>А как сделать, чтобы происходило изменение пользовательского интерфейса именно в процессе выполнения длительной бизнес-операции?
Z>Например. Z>Бизнес-операция — это обработка вложенных файлов и папок. Обработка каждой папки достаточно длительная. Z>Нужно, чтобы при выполнении этой операции в окне отображалась таблица с колонками. Z>При начале обработки новой папки\подпапки в таблице должна появляться новая строка и в первой колонке "Имя папки" таблицы отображается имя папки. Z>По ходу обработки папки (при обработке очередного файла в этой папки) во второй колоке "Файл" должна появиться строка "обрабатывается файл ххххх". После обработки всех файлов в колонке таблицы "Результат" должен появиться результат обработки папки.
Z>В общем-то по смыслу ничего сложного. Z>Но как это реализовать, придерживаясь принципов Clean Architecture? Z>Как вызывающий слой должен вызвать UseCaseInteractor? Z>Что должна сделать процедура бизнес-операции, чтобы "сработали" все эти OutputPort, Presenter и т.д., и чтобы в итоге пользователь видел процесс заполнения таблицы?
Z>Объясните, пожалуйста. Z>Если можно — покажите какой-нибудь подходящий пример кода.
Почитал бы книжку: Чистая архитектура она того стоит и кстати, там есть про то, что перебарщивать в архитектуре не стоит без явной в этом необходимости.
Программа – это мысли спрессованные в код
Re[2]: Clean Architecture. Отображение в GUI процесса выполнения длительной опер
Q>Почитал бы книжку: Чистая архитектура она того стоит и кстати, там есть про то, что перебарщивать в архитектуре не стоит без явной в этом необходимости.
Я ее как раз сейчас читаю.
Только в книжке там все просто и простые примеры. Но вот что касается длительных операций там нифига не описано.
Re[2]: Clean Architecture. Отображение в GUI процесса выполнения длительной опер
DP>... А мог бы просто за это время набить шишек ...
Так вот я и набиваю шишки.
DP>... можно всю жизнь тренироваться на кошечках, писать хеллоу ворлды в вакууме и натягивать сов на глобусы разных цветов размеров.
Я пишу реальное приложение, используемое на практике
Да, это приложение небольшое.
DP>... Сорян ... простите ...
Все нормально.
Я даже приветсвую критику.
DP>... наболело от однообразия твоих постов
Да, все посты касаются архитектуры.
Но в каждом посте затрагиваются разные конкретные моменты, которые в явном виде нигде не описаны.
DP>... нет никакого "правильного" варианта написания архитектуры ....
Ну как же нет?
Ведь "шаблоны", "принципы" — это и есть некие "правила" "правильной" архиектуры, которые были сформулированы в теоретическом виде только на основе анализа многих реальных программ.
Нарушая эти принципы, в итоге с очень большой вероятностью получится нерабочая\неподдерживаемая программа.
Re[4]: Clean Architecture. Отображение в GUI процесса выполнения длительной опер
Q>Длительную операцию надо разбить на отдельные составляющие.
Q>Например, пользователь запускает вычисление где-то на сервере. Q>Это первая субоперация. Возврат ее — вычисления успешно начаты или ошибка (например, входные параметры неправильные). Qulac>И получает Id начатой операции.
ОК, понятно.
Q>Далее по логике UI можно опрашивать статус вычислений (например, по таймеру).
А если нету таймера? Если все выполняется в одном потоке?
То есть: по событию формы вызывается контроллер, контроллер создает презентера и вызывает бизнес-операцию... И все это один поток.
Как в этом случае "опрашивать" статус вычислений?
Я то думал, что согласно "чистой архитектуре", бизнес-операция через интерфейс презентера должна сама сообщать о статусе.
Re[4]: Clean Architecture. Отображение в GUI процесса выполнения длительной опер
Q>Длительную операцию надо разбить на отдельные составляющие. Q>Далее по логике UI можно опрашивать статус вычислений (например, по таймеру). Q>Эта субоперация вернет прогресс, признак завершения или ошибку.
Сразу возник еще вопрос.
По условвиям задачи, UI должен выполненные действия бизнес-операции отобразить в виде таблицы.
Если UI будет сам опрашивать состояние, то при очередном опросе UI должен получить список выполненных действий, которые были выполнены с момента предыдущего опроса.
Как это сделать?
Re[5]: Clean Architecture. Отображение в GUI процесса выполнения длительной опер
Здравствуйте, zelenprog, Вы писали:
Z>А если нету таймера? Если все выполняется в одном потоке?
Есть системное время, вычисляй разность с последней операции и если оно больше заданной дельты обновляй интерфейс взаимодействия с пользователем.
Вопрос здесь скорее во сколько тебе обходится показ прогресса и стоит ли выводить его весь с каждой операции или только часть с задержкой по дельте времени, например, 0.1 сек, чтобы показать, что он есть.
Это типичная ловушка абстракций. GUI это самый обычный условно бесконечный цикл пока не будет выполнено условие выхода. И внутри него крутятся циклы обработки сообщений или называй как хочешь.
Фактически это машина состояний как в том же контроллере. То есть вся эта байда будет работать даже если программист не продвинулся дальше процедурного программирования с блоком, ветвлением и циклом.
Плюс получение системного времени или чего-то похожего учитывающего перевод часов. В общем смысл в простеньких алгоритмах уровня программистов аппаратчиков, см. статью выше.
А вот на третьем уровне абстракционистов нет понимания работы компьютера. На нём работают уже состоявшиеся в алгоритмах программисты, которые просто записывают их иначе.
Это как раз все эти шаблоны проектирования и прочее. Например, шаблон проектирования итератор внутри является самым обычным циклом относящимся к синтаксису языка программирования.
Все эти шаблоны это здорово и хорошо, но они не дают понимания алгоритмов, причём даже самых простых, а часто напротив превращают нечто сверх простое в сверх сложное.
Я писал ради опыта реализацию со временем сам, так и видел её на стековерфлоу. Если лень писать самому просто найди поиском готовое решение.
А про Мартина Роберта с его книгами Чистым Кодом, Чистым Кодером, Чистой Архитектурой и Чистым Agile, скажу так, сам он начинал с перфокарт. Статья же на хабре вторична и не имеет отношения к этому автору.
Между прочим UML это тоже попытка абстрагироваться, но уже от языков программирования. А в итоге получаем ещё один язык программирования с рамочками.
В общем сначала нужно учить алгоритмы и структуры данных, пусть даже это будет процедурное программирование, и лишь потом переводить работающий алгоритм в некую абстракцию по сути делающую тоже самое.
Четвёртому поколению пользователей ещё сложнее, так как они сидят на чужих готовых библиотеках алгоритмов в виде чёрных ящиков. И даже если код открыть за многоэтажными абстракциями сложно найти алгоритмы.
Кстати, интересная мысль вроде бы от Мартина Роберта, парадигмы всегда ограничивают возможности, а не добавляют их. Но если продолжить мысль, то став пользователем или пусть даже абстракционистом тоже ограничиваешь собственные возможности.
Re[5]: Clean Architecture. Отображение в GUI процесса выполнения длительной опер
Здравствуйте, zelenprog, Вы писали:
Z>По условвиям задачи, UI должен выполненные действия бизнес-операции отобразить в виде таблицы. Z>Если UI будет сам опрашивать состояние, то при очередном опросе UI должен получить список выполненных действий, которые были выполнены с момента предыдущего опроса. Z>Как это сделать?
В этом случае прогресс это не % выполнения, а список сделанного.
В простейшем случае — лог, список строк. Или что-то более сложное, в зависимости от задачи.
Re[5]: Clean Architecture. Отображение в GUI процесса выполнения длительной опер
Здравствуйте, zelenprog, Вы писали:
Z>А если нету таймера? Если все выполняется в одном потоке?
Если писали на Win API или чем-то подобном, то должны понимать, что однопоточность и таймер — не взаимоисключающие вещи.
Z>То есть: по событию формы вызывается контроллер, контроллер создает презентера и вызывает бизнес-операцию... И все это один поток. Z>Как в этом случае "опрашивать" статус вычислений? Z>Я то думал, что согласно "чистой архитектуре", бизнес-операция через интерфейс презентера должна сама сообщать о статусе.
Вообще плохой подход.
UI и вычисления в одном потоке — это уровень программ 25 лет назад.
Если деваться некуда, то да, тот или иной вид callback. Вычислительное ядро дергает какой-то интерфейс (слушатель, прогресс, ...) и надо обеспечивать обновление (перерисовку) UI. Весь такой треш с while (PeekMessage(...)), т.к. мы в единственном потоке и не в цикле обработки сообщений, а в стеке вычислительной задачи.
Re[6]: Clean Architecture. Отображение в GUI процесса выполн
Z>>А если нету таймера? Если все выполняется в одном потоке?
Q>Если писали на Win API или чем-то подобном, то должны понимать, что однопоточность и таймер — не взаимоисключающие вещи.
Да, писал, правда очень давно.
Я понимаю, что есть основной цикл приложения, обрабатывающий события от операционки.
Плюс есть обработчики прерываний.
Z>>То есть: по событию формы вызывается контроллер, контроллер создает презентера и вызывает бизнес-операцию... И все это один поток. Z>>Как в этом случае "опрашивать" статус вычислений? Z>>Я то думал, что согласно "чистой архитектуре", бизнес-операция через интерфейс презентера должна сама сообщать о статусе.
Q>Вообще плохой подход. Q>UI и вычисления в одном потоке — это уровень программ 25 лет назад. Q>Если деваться некуда, то да, тот или иной вид callback. Вычислительное ядро дергает какой-то интерфейс (слушатель, прогресс, ...) и надо обеспечивать обновление (перерисовку) UI. Весь такой треш с while (PeekMessage(...)), т.к. мы в единственном потоке и не в цикле обработки сообщений, а в стеке вычислительной задачи.
Да именно так. "Моя" среда разработки предоставляет только такой механизм.
Само приложение конечно же работает в цикле. Но мне как разрабочику управление этим циклом не доступно.
Мне доступны только методы-события от элементов управления и какие-то немногочисленные обработчики внешних событий, срабатывающие в момент ожидания ввода от пользователя.
Только не понял, что вы имеете ввиду про "треш с while (PeekMessage(...))"?
Где должен быть организован этот while? В бизнес-логике?
Не штатными средствами можно попробовать "прикрутить" таймер.
Но если рассуждать "теоретически", то тут такая дилемма...
Для каких-то событий бизнес-логики будет достаточно, если интерейс будет обновляться по таймеру.
Но для некоторых "критичных" событий обновление интерфейса должно срабатывать моментально.
То есть, как мне кажется, в программе должно быть два механизма взаимодействия с UI:
— первый: через опрос состояния бизнес-логики
— второй: через непосредственный вызов методов-реализаций перерисовки UI через интерфейсы, вызываемые из бизнес-логики.
Второй механизм покрывает возможности первого, и делает первый механизм ненужным.
И, как я понимаю, Clean Architecture описывает именно второй способ.
Z>>А если нету таймера? Если все выполняется в одном потоке?
V>Есть системное время, вычисляй разность с последней операции и если оно больше заданной дельты обновляй интерфейс взаимодействия с пользователем. V>Вопрос здесь скорее во сколько тебе обходится показ прогресса и стоит ли выводить его весь с каждой операции или только часть с задержкой по дельте времени, например, 0.1 сек, чтобы показать, что он есть.
Все правильно.
Какой код (какой слой\модуль\метод) дожен выполнять эту работу? И откуда будет вызываться этот код?
То есть у меня вопрос скорее про разделение отвественности, а не про "техническую" начинку.
V>И в принципе я написал по этому поводу. V>Почему программисты прошлого были умнее
Да, я читал эту статью. И горячие обсуждения этой статьи.
V>Это типичная ловушка абстракций. GUI это самый обычный условно бесконечный цикл пока не будет выполнено условие выхода. И внутри него крутятся циклы обработки сообщений или называй как хочешь. V>Фактически это машина состояний как в том же контроллере. То есть вся эта байда будет работать даже если программист не продвинулся дальше процедурного программирования с блоком, ветвлением и циклом. V>Плюс получение системного времени или чего-то похожего учитывающего перевод часов. В общем смысл в простеньких алгоритмах уровня программистов аппаратчиков, см. статью выше. V>А вот на третьем уровне абстракционистов нет понимания работы компьютера. На нём работают уже состоявшиеся в алгоритмах программисты, которые просто записывают их иначе. V>Это как раз все эти шаблоны проектирования и прочее. Например, шаблон проектирования итератор внутри является самым обычным циклом относящимся к синтаксису языка программирования. V>Все эти шаблоны это здорово и хорошо, но они не дают понимания алгоритмов, причём даже самых простых, а часто напротив превращают нечто сверх простое в сверх сложное.
В общем согласен. Знание и понимание "азов" помогает в более высокоуровневом программировании.
Я начинал писать на ассемблере, потом на С, потом на С++ и так далее.
Кстати и эту программу я пишу на процедурном языке, в котором нету классов.
Но это не исключает применение принципов разделения кода, которые были наработаны "потом и кровью".
Эти принципы были наработаны в том числе и программистами прошлого, которые дали нам (современным программистам) огромный опыт, в том числе и такой опыт как не надо делать.
Ведь, например, насколько я помню MVC был придуман когда еще не было ни ООП ни шаблонов проектирования.
V>В общем сначала нужно учить алгоритмы и структуры данных, пусть даже это будет процедурное программирование, и лишь потом переводить работающий алгоритм в некую абстракцию по сути делающую тоже самое.
Алгоритм тут как раз простой: изменили данные — перерисуй интерфейс. Структуры данных тоже понятные и простые.
Тут вопрос больше относится к тому, как организовать\разделить код так, чтобы программа оставалась поддерживаемой\расширяемой и т.д.
Чистая Архитектура — мне кажется именно про это.
Автор предлагает разделить этот код на части (грубо говоря на отдельные методы), которые он называет определенными терминами, и которые должны вызываться в следующем порядке:
Controller -> UseCaseInteractor (InputPort) -> Presenter (OutputPort).
V>А про Мартина Роберта с его книгами Чистым Кодом, Чистым Кодером, Чистой Архитектурой и Чистым Agile, скажу так, сам он начинал с перфокарт. Статья же на хабре вторична и не имеет отношения к этому автору.
Да, я это понимаю. Книгу читаю.
Но в самой книге нету про длительные операции.
Там, например, говорится о подготовке отчета: Контроллер вызвал Интерактора, который готовит отчет. Интерактор после выполнения отдает эти данные Презентеру. Презентер управляет отображением этого отчета.
Но мне нужно, чтобы кроме отображения отчета, еще отобразить и процесс его формирования\подготовки. Об этом в книге ничего не сказано.
Вот поэтому я и советуюсь с сообществом: как это лучше сделать?
Re[7]: Clean Architecture. Отображение в GUI процесса выполн
Здравствуйте, zelenprog, Вы писали:
Z>Только не понял, что вы имеете ввиду про "треш с while (PeekMessage(...))"? Z>Где должен быть организован этот while? В бизнес-логике?
В обработчике изменения прогресса, т.е. в callback, который дергает бизнес-логика.
Если не прокачать скопившиеся в очереди сообщения, то UI нормально не перерисуется.
Re[6]: Clean Architecture. Отображение в GUI процесса выполн
Z>>По условвиям задачи, UI должен выполненные действия бизнес-операции отобразить в виде таблицы. Z>>Если UI будет сам опрашивать состояние, то при очередном опросе UI должен получить список выполненных действий, которые были выполнены с момента предыдущего опроса. Z>>Как это сделать?
Q>В этом случае прогресс это не % выполнения, а список сделанного. Q>В простейшем случае — лог, список строк. Или что-то более сложное, в зависимости от задачи.
Какой код должен сформировать это список сделанного?
Как мне кажется, интерфейс (то есть Presenter по терминологии Чистой Архитектуры) не должен этого делать, он должен только управлять отображением полученных данных.
Бизнес-логика (UseCaseInteractor) по идее тоже не дожлна делать этот список, так как она только выполняет свою работу и фиксирует информацию о ходе своего выполнения.
Значит, дожен быть еще какой-то код, который:
1) при появлении новой информации о ходе выполнения отслеживает "разницу" по сравнению с прошлым состоянием, и делает список выполненных действий.
2) каким-то образом оповещает UI и передает в UI этот список.
В каком месте\слое Чистой Архитектуры должен находиться этот код?
Из прочтения книги это неясно.
Q>На самом деле вся архитектура сводится к одной мысли: есть код который решает проблему, а есть код который позволяет этот код использовать и представляет из себя в большей части случаев рутину. Проблема в собственно в том, что у многих усилия при разработке почему-то сосредоточены на втором и все проблемы возникают там же, а не на первом. В твоем случае главный код это тот код, который представляет долго выполняющиеся задачу, а как он будет взаимодействовать с 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[10]: Clean Architecture. Отображение в GUI процесса выполн
Рискну предположить, что вы еще не доросли до архитектуры. Сначала нужно научиться писать код, потом познать боль из-за плохо написанного кода, а уже потом читать, как эти боли решаются. Иначе какой-то карго-культ получается.