2008-11-17 17 views
11

He luchado durante los últimos meses para obtener un código limpio para informar el progreso a un usuario. Todo siempre parece reducirse a: "! No tiene que haber una forma más limpia"¿Cómo hacer el código más limpio al informar el progreso a un usuario?

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. 

El buen programador en mí grita Pero estoy perplejo. ¿Alguna idea?

EDIT :: Estoy buscando más información sobre información arquitectónica en comparación con la implementación específica. El código proporcionado es muy sobresimplificado.

+0

¿Qué idioma estás usando? DO#? ¿Java? –

Respuesta

9

configure sus tareas como una secuencia de eventos y haga que avance el informe del "motor" de procesamiento de eventos. Cada instancia de evento puede tener su propio nombre, plantilla/anuncio de informes de progreso, etc. si desea ir tan lejos

si este es un patrón que ocurre con frecuencia, vale la pena el esfuerzo para la infraestructura.Cuando haya terminado, el código utilizable podría 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); 
+0

Guau, un olor a código de menta. :) +1 –

+0

@ [Allain Lalonde]: gracias, es tan fresco que todavía puedes oler el compilador. –

3

¿Podría quizás usar Aspect Oriented Programming, e idear un aspecto de progreso?

Existen varias implementaciones de AOP. En el mundo de Java, los 2 más comunes son AspectJ y Spring (que utiliza AspectJ o Aspectos basados ​​en Proxy).

+0

lol - ¡sí, aprenda todo un nuevo paradigma para resolver un problema simple! –

+0

Supongo que depende de la cantidad de código. Por un pequeño fragmento de código, entonces seguro, un enfoque de progreso dentro del código siempre será el más simple. Pero a medida que aumenta la cantidad de código, terminará teniendo más código para el informe de progreso, ofuscando la lógica del núcleo en sí. Solo es mi opinión. – toolkit

+0

@Steven A. Lowe: Me pregunto si las personas respondieron casi de la misma manera a la recomendación de usar objetos cuando la programación orientada a objetos estaba en su infancia. –

1

Sería natural tener los informes dentro de las llamadas doTask().
Normalmente, el reportero habría un conjunto unitario que todos los objetos de los mensajes enviados a una clase y reportero fue el responsable de los decidir si y dónde mostrarlo - barra de estado, el archivo de registro, etc. stderr

+0

Esto combina los métodos con la clase de reportero, lo que significa que no puede llamar al método sin informar (o agregar un parámetro para controlar si llama al notificador). Eso puede estar bien, solo decirlo. – MusiGenesis

+0

Normalmente deja que el periodista decida si va a informar. A menos que le preocupen los gastos generales de los informes que no se usarán. –

1

Suponiendo que el patrón en lo que' estamos haciendo es:

  • tarea Registrar inicio
  • hacer tarea
  • registro final tarea

puede ordenar una Clase "Tarea" (principal para todas sus tareas), cuyo método do() tiene una subclase y registra automáticamente el inicio y el final de la tarea.

Solo una idea.

0

Se podría llamar ReportProgress desde el interior de los métodos doTask, que podría hacer que se vea un poco más limpio, en lugar sólo tendría:

doTask1(); 
doTask2(); 

La presentación de informes se manejan dentro de esos métodos.

Podrías usar AOP, pero mi cerebro grita BESO !! (Keep It Simple Stupid) en este caso. Si esto es solo una representación simple de algo más complicado con el que está tratando, el AOP podría ser una opción.

3

Puede crear una clase de tarea con una propiedad de nombre y delegar. Coloque cada tarea en una colección, luego repítala, imprima el mensaje e invoca al delegado para cada tarea.

1

No codificaría manualmente las partes numéricas de los mensajes mostrados de esa manera (cada vez que necesite agregar o quitar acciones o cambiar la secuencia que tiene un lío de cortar y pegar para hacer). Querrá que cualquier objeto que maneje el método ReportProgress se autoincremente a medida que avanza.

1

una manera bastante sencilla y limpia sería la creación de una clase abstracta que tiene un método do() y doTask abstracta() y getName() métodos:

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

luego, en sus tareas:

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

a continuación, podría tener una tarea que tiene un método doTask() que se ejecuta en do() un montón de o otras tareas Esto podría ser fácilmente recursivo, ya que cualquier tarea podría ejecutar una cantidad de subtareas.

1

+1 en la sugerencia de AOP. Esta es una clásica preocupación transversal que AOP resolvería elegantemente.

0

Lamentablemente, creo que la mejor manera de hacerlo depende de los detalles, por lo menos, del idioma que está utilizando. Por ejemplo en Python se puede utilizar un context manager para permitir escribir código como este:

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

Este ejemplo podría, garantizar, que la "Tarea 1 se hace" se informa incluso si do_task_1() lanza una excepción. Si quisiera, podría manejar las excepciones por separado e imprimir algo diferente como "Falló la Tarea 1" o "Tarea 1 abortó".

0

En nuestro kit de herramientas, tenemos un controlador de tareas que gestiona las tareas. Una tarea se ejecuta como un hilo. Además del soporte de subprocesos típico, una tarea admite métodos de progreso. Una posible vista sobre el progreso es una barra de progreso visual con un título que se refiere al nombre de la tarea y al paso dentro de la tarea. Para admitir estadísticas visibles y el estado, el código debe hacer llamadas ocasionales al método de progreso de la tarea. Por lo general, esto se realiza dentro de los bucles for ya que el progreso porcentual se puede estimar mediante el índice actual dividido por el límite.

El controlador de tareas es un lugar útil para agregar control global de hilos, sondeos de estado, otras estadísticas y ganchos de medición de rendimiento. Algunos errores de subprocesos múltiples y problemas de temporización se pueden analizar examinando el estado del controlador y el estado de todas las tareas.

2

Depende de cuánta configuración se necesita sobre la marcha, esperaría que el código fuera muy general, y las tareas se configurasen a través de la primavera o de cualquier contenedor de ioc.

Todo esto estaría en una configuración de muelles: La configuración xml proporcionaría al objeto tarea su nombre y parámetros. luego agrega estas tareas a una colección, y entrega esa colección al taskrunner.

El corredor de tareas es entonces un código que indica el inicio y el final de cada tarea, pero cada tarea es libre de dar un estado específico de cómo va. Además, el correcaminos detectará cualquier excepción y continuará si algo falla. Podría configurarse para decir que ciertas tareas dependen de la finalización de otras, y algunas tareas deberían detener todo si fallan.

No estoy de acuerdo en que se deba usar AOP aquí. excesivo

0

Si está utilizando .NET, sugeriría usar el Bloque de aplicación de inyección de directivas desde Enterprise Library (Versión mínima: 3.1). Usé un elemento similar para hacer un "Revertir a la identidad del grupo de aplicaciones" para un sitio web que era pesado en la suplantación.

Puede hacer lo mismo con su tarea. Simplemente podría definir una clase de tarea con una fábrica que construya el objeto con la fábrica de objetos de la Biblioteca Empresarial y agregue automáticamente un mensaje "Antes" y "Después" a la tarea. Eso le daría EXACTAMENTE lo que quiere con la elección que se requiere.

¡Diviértete!

Cuestiones relacionadas