Pergunta

Eu tenho lutado para o último par de meses para chegar a algum código limpo ao progresso relatório para um usuário. Tudo sempre parece resumir-se a:

ReportProgress("Starting Task 1");
doTask1();
ReportProgress("Task 1 is done");

ReportProgress("Starting Task 2");
doTask2();
ReportProgress("Task 2 is done");

//etc... where report progress does some form of output to the user.

O bom programador em mim grita "Não tem que ser uma maneira mais limpa!" Mas eu estou perplexo. Quaisquer pensamentos?

EDIT :: Eu estou olhando mais para obter informações sobre informações de arquitetura em oposição à aplicação específica. O código dado é muito simplificado.

Foi útil?

Solução

configurar suas tarefas como um fluxo de eventos, e têm o 'motor' relatório de progresso de processamento de evento. Cada instância de evento pode ter o seu próprio nome, de relatório de progresso sinopse / modelo, etc. se você quiser ir tão longe

Se este é um padrão que ocorre muitas vezes, vale a pena o esforço para a infra-estrutura. Quando estiver pronto, o código utilizável poderia ser algo como:

EventQueue tasks = new EventQueue();
tasks.Add(new TaskEvent(this.doTask1,"Foo-ing the bar"));
tasks.Add(new TaskEvent(this.doTask2,"Bar-ing the foo"));
tasks.Add(new TaskEvent(this.doTask3,"Glitching and whinging"));
...
tasks.Execute(this.ProgressEventHandler);

Outras dicas

Você poderia talvez usar Aspect Oriented Programming , e elaborar um aspecto Progress

Há uma série de implementações de AOP. No mundo Java, a 2 mais comuns são AspectJ e Spring (que usa o AspectJ, ou proxy aspectos baseados).

Você pode criar uma classe de tarefas com uma propriedade de nome e delegado. Coloque cada tarefa em uma coleção, em seguida, iterar através dele, imprimir a mensagem e invocando o delegado para cada tarefa.

Depende de quanto de configuração é necessária na mosca, eu esperaria o código a ser muito geral, e têm as tarefas ser configurado via primavera ou qualquer recipiente COI.

Este seria em uma configuração primavera: A configuração XML iria fornecer o objeto de tarefa com o seu nome e parâmetros. em seguida, adicionar essas tarefas a uma coleção, e mão que recolha ao TaskRunner.

O corredor tarefa é, em seguida, o código que sinaliza o batente e começar de cada tarefa, mas cada tarefa, então, é livre para dar estatuto específico de como ele está indo. Também o TaskRunner vai pegar qualquer exceção e continuar se algo erra fora. Pode ser feita configurável para dizer que certas tarefas dependem da conclusão dos outros, e algumas tarefas deve parar tudo, se eles falham.

Eu discordo que AOP deve ser usado aqui. um exagero.

Seria natural para ter a informação dentro do doTask () chamadas.
Normalmente o repórter seria um solteirão que todos os objetos enviou mensagens para e uma classe repórter foi reponsável para decidir se e onde para mostrá-lo -. Statusbar, arquivo de log, stderr etc

Assumindo o padrão em que você está fazendo é:

  • início da tarefa de log
  • fazer tarefa
  • end tarefa log

você pode ter uma classe "Task" (pai para todas as suas tarefas), cuja fazer () é uma subclasse e automaticamente registros de início e fim da tarefa.

Apenas uma idéia.

Eu não mão-código as partes numéricos das mensagens exibidas como que (qualquer hora que você precisa para adicionar ou remover ações ou alterar a seqüência você tem uma confusão de cut-and-paste para fazer). Você iria querer qualquer objeto que está a lidar com o método ReportProgress à própria auto-incremento como ele vai junto.

Uma maneira bastante simples e limpo seria a criação de uma classe abstrata que tem um método do() e doTask abstrato () e métodos getName ():

do() {
    ReportProgress("Starting " + this.getName());
    doTask();
    ReportProgress("Finished " + this.getName());
}

Então, em suas tarefas:

class Task1 extends Task {
    getName(){return "Task 1";}
    doTask() {
        //do stuff here
    }
}

Você poderia, então, ter uma tarefa que tem um método doTask () que executa do() em um monte de outras tarefas. Isto poderia facilmente ser recursiva, em que qualquer tarefa pode, em seguida, executar um número de sub-tarefas.

+1 sobre a sugestão AOP. Esta é uma preocupação transversal clássico que AOP resolveria elegantemente.

Você poderia chamar ReportProgress de dentro dos métodos doTask, que pode fazer com que pareça um pouco mais limpo, em vez disso você teria apenas que:

doTask1();
doTask2();

O relato seria tratado dentro desses métodos.

Você pode usar AOP, mas meu cérebro grita BEIJO !! (Keep It Simple Stupid) neste caso. Se esta é apenas uma simples representação de algo mais complicado que você está lidando com, AOP pode ser uma opção.

Infelizmente eu acho que a melhor maneira de fazer isso dependerá dos detalhes - pelo menos o idioma que você está usando. Por exemplo em python você poderia usar um gerente contexto para permitir a escrita de código assim:

with progress_report("Task 1"):
    do_task_1()

Isso poderia, por exemplo, garantir que a "Tarefa 1 é feito" É relatado mesmo que do_task_1 () gera uma exceção. Se você quisesse, você poderia lidar com exceções separadamente e imprimir algo diferente, como "Task 1 falhou" ou "Tarefa 1 abortada."

No nosso kit de ferramentas, temos um controlador tarefa que gerencia tarefas. A tarefa é executada como um fio. Além do apoio do segmento típico, uma tarefa que apoie o progresso métodos. Uma vista possível para o progresso é uma barra de progresso visual com um título que se refere ao nome da tarefa e o passo dentro de tarefa. Para apoiar as estatísticas visíveis e status, o código deve fazer chamadas ocasionais ao método de progresso da tarefa. Normalmente, isso é feito dentro de loops desde o progresso percentual pode ser estimada pelo índice atual dividido pelo limite.

O controlador de tarefa é um lugar útil para adicionar o controle global da linha, sondas de status, outras estatísticas e ganchos de medição de desempenho. Alguns bugs multithreaded e problemas de tempo pode ser analisado examinando o estado do controlador e o estado de todas as tarefas.

Se você estiver usando .NET, gostaria de sugerir usando a injeção Política Application Block de Enterprise Library (Versão mínima: 3,1). Eu usei um material semelhante a fazer um "Reverter para a identidade pool de aplicativos" para um site que pesava sobre a representação.

Você poderia fazer o mesmo com a sua tarefa. Você poderia simplesmente definir uma classe tarefa com uma fábrica que construir o objeto com a fábrica objeto Enterprise Library e adicionar automaticamente uma mensagem de "antes" e "depois" para a tarefa. Isso daria exatamente o que quer com o elegence que é necessário.

Divirta-se!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top