Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 20-11-2014
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Información detallada sobre la interfaz IObserver

Hola amigos.

Hace un par de días, trabajando con Delphi XE5, encontré la interfaz IObserver en System.Classes. Su declaración es la siguiente:
Código Delphi [-]
  IObserver = interface
    ['{B03253D8-7720-4B68-B10A-E3E79B91ECD3}']
    procedure Removed;
    function GetActive: Boolean;
    procedure SetActive(Value: Boolean);
    function GetOnObserverToggle: TObserverToggleEvent;
    procedure SetOnObserverToggle(AEvent: TObserverToggleEvent);
    property OnObserverToggle: TObserverToggleEvent read GetOnObserverToggle write SetOnObserverToggle;
    property Active: Boolean read GetActive write SetActive;
  end;
He podido averiguar un poco sobre ella y veo que está relacionada con LiveBindings y con una relativamente nueva propiedad de TComponent llamada Observers (objeto lista de clase TObservers). Todo esto tiene que ver con el patrón observador que es más o menos conocido.

Se incluyó esa propiedad en TComponent para ayudar a los programadores de clases a implementar de forma más holgada el patrón mencionado. La documentación oficial de la interfaz IObserver es prácticamente nula (como desafortunadamente suele pasar con las características novedosas y poco populares de RAD Studio) y, como de todas maneras suelo cerciorarme de las cosas revisando cómo funcionan por dentro, pude deducir a través del código fuente de varias clases nativas cuál es significado y uso que la VCL (y FMX) hace de las diferentes propiedades y métodos de la interfaz IObserver. Con excepción del método Removed, del cual no hay una sola línea de código fuente que lo llame, como para yo darme una idea de lo que debo tomar en cuenta cuando implemente la interfaz.

Así que aquí estoy, después de intentar con Google y Yandex, preguntando si casualmente alguno de ustedes tiene más información al respecto. Me serviría cualquier dato o pista de valor sobre la interfaz IObserver de Delphi y en especial su método Removed, así como cualquier "tuit" que quieran hacer de esta solicitud (con algo de suerte puede que el mensaje llegue hasta alguien de los que estuvo presente cuando se diseñó esta característica).

Lo sé, lo sé, es probable que haya que abrir un hilo similar en los foros de Embarcadero, pero aquí es más cómodo preguntar primero.

Muchas gracias.

Al González.
Responder Con Cita
  #2  
Antiguo 20-11-2014
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Hola Al, vi tu duda en Twitter. No uso esa versión de Delphi, es más me pasé a CodeTyphon, por lo que no estoy tan al tanto de las novedades pero intentaré hechar algo de luz.

El patrón Observador, como seguramente ya lo habrás estado estudiando, consiste de 2 clases. La clase Sujeto (o también llamada Observable) y la clase Observador.
El patrón fue pensado para dar solución a la forma en como una clase notifica que algo ha cambiado sin verse fuertemente acoplada a las clases interesadas.
Desde la perspectiva del Sujeto, las clases a las que avisa, las percibe como una interfaz única sin importarle realmente como están implementadas. Simplemente se limita a notificar.

El Sujeto mantiene una lista de todos los observadores registrados, activos o no. Y cuando sea necesario recorre esa lista enviándoles el mensaje de notificación. Lo que hará cada uno ya es otra cosa.

Del código de muestra que das, a mi ver falta la mitad. Eso corresponde a los observadores más, debe haber una interfaz ISubject o IObservable que establece los métodos que han de tener ésta.

Llendo a tu duda puntual, el método en cuestión da a entender que hacer cuando el Observador solicita ser removido de la lista.

Recuerda que como interfaces tu desbes luego dar la implementación que tu consideres oportuna. Puedes ver un ejemplo de que como llevar el patrón en este hilo de DA. Quizá eso te aclare algunas cosas.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #3  
Antiguo 20-11-2014
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.039
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Cita:
Empezado por Delphius Ver Mensaje
Saludos
Saludos
Responder Con Cita
  #4  
Antiguo 20-11-2014
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Gracias, Marcelo. Mi comprensión del manejo de interfaces no es mala, y está claro lo que dices. Pero rescato este punto:
Cita:
Empezado por Delphius Ver Mensaje
[...] el método en cuestión da a entender que hacer cuando el Observador solicita ser removido de la lista.
Eso mismo pienso, pero como no hay nada de nada (ni código, ni documentación) que asiente cuándo podría o tendría que ser llamado ese método, queda una rendija de duda.

Me parece que la clase TObservers (tipo de la propiedad Observers de TComponent), debería llamar al método IObserver.Removed en su método RemoveObserver (tomando la interfaz IObserver del parámetro AIntf), pero como puede verse no ocurre tal cosa:
Código Delphi [-]
procedure TObservers.RemoveObserver(const IDs: array of Integer; const AIntf: IInterface);
var
  LID: Integer;
  LList: IInterfaceList;
  I: Integer;
begin
  for I := 0 to Length(IDs) - 1 do
  begin
    LID := IDs[i];
    if FObservers.TryGetValue(LID, LList) then
    begin
      LList.Remove(AIntf);
      if LList.Count = 0 then
      begin
        FObservers.Remove(LID);
        LList := nil;
      end;
    end;
  end;
end;
Es probable que Embarcadero añada algún cambio después de la línea "LList.Remove(AIntf);", si es que no lo ha hecho ya, en las siguientes versiones.

Alguien que tenga XE7 instalado, ¿sería tan amable de verificar si el método TObservers.RemoveObserver sigue igual o presenta alguna modificación en su código fuente? El archivo de código es System.Classes.pas.

Muchas gracias.

Al.
Responder Con Cita
  #5  
Antiguo 21-11-2014
Avatar de ElKurgan
[ElKurgan] ElKurgan is offline
Miembro Premium
 
Registrado: nov 2005
Posts: 1.234
Poder: 20
ElKurgan Va camino a la fama
En Delphi XE7 está exactamente el mismo código que muestras en el post anterior, es decir, no han arreglado nada.

Saludos
Responder Con Cita
  #6  
Antiguo 21-11-2014
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Hola Al,
Lamentablemente no hay mucho que yo pueda hacer. Al no contar con esa versión de Delphi.

Sabiendo que entre XE5 y XE7 no hubo mucho tiempo de salida era de esperarse que no hubiera algún cambio en dicha clase. Al menos que exista otra clase que implemente dicha interfaz y haga algo con él no sabría que pensar.

Lo más probable es que exista para que el desarrollador pueda definir sus propios observadores y puede que le sea de utilidad un método Removed que deseen disparar cuando se elimina de la lista. No encuentro otra explicación. Recuerda que el que ellos no lo hayan usado o darle funcionalidad a ese método... tu puedes tener tu Observer con dicha funcionalidad. Para evacuar esta duda habría que buscar en la VCL y/o FMX si por casualidad no hay alguna clase que implemente dicha interfaz.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #7  
Antiguo 21-11-2014
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Gracias por la confirmación, ElKurgan. En la empresa todavía no hemos adquirido la actualización a XE7, pero estoy seguro que lo haremos en un par de meses.

------

Gracias Marcelo.

En la VCL/FMX sí hay un par de clases que implementan la interfaz IObserver. Se trata de TBindObserver y TEditLinkProxy, de las cuales no hay documentación por el momento. El código de los métodos Removed de dichas clases realizan acciones que van en la lógica de lo que hemos venido comentando. Incluso el segundo de ellos —TEditLinkProxy.Removed— termina llamando al método Removed de una interfaz derivada de IObserver (IEditGridLinkObserver), pero no parece ser llamado por nadie. Aquí podría haber recursividad pero, como es lógico, todo proceso recursivo debe iniciar por una tangente de entrada que para el método IObserver.Removed parece no existir.

Sigo pensando que al método TObservers.RemoveObserver le falta ese desencadenamiento. La buena noticia es que este es virtual, y ya me adelanté a crear una clase derivada TghObservers, con la suerte de que el método que se encarga de crear la propiedad Observers de TComponent (GetObservers) también es virtual. Lo anterior quiere decir que puedo definir clases de componentes donde su propiedad Observers, declarada de tipo TObservers, sea un objeto TghObservers, asegurándome con ello de que el método Removed sea llamado para cada interfaz observador que sea eliminada de esa lista.

Lo malo es que Delphi todavía no tiene redefinición de clases (herencia insertada), con lo cual me ahorraría escribir varias redefiniciones del método GetObservers, prácticamente repitiendo el mismo código, cuando haya que derivar de diferentes clases nativas descendientes de TComponent (lo que es bastante común).

Este es mi borrador del método virtual RemoveObserver redefinido en TghObservers. De paso he agregado el evento OnObserverRemoved, a semejanza del evento OnObserverAdded ya presente en la clase padre.
Código Delphi [-]
  Procedure TghObservers.RemoveObserver (Const IDs :Array Of Integer;
    Const AIntf :IInterface);
  Var
    ID :Integer;
    Observer :IObserver;
  Begin
    Inherited RemoveObserver (IDs, AIntf);
    Observer := (AIntf As IObserver);
    Observer.Removed;  // We notify the observer that it has been removed

    If Assigned (OnObserverRemoved) Then
      For ID In IDs Do
        OnObserverRemoved (ID, Observer);
  End;
Salvo que se arroje más luz sobre el tema y haya que replantearlo, esta pretendida mejora estaría disponible en la primera liberación de GH Freebrary para Delphi XE5 a XE7.

De todas formas agradeceré cualquier otro dato que tengan.

Un saludo.

Al González.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Duda sobre interfaz gráfica de sistema Spk2000ar Varios 1 13-05-2011 19:34:02
OJO NOVATOS: Excelentes artículos sobre la interfaz de usuario. AzidRain Varios 5 27-03-2008 19:16:45
Problemas para desplegar información detallada Nelly Varios 20 10-04-2007 19:54:21
Necesito documentacion detallada sobre ECO edalmasso Varios 2 12-01-2006 09:47:57
Información sobre DOA Ana Conexión con bases de datos 3 05-07-2003 14:11:13


La franja horaria es GMT +2. Ahora son las 19:48:28.


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
Copyright 1996-2007 Club Delphi