Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Discusión OOP: Un sistema de avisos, usado por varias clases (https://www.clubdelphi.com/foros/showthread.php?t=63272)

Bauhaus1975 06-02-2009 13:28:57

Discusión OOP: Un sistema de avisos, usado por varias clases
 
Hola, os comento este tema, al que ahora le estoy dando vueltas:

Se trata de incluir un sistema de avisos (visuales) en un programa. Hay ciertas entidades o clases en el proyecto que son suceptibles de generar avisos: Por ejemplo, la entidad 'factura' debe dar avisos de facturas pendientes, así como la clase 'agenda' genera avisos cuando hay una cita apuntada para el dia actual. Este tipo de funcionalidad seguro que a muchos ya se os ha presentado. Lo ideal sería mostrar información del aviso y un enlace al formulario dónde se puedan ver los datos de la entidad/objeto que ha generado dicho aviso.

En este post me gustaria conocer/discutir cómo organizariais el modelado de objetos. Yo lo organizaria de la siguiente manera, hablando desde el punto de vista de UML.

Cita:


[Class Gestion]. Cualquier clase que necesite publicar avisos en el sistema. Inclye la Interfaz 'Aviso' que ofrece información sobre el método 'obtenerAvisos' a implementar por las clases.
+function ObtenerAvisos:listaAvisos (implementación)

[Interfaz Aviso]. Define un método que obtiene la lista de avisos. La lista de avisos puede contener información sobre: Un título, la entidad que epresenta, una 'manera' de abrir un formulario para acceder a los datos etc.
+function ObtenerAvisos:listaAvisos (definición)

[Class Aviso]. Ofrece la funcionalidad para mostrar la lista de avisos pendientes, por ejemplo al entrar en el programa, o en un momento eterminado. Aquí también podemos definir un tipo de datos para la estructura 'itemAviso' o la 'listaAvisos' antes mencionada.
No sé si hay interfaces en delphi, (todavía no sé nada sobre ello). En Java si las he usado. Aquí es donde necesitaria vuestra ayuda, si este enfoque es adecuado, para ver cómo se implementaria de la mejor manera.

Bueno, no sé si os habré liado mucho. Espero vuestros comentarios.
Gracias por vuestra atención y un saludo.

Delphius 13-02-2009 18:45:59

Hola Bauhaus1975,
He visto que me haz enviado un mensaje al correo.
Bueno, déjame decirte que si había visto el hilo y he estado organizando y reordenando en mi cabeza tus palabras y algo no me agrada mucho.

Por empezar debo comentarte que tengo mis reservas de que basarse en ejemplos en Java para exponerlos a Delphi sea una buena idea. Sobre todo debido a que en Java hay demasiado purismos y existen ciertas diferencias en como resolver las cosas respecto a Delphi.
Si bien tiendo a pensar en purismos, me parece que Java llega a un extremo exagerado y prefiero llegar a un purismo que me brinda Delphi.:)

Debido a esto, no me atrevo a decir que la forma de como lo estás organizando este bien, ni tampoco puedo asegurar de que esté mal.
Ten presente que cada persona puede ver al asunto de forma diferente, pero ello no implica que uno sea malo y otro sea bueno. En POO existe el gris... sino mira a aquel animal símbolo máximo de que en la naturaleza y en POO las cosas no son simples hechos concretos y una simple lógica binaria: el ornitorrinco.;)

Asi que de entrada no tomes a mis palabras como la verdad absoluta. Si tu sientes que tu modelo sirve, quedate con él. No les mucha vuelta al asunto.

Me gustarías que expusieras de otro modo tu modelo y que reordenaras tus ideas. Temo no interpretar apropiadamente tus palabras y me gustaría que seas un poco más gráfico/a. Disculpame pero no veo un punto de vista UML el asunto;)

Lo que más me nubla y cuesta interpretar es la diferencia entre la clase Gestion y la clase Aviso... ¿al final que hace cada una? ¿Que relación existe entre una y otra?

En Delphi existen las interfaces. Lee desde la página 801 de la Cara Oculta de Delphi 4 (puedes acceder a una copia del mismo en .pdf en el FTP del club), allí está expuesto el tema de las interfaces. Recomiendo además la lectura de la ayuda que ofrece Delphi al respecto.

Habría que ver hasta que punto es bueno tener esa interfaz. En Delphi, no es tan necesario estar definiendo interfaces. De vez en cuando añadirlas provoca más ruido... en principio bastaría con una clase que implemente los métodos necesarios.

Para asesorarte bien, necesitaría conocer mejor el negocio o contexto. Ver estas simples clases es la mitad del problema. Deberías saber que sin analizar en contexto no se puede tomar una decisión.

Saludos,

Bauhaus1975 16-02-2009 10:51:59

Gracias Delphius por responder. He leido atentamente las lecturas que me has recomendado y he estudiado tus consejos. También he visto que puedo usar interfaces si lo considerase oportuno. Paso ahora a profundizar un poco más en el tema:

Cita:

Empezado por Delphius (Mensaje 338069)
Hola Bauhaus1975,
Para asesorarte bien, necesitaría conocer mejor el negocio o contexto. Ver estas simples clases es la mitad del problema. Deberías saber que sin analizar en contexto no se puede tomar una decisión.

Exposición del contexto:
Pensemos un programa para gestionar Clientes, Facturas, Citas... que cuenta con entidades como 'Agenda', para apuntar hitos o citas y 'Factura', entre otras. Necesito mostrar avisos, por ejemplo en forma de lista al entrar al programa, o cuando sea necesario. Por tanto, se generarán avisos por aquellas entidades suceptible de generar avisos (Agenda o Factura). Sería adecuado que la ventana / form que muestre los avisos presente un texto descriptivo del aviso y un enlace al formulario que trate el dato 'a revisar'.

Cita:

Empezado por Delphius (Mensaje 338069)
Hola Bauhaus1975,
Lo que más me nubla y cuesta interpretar es la diferencia entre la clase Gestion y la clase Aviso... ¿al final que hace cada una? ¿Que relación existe entre una y otra?

La Clase 'Gestion' es una clase que representa a Agenda o Factura (o cualquiera suceptible de generar avisos). A modo de ejemplo había usado un término genérico. También puedes pensar que es una clase padre de ambas. Esta clase implementa los métodos de la interfaz 'Aviso'.

La Clase 'Aviso' la había pensado para que ofreciera funcionalidad para mostrar los avisos. En una ventana con la lista antes comentada.

La Interfaz 'Aviso' es la que define el/los método/s necesarios para obtener los avisos. A implementarse en las Clases de tipo 'Gestion'.

Mi idea de usar una interfaz era para garantizar que el método que obtenga los avisos en cada entidad garantizara homogeneidad, es decir, que ofrezca un patrón de comportamiento. Por esto había pensado en usar una interfaz, si bien no es obligatorio. Y no porque estuviera pensando en términos de Java o traduciendo un programa de Java.

La idea de este post era dialogar con gente que ha tenido que implementar este caso para ver qué decisión han optado, o áprender de personas más expertas su opnión de como implementar este caso. Es por eso que a lo mejor necesito que me acerqueis a los 'purismos' que comentas de Delphi para ir implementando este caso de la mejor manera.

Muchas gracias por la atención y un saludo.

Chris 16-02-2009 17:10:48

Estamos hablando en formas astractas. (Class TAviso, TGestion) y cómo las he de utilizar luego?

A cómo dijo delphius anteriormente, eso depende del punto de vista de cada uno. En lo personal YO antes de escribir e implementar una clase la visualizo desde el punto de como la he de llamar, cómo la quiero llamar y qué grado de fácilidad y flexivilidad quiero que tenga cunado la quiera llamar.

Si yo fuera tú, primero me pondría a pensar en que grado de dificultad que tendré al momento de utilizar clases o interfaces, así cómo también implementarlas.

Según la tarea y objetivo que buscas yo mejor dejaría las clases a un lado me utilizaría mejor algun tipo de función en, por ejemplo, la unidad de facturación que me devuelva todos los avisos de facturación y así sucesivamente.

Saludos.

roman 16-02-2009 17:40:09

Hola,

Creo que confunde un poco la terminología que usas. En principio, tal como yo lo entendería, para un sistema de avisos no necesitas ninguna interfaz ni clase ancestra común. Simplemente necesitarías un objeto central GestorAvisos con un método público ColocarAviso:

Código:

+------------------------------+
| GestorAvisos                |
+------------------------------+
| +ColocarAviso(Aviso: TAviso) |
+------------------------------+

Cualquier clase del sistema puede colocar un aviso sin necesidad de implementar interfaz alguna.




No obstante, lo que tú tienes más parece ser una lista de pendientes. En tal caso, creo que podrías partir de una interfaz:

Código:

+-----------------------+
| IEntidad              |
+-----------------------+
| +getListaPendientes() |
+-----------------------+

que tendría que implementar cualquier clase que quiera publicar su lista de pendientes. Cada una de estas clases tendría que registrarse con un gestor central:

Código:

+--------------------------------------------+
| GestorPendientes                          |
+--------------------------------------------+
| -FEntidades                                |
+--------------------------------------------+
| +RegistrarEntidad(Entidad: IEntidad)      |
| +EnumerarPendientes()                      |
+--------------------------------------------+

Dicho gestor, en el momento que tú decidas (al principio de la aplicación, cuando lo requiera el usuario, cada cierto tiempo, etc.) revisará su lista de clases registradas (FEntidades) para saber a cuáles debe solicitar la lista de pendientes.

// Saludos

Delphius 16-02-2009 18:41:39

¡Orden en la sala!

Siempre quise decir eso:D

Pues creo que no se termina de comprender, bien el asunto. Y todo se debe a los nombres tanto de las clases como de sus métodos. Vayamos al primer punto elemental a cuestionar:

¿Quién da a conocer los avisos? ¿Y quien los genera?

No es lo mismo gestionar, que generar;)

A como yo lo entiendo, TFactura y TAgenda son quienes GENERAN avisos (aunque creo que el término más adecuado sería PUBLICAR), los cuales son luego administrados por una sola clase TGestorAviso (por darle un nombre). TGestorAviso tiene por tanto la responsabilidad de ordenarlos, clasificarlos, etc. En pocas, hará con lo avisos lo que deba hacer. Al final, es ésta clase quien terminará mostrando los avisos al usuario.

Una manera de enfocar el tema es algo similar a como lo detalle roman. TAgenda, TFactura y demás clases interesadas se registran a este TGestor. TGestor recibirá de todas las entidades que se registren los avisos. Si no me equivoco en el término, creo que aquí podría ser útil las "clases amigas". Algo similar a como funciona TParam y TParams, y otras colleciones.

Todas las entidades que publiquen avisos debe heredar de una clase base, a falta de imaginación la llamo: TPublicadorAviso. TPublicadorAviso está diseñado para mantener una referencia del Gestor al que se asociará y contará con al menos tres métodos: Suscribirse(), PublicarAviso() y Desuscribrirse() (sería mejor Reigstrar, pero no encuentro su antónimo:p)

Código:

+------------------------------------------+
| TPublicadorAviso                        |
+------------------------------------------+
| - FGestorAviso: TGestorAviso            |
+------------------------------------------+
| + Suscribirse(GestorAviso: TGestorAviso) |
| + PublicarAviso(Aviso: TAviso)          |
| + Desuscribirse                          |
+------------------------------------------+

De éste modo, unas posible (y simples) implementaciones de éstos métodos podría ser:

Código Delphi [-]
procedure TPublicadorAviso.Suscribirse(GestorAviso: TGestorAviso);
begin
  if not assigned(FGestorAviso) 
    then begin
             GestorAviso.Registrar(Self);
             FGestorAviso := GestorAviso;
           end;
end;

procedure TPublicadorAviso.PublicarAviso(Aviso: TAviso);
begin
  FGestorAviso.AgregarPendientes(Aviso);
end;

procedure TPublicadorAviso.Desuscribirse;
begin
  FGestorAviso.Eliminar(Self);
  FGestorAviso := nil;
end;

Como se ve, se delegan algunas cosas a un TGestorAviso, que muy posiblemente sea un Singleton. Ahora TGestorAviso debe tener dos listas, una para llevar sus Publicadores y otra con los avisos. Ya podemos ir viendo algunos de sus métodos:
Código:

+-------------------------------------------+
| TGestorAviso                              |
+-------------------------------------------+
| - FPublicadores: TObjectList              |
| - FAvisosPendientes: TObjectList          |
+-------------------------------------------+
| + Registrar(Publicador: TPublicadorAviso) |
| + AgregarPendientes(Aviso: TAviso)        |
| + Eliminar(Publicador: TPublicadorAviso  |
| + MostrarAviso(Aviso)                    |
+-------------------------------------------+

Creo que no hace falta mucha imaginación y dar detalles de lo que sucede aquí,

Registrar() debería agregar en la lista de publicadores al PublicadorAviso, de forma similar, AgregarPendientes() agrega el aviso a su lista.

Un enfoque similar, habría que determinar cual es el más conveniente, es que el TGestorAviso no maneje la lista, sino que cada PublicadorAviso maneje la propia. En este caso, tal vez TGestorAviso disponga de métodos como ObtenerPendientes() y reciba como parámetro un TPublicadorAviso, y de este modo TPublicadorAviso le hace llegar o conocer sus avisos. Luego, el TGestor "recorre" el listado de estos avisos y actúa en razón a ellos. Ahora podría ser útil un PublicarLista.

Código:

+------------------------------------------+
| TPublicadorAviso                        |
+------------------------------------------+
| - FGestorAviso: TGestorAviso            |
| - FListaPendientes: TObjectList          |
+------------------------------------------+
| + Suscribirse(GestorAviso: TGestorAviso) |
| + PublicarAviso(Aviso: TAviso)          |
| + PublicarLista                          |
| + Desuscribirse                          |
+------------------------------------------+

¿Se entiende? Espero que sí.

Saludos,

roman 16-02-2009 19:03:10

Yo me permito insistir un poco en la nomeclatura. El hecho de haya facturas pendientes es una situación, no un aviso. Porque mientras persista dicha situación, el objeto fuente tendría que estar generando el mismo aviso, que es lo que no me cuadra.

Ahora, más allá de los términos exactos, creo que éste es un caso en donde las interfaces aplican muy bien. Una entidad agenda y una entidad facturas, en principio podrían no tener nada en común salvo el hecho de poder publicar una lista de pendientes. En este caso, derivar ambas de una clase común podria ser algo forzado y no natural para efectos de la aplicación.

Cita:

Empezado por Delphius
Un enfoque similar, habría que determinar cual es el más conveniente, es que el TGestorAviso no maneje la lista, sino que cada PublicadorAviso maneje la propia

A como veo las cosas, tiene que ser así. Porque el hecho de publicar un aviso no resuelve la tarea, es decir, la factura sigue pendiente por ejemplo, y desde luego, no puede ser el gestro de avisos quien cumplimente la operación, debe por fuerza ser la entidad que genera el aviso. Por ello es que aviso no es un término que me parezca adecuado.

Cita:

Empezado por Delphius
En este caso, tal vez TGestorAviso disponga de métodos como ObtenerPendientes()

Básicamente es lo que planteé con el método getListaPendientes de la interfaz IEntidad.

Cita:

Empezado por Delphius
y reciba como parámetro un TPublicadorAviso

aunque esta parte no le veo necesidad. Cada IEntidad (o IPublicadorPendientes) se registra con el Gestor de manera que éste simpemente debe ciclar sobre la lista de registrados llamando al método getListaPendientes:

Código Delphi [-]
for I := 0 to FEntidades.Count - 1 do
begin
  FEntidades[i].getListaPendientes(...);
end;

que básicamente sería lo que llamé EnumerarPendientes.

// Saludos

roman 16-02-2009 20:01:54

Aquí va mi idea más desarrollada:

Partiremos de una clase TPendiente (si quieren llamarla TAviso está bien :)) que represente un pendiente:

Código Delphi [-]
TPendiente = class
private
  FFuente: String;
  FDescripcion: String;

public
  property Fuente: String read FFuente write FFuente;
  property Descripcion: String read FDescripcion write FDescripcion;
end;

Fuente sería el nombre de la entidad que genera el pendiente o aviso y Descripcion sería la descripción del pendiente. Obviamente la estructura real de esta clase dependerá de lo que se quiera publicar.

Luego tenemos la interfaz que publica mensajes

Código Delphi [-]
IPublicadorPendientes = interface
['{B34CC894-1ED9-4968-BE00-09D48676F734}']
  procedure getListaPendientes(Lista: TList);
end;

Lo que está entre corchetes es el GUID (global unique identifier) de la interfaz y es necesario declararlo (Ctrl+Shift+G) para poder moldear una interfaz con el operador as.

getListaPendientes deberá llenar la lista que se le pasa como parámetro con los pendientes que haya.

Después tenemos el gestor de pendientes:

Código Delphi [-]
TGestorPendientes = class
private
  FPublicadores: TInterfaceList;

public
  constructor Create;
  destructor Destroy; override;

  procedure RegistrarPublicador(Publicador: IPublicadorPendientes);
  procedure EnumerarPendientes(Publicar: TPublicarPendiente);
end;

Este gestor mantiene una lista interna de las entidades que se registren para publicar pendientes. Obsérvese que es una lista de interfaces, no de clases. Dicha lista se crearía en el constructor Create y se destruiría en el destructor.

Un entidad que quiera publicar pendientes se registra con el método RegistrarPublicador, quien simplemente añade la entidad a la lista interna.

El método EnumerarPendientes es el encargado de recorrer todos los pendientes de todas las entidades registradas. Pero este método no publica el pendiente, ya que esto es materia de la parte visual de la aplicación, que decidirá si pone el pendiente en un ListView, en un Memo, o lo manda por correo, o cualquier cosa que quiera hacer con el pendiente.

Para ello, al método se le pasa como parámetro un procedimiento, que será el encargado de publicar el pendiente. El tipo TPublicarPendiente se define asi:

Código Delphi [-]
TPublicarPendiente = procedure(Pendiente: TPendiente) of object;

Así, por ejemplo, el formulario principal puede declarar un método

Código Delphi [-]
TMainForm = class(TForm)
private
  procedure PublicarPendiente(Pendiente: TPendiente);
end;

que pondrá el pendiente en el control visual que desee. Cuando se requiera listar los pendientes se llamará al gestor:

Código Delphi [-]
GestorPendientes.EnumerarPendientes(PublicarPendiente);

El método EnumerarPendientes podría implementarse así:

Código Delphi [-]
procedure TGestorPendientes.EnumerarPendientes(Publicar: TProcesarPendiente);
var
  Pendientes: TList;
  I, J: Integer;

begin
  Pendientes := TList.Create;

  try
    // Recorrer la lista de publicadores
    for I := 0 to FPublicadores.Count - 1 do
    begin
      // Obtener la lista de endientes de este publicador
      (FPublicadores[i] as IPublicadorPendientes).getListaPendientes(Pendientes);

      // Publicar cada pendiente de este publicador
      for J := 0 to Pendientes.Count - 1 do
      begin
        Publicar(TPendiente(Pendientes[J]));
      end;
    end;
  finally
    Pendientes.Free
  end;
end;

Como dije antes, EnumerarPendientes simplemente recorre la lista de pendientes más no hace nada con ellos excepto llamar al método que se le pasa como parámetro.

Esto nos permite usar distintos métodos según sea el caso. Por ejemplo, además del método PublicarPendiente del formulario principal, podríamos tener un EnviarPendiente, que se encargue de mandar el pendiente por correo, de manera que

Código Delphi [-]
GestorPendientes.EnumerarPendientes(EnviarPendiente);

tendría el efecto de enviar por correo la lista de pendientes.

// Saludos

Delphius 16-02-2009 20:16:05

Cita:

Empezado por roman (Mensaje 338292)
Yo me permito insistir un poco en la nomeclatura. El hecho de haya facturas pendientes es una situación, no un aviso. Porque mientras persista dicha situación, el objeto fuente tendría que estar generando el mismo aviso, que es lo que no me cuadra.

Pues yo la verdad no entiendo si al final se trata de facturas pendientes... y/o si debemos entender por aviso otra cosa.:o
Hace falta claridad en las explicaciones de Bauhaus1975 sobre el contexto en forma intregral (macro) del problema y no en éstas simples clases.

Cita:

Empezado por roman (Mensaje 338292)
Ahora, más allá de los términos exactos, creo que éste es un caso en donde las interfaces aplican muy bien. Una entidad agenda y una entidad facturas, en principio podrían no tener nada en común salvo el hecho de poder publicar una lista de pendientes. En este caso, derivar ambas de una clase común podria ser algo forzado y no natural para efectos de la aplicación.

Estaba pensando en ello también. Creo que el tener esta interfaz serviría, y además nos evitaría el tener que depender de alguna clase base.


Cita:

Empezado por roman (Mensaje 338292)
A como veo las cosas, tiene que ser así. Porque el hecho de publicar un aviso no resuelve la tarea, es decir, la factura sigue pendiente por ejemplo, y desde luego, no puede ser el gestro de avisos quien cumplimente la operación, debe por fuerza ser la entidad que genera el aviso. Por ello es que aviso no es un término que me parezca adecuado.

Pues yo no puedo decir, ni asegurar que deba ser ser así. Hay cosas que no están bien claras.
Efectivamente, creo que debemos partir de este punto. ¿Qué debemos entender por aviso?

Además, me suena un tanto extraño de que entidades, un tanto dispares como ser TAgenda y Factura deban dar respuesta a una misma problemática. ¿Que és este TAgenda? ¿Qué es esta TFactura? ¿Qué tiene que ver citas, agendas y facturas? No se, pero no me gusta mucho mezclar citas con negocios.:D
Yo pido que Bauhaus1975 se explique apropiadamente.

Cita:

Empezado por roman (Mensaje 338292)
Básicamente es lo que planteé con el método getListaPendientes de la interfaz IEntidad.

aunque esta parte no le veo necesidad. Cada IEntidad (o IPublicadorPendientes) se registra con el Gestor de manera que éste simpemente debe ciclar sobre la lista de registrados llamando al método getListaPendientes:

Código Delphi [-]for I := 0 to FEntidades.Count - 1 do begin FEntidades[i].getListaPendientes(...); end;


que básicamente sería lo que llamé EnumerarPendientes.

// Saludos

Eso noté luego. Tu idea me resulta mejor.

Saludos,

Delphius 16-02-2009 20:26:44

Impresionante roman.
Cuando estaba respondiendo ví que habías puesto algo más concreto.

Me sorprende lo de pasar como parámetro el procedimiento. No se me hubiera ocurrido:o.

Hoy aprendo algo nuevo: desconocía TInterfaceList.:)

Saludos,

roman 16-02-2009 20:29:47

Cita:

Empezado por Delphius (Mensaje 338300)
Además, me suena un tanto extraño de que entidades, un tanto dispares como ser TAgenda y Factura deban dar respuesta a una misma problemática. ¿Que és este TAgenda? ¿Qué es esta TFactura? ¿Qué tiene que ver citas, agendas y facturas?

Precisamente por eso viene lo de interfaces. Agendas, facturas y seguramente otras entidades del sistema del compañero, tiene poco a nada en común, salvo el hecho de notificar que hay tareas pendientes. Y es esta problemática la que resuelve la interfaz. No es que esas entidades deban dar respuesta a una misma problemática, sino que esta problemática es común (y quizá lo único común) a ellas.

// Saludos

roman 16-02-2009 20:33:56

Cita:

Empezado por Delphius (Mensaje 338303)
Me sorprende lo de pasar como parámetro el procedimiento. No se me hubiera ocurrido:o.

Pues son de las cosas que te gustan. Si no me equivoco, no es más que el patrón Iterador (interno).

// Saludos

Delphius 16-02-2009 20:39:17

Cita:

Empezado por roman (Mensaje 338307)
Pues son de las cosas que te gustan. Si no me equivoco, no es más que el patrón Iterador (interno).

// Saludos

Había "escuchado" sobre ese patrón, pero no lo he estudiado. Más adelante le daré su debido tiempo de análisis y estudio y me documentaré al respecto.
Gracias por el dato:).

Saludos,

Bauhaus1975 17-02-2009 11:27:34

Muy buenas compañeros. Me alegra ver como ha crecido el interés en el post (y eso que había empezado flojo).
Es cierto, probablemente lo que nos parece bien explicado no se entienda por diferente uso de términos. Y sin duda, los nombres que tomé inicialmente eran demasiado genéricos.

Cita:

Empezado por Delphius (Mensaje 338300)
Estaba pensando en ello también. Creo que el tener esta interfaz serviría, y además nos evitaría el tener que depender de alguna clase base.

Estupendo, me alegra que seas el primero que me de la razón en algo :). Es broma, mi madre alguna vez ya lo hizo antes.

Cita:

Empezado por Delphius (Mensaje 338300)
¿Qué debemos entender por aviso?

Hasta donde yo había pensado, una descripción y un enlace que pueda abrir un formulario para acceder al dato y poder cambiar esa situación.
Y como apunto más adelante una propiedad 'prioridad' = (urgente, normal)

Cita:

Empezado por Delphius (Mensaje 338300)
Además, me suena un tanto extraño de que entidades, un tanto dispares como ser TAgenda y Factura deban dar respuesta a una misma problemática. ¿Que és este TAgenda? ¿Qué es esta TFactura? ¿Qué tiene que ver citas, agendas y facturas? No se, pero no me gusta mucho mezclar citas con negocios.
Yo pido que Bauhaus1975 se explique apropiadamente.

Nada que ver, evidentemente. Por eso Roman está acertado viendo lo conveniente de introducir una Interfaz que defina la funcionalidad necesaria para obtener el aviso. 'obtener' -> Aquí nos hemos creado confusión con el término. Cada entidad que quiera 'publicar' avisos debe implementar un método con sus propios criterios para obtener dichos elementos.
Es más, por eso he puesto así el ejemplo. Porque el sub-sistema que estamos definiendo quede aislado del contexto. Es decir, igual que hemos hablado de facturas y agenda podemos pensar en un artículo que se haya agotado y hay que pedirlo. (serviría a cualquier proyecto con entidades suceptibles de generar 'pendientes')

Otra cosa, como apuntais: No todos los avisos son iguales. Me explico, a lo mejor es bueno mostrar 'de vez en cuando' en la ventana de avisos los artículos que faltan, pero a lo mejor en cuanto a las facturas pendientes de pago es suficiente con que aparezcan al iniciarse el programa.
Por tanto puede que el objeto que represente a un item 'aviso' tenga 'prioridad' = (urgente, normal) prioridad normal podría ser sólo para mostrar en la ventana al iniciarse el programa, y urgente para mostrar periódicamente.

He leido detenidamente el análisis de Roman y me parece lo más acertado. Y, el uso del InterfaceList y el paso del procedimiento como parámetro impresionante ejemplo de elegancia.

Entonces podemos resumir las clases y sus responsabilidades:

TPendiente: representa a un item. con elementos como (prioridad, fuente, descripcion)
IPublicador: La interfaz que define el método para obtener los pendientes de clase con getListaPendientes(Lista: TList);
TGestorPendientes: Se encarga de ofrecer el registro a las clases que quieran publicar, y de enumerar los items a publicar
TPublicarPendiente: Un tipo procedimiento para que la acción 'publicar' sea cualquier cosa que implemente una clase encargada del tema gráfico u otros.

Podría quedar por sacar punta a como añadir la acción de abrir formulario de la entidad a la que se refiera el item (TPendiente)

Para el tema de controlar avisos de alta prioridad se puede incorporar un sistema de control periódico, si no recuerdo mal esto se ha tratado antes en otros post. (Abajo en la lista de relacionados puede verse algún ejemplo)

Espero que este laborioso estudio ofrezca información de este sistema y muchos compañeros puedan implementarlo cuando les haga falta. Yo estoy ya deseando de implementarlo, a ver si puedo sacar hueco porque estoy con varias cosas a la vez.

Un saludo.

roman 17-02-2009 17:54:04

Cita:

Empezado por Bauhaus1975 (Mensaje 338384)
Cita:

Empezado por roman
Estaba pensando en ello también. Creo que el tener esta interfaz serviría, y además nos evitaría el tener que depender de alguna clase base.


Esto, en realidad, lo dijo Delphius.

Cita:

Empezado por Bauhaus1975
Podría quedar por sacar punta a como añadir la acción de abrir formulario de la entidad a la que se refiera el item (TPendiente)

La clase TPendiente puede tener una propiedad que apunte al formulario deseado.

Por otra parte estaba pensando que una ampliación que puede hacerse es la de incluir al gestor de mensajes en la interfaz IPublicador con objeto de que cada publicador pueda notificar al gestor cuando hay algún cambio en su lista de pendientes.

// Saludos

Bauhaus1975 17-02-2009 18:18:55

Cita:

Empezado por roman (Mensaje 338428)
Esto, en realidad, lo dijo Delphius.



La clase TPendiente puede tener una propiedad que apunte al formulario deseado.

Por otra parte estaba pensando que una ampliación que puede hacerse es la de incluir al gestor de mensajes en la interfaz IPublicador con objeto de que cada publicador pueda notificar al gestor cuando hay algún cambio en su lista de pendientes.

// Saludos

Perdón, lo rectifico ahora mismo.


La franja horaria es GMT +2. Ahora son las 21:10:23.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi