Шаблоны проектирования шаблонов хода?
Приложение, которое я пишу, выполняет алгоритм длины, который обычно занимает несколько минут. В течение этого времени я хотел бы показать пользователю индикатор выполнения, который указывает, насколько алгоритм выполняется максимально точно.
Алгоритм разделен на несколько этапов, каждый из которых имеет свой собственный характерный момент. Например,
- инициализация (500 миллисекунд)
- входы для чтения (5 секунд)
- шаг 1 (30 секунд)
- шаг 2 (3 минуты)
- записывающие выходы (7 секунд)
- выключение (10 миллисекунд)
Каждый шаг может легко сообщить о его прогрессе, установив диапазон его работы, скажем [от 0 до 150], а затем сообщив о значении, которое он завершил в своем основном цикле.
В настоящее время я настроил схему вложенных мониторов прогресса, которые образуют своего рода неявное дерево отчетов о прогрессе.
Все мониторы прогресса наследуются от интерфейса IProgressMonitor
:
class IProgressMonitor
{
public:
void setRange(int from, int to) = 0;
void setValue(int v) = 0;
};
Корнем дерева является ProgressMonitor, который подключен к фактическому интерфейсу графического интерфейса:
class GUIBarProgressMonitor : public IProgressMonitor
{
GUIBarProgressMonitor(ProgressBarWidget *);
};
Любые другие node в дереве - это мониторы, которые управляют частью родительского хода:
class SubProgressMonitor : public IProgressMonitor
{
SubProgressMonitor(IProgressMonitor *parent, int parentFrom, int parentLength)
...
};
A SubProgressMonitor
управляет диапазоном [parentFrom, parentFrom+parentLength]
его родителя.
С помощью этой схемы я могу статически делить прогресс верхнего уровня в соответствии с ожидаемой относительной частью каждого шага в глобальном времени. Затем каждый шаг можно далее подразделить на куски и т.д.
Основным недостатком этого является то, что разделение является статическим, и становится болезненным вносить изменения в соответствии с переменными, которые обнаруживаются во время выполнения.
Итак, вопрос: есть ли какие-либо известные шаблоны проектирования для мониторинга прогресса, которые решают эту проблему?
Ответы
Ответ 1
Очень интересный подход - восприятие пользователя.
Крис Харрисон опубликовал документ о том, как пользователь воспринимает проходящее время в зависимости от прогресса, о котором сообщает индикатор выполнения (хотя фактическая продолжительность была явно идентичны во всех экспериментах)
Обратите внимание, что предпочтительная отображаемая формула (x + (1-x)/2) 8 где x
- фактический прогресс по шкале от 0 до 1:)
Поэтому я бы предложил:
- собрать статистические данные о проценте времени, которое требуется выполнить данной задаче.
- измерять инициализацию и использовать ее для масштабирования вашего хода на индикаторе выполнения, будучи пессимистичным (например, подготовьте буфер размером 10-15%)
- перед последней задачей (или несколькими последними задачами, если они имеют детерминированную продолжительность), изо всех сил, чтобы завершить индикатор выполнения вовремя (с прогрессивным ускорением)
Я знаю, что это не точно, но если пользователи считают это быстрее, я соглашусь на это!
Ответ 2
Péter был подходом, который я предпринял для большого проекта; во время нашего пилотного и первоначального развертывания каждое из наших тысяч мобильных устройств отправляло данные о сроках и использовании данных, и мы использовали средние, медианные и стандартные отклонения времени, затраченного на точную настройку наших задач (когда задача была разрешена для запуска, сколько времени было разрешено для запуска, какие значения использовались на дисплее индикатора выполнения и т.д.). Поскольку наше решение было построено немного как ваше, но оно управляется значениями, представленными в файле конфигурации XML, мы подумали о том, чтобы создать это как автоматизированную систему (например, сервер будет проверять эти значения на некоторый интервал, заметить, что некоторые задачи занимают больше времени в последних дней, которые они использовали, и обновить файл конфигурации, чтобы перенести или удлинить их), но полагал, что это не стоит хлопот, чтобы предотвратить быстрый обзор человека каждые несколько недель.
Поскольку я не знаю о техническом решении вашей проблемы, я думаю, что то, что вы показываете пользователю (и сколько времени вы тратите на разработку решения), должно основываться на функциональных проблемах: кто использует это? насколько точна информация? Является ли это интерактивным процессом, в ходе которого они не могут выполнять никакой другой работы или могут ли они работать в фоновом режиме и возвращаться к нему? Является ли процесс работы, в течение которого ваша долговременная функция выполняется с учетом времени или критически важная?
Мне жаль, что я не могу дать вам ответ, который вы ищете, но, возможно, подумать о том, чего вы пытаетесь добиться в широких мазках, дает отличную идею. =)
Ответ 3
Создайте AggregateProgressMonitor, который автоматически вычисляет дочерние отделы прогресса на основе информации, отображаемой мониторами прогресса ребенка. Мониторинг прогресса ребенка должен по крайней мере информировать родителя о "ожидаемом" времени выполнения. Оценочное время работы дочернего монитора затем может быть обновлено соответствующими операциями на основе параметров времени выполнения, и общая отчетность о ходе будет скорректирована соответствующим образом и автоматически.
Что-то вроде этого...
class IAggregateProgressMonitor : public IProgressMonitor
{
void setChildValue(IProgressMonitor *, int v);
void setChildEstimatedTime(IProgressMonitor *, int v);
}
class AggregateProgressMonitor : public IAggregateProgressMonitor
{
void setChildValue(IProgressMonitor * child, int v)
{
int aggregateValue = mapChildValueToAggregateValue(child, v);
setValue(aggregateValue);
}
void setChildEstimatedTime(IProgressMonitor * child, ulong ms)
{
children[child]->estimatedTime = ms;
updateChildProgressRatios();
}
}
class SubProgressMonitor : public IProgressMonitor
{
SubProgressMonitor(IAggregateProgressMonitor *parent, int parentFrom,
int parentLength) ... ;
void setValue(int v)
{
parent->setChildValue(this, v);
}
void setEstimatedRunningTime(ulong ms)
{
parent->setChildEstimatedTime(this, ms);
}
};
Вы даже можете использовать наблюдаемое время первого шага для более точной настройки последующих докладчиков прогресса.
Вам необходимо сохранить упорядоченную карту в AggregateProgressMonitor, чтобы иметь возможность отслеживать и вычислять всю информацию от детей.
После завершения вы можете расширить AggregateProgressMonitor (переопределить методы IProgressMonitor), чтобы отобразить прогресс для пользователя.
Ответ 4
Это сложная проблема, мы также боролись с ней в предыдущем проекте.
Лучшее, что я мог бы придумать, - собрать статистику того, как долго каждая фаза фактически выполняется в реальной жизни, и соответственно корректировать относительные интервалы.
Мы не реализовали его в этом проекте (хотя бы до тех пор, пока я был там), так что это всего лишь теоретическая идея: -)
Ответ 5
Вы можете рассмотреть возможность замены индикатора выполнения с кругом хода. Если задача имеет N шагов, то сделайте N клинья в пироге и заполните каждый клин, как индикатор выполнения, по мере того, как этот шаг выполняется.
В качестве дополнительного шага, возможно, есть какой-то текст, отображаемый для каждого шага, поэтому им нужно что-то читать, пока шаг прогрессирует.