DESIGN PATTERN OBSERVER : IMPLÉMENTATION RÉUTILISABLE

DeltaFX Messages postés 449 Date d'inscription lundi 19 avril 2004 Statut Membre Dernière intervention 8 avril 2009 - 30 avril 2006 à 14:03
paulatreides Messages postés 1 Date d'inscription mardi 21 octobre 2003 Statut Membre Dernière intervention 12 juin 2008 - 12 juin 2008 à 15:31
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/37338-design-pattern-observer-implementation-reutilisable

paulatreides Messages postés 1 Date d'inscription mardi 21 octobre 2003 Statut Membre Dernière intervention 12 juin 2008
12 juin 2008 à 15:31
Il y a un composant teechart de steema dans ce programme...
et j'ai pu le compiler et l'exécuter avec turbo explorer
(alors qu'un autre prog avec ce même composant j'ai pas pu)
C'est étrange... Quelqu'un à une explication ?

Merci
DeltaFX Messages postés 449 Date d'inscription lundi 19 avril 2004 Statut Membre Dernière intervention 8 avril 2009 2
29 nov. 2006 à 00:46
Ben un peu que j'y porte de l'interet, tu avais fait ce tuto en réponse à une de mes questions sur le forum. Or, quand je pose une question, c'est que la réponse m'interresse :)


Donc dans le cadre d'un prog simple, puis-je les omettre, ces identifiant uniques ?




Cette implémentation résoud une partie du problème qui me turlupinait à l'époque (et que j'avais réglé à la barbare-pas trop POO dirons-nous) : faire réagir mes forms (celles qui en ont besoin donc), à une source de données : dans le cas présent une carte interface USB, où en gros quand telle entrée passait à 1, je devais signifier à la form s'occupant de la lecture MP3 de faire un mute, et à celle s'occupant de la camera de recul de passer en plein écran et inversement.

Ensuite une source composite est apparue : un GPS ( à 1 Hz) fusionné à 2 accéléromèetres 3D ( à 20 Hz), le tout dans un thread, avec 2 filtres de Kalman pour le cas ou le gps ne renvoie rien,le tout en temps réel mou vu que plateforme zindoz : OK, là aussi, interface, et notification de mise a jour de 2 forms.

Pareil pour le bus CAN-habitacle et les données du tauradio ( faire croire au toradio qu'il a un chargeur cd de branché....) rebelote, interface, pif pouf.

Là ou ça commence à faire lourd pour mes neurones toutes ces interfaces à la ActionListener Style, c'est qu'en plus, chacune des forms doit écouter aussi la form principale pour les cas de mise en veille du système : procedure PrepareToHibernate, du genre déconnecter la carte USB, fermer le port GPS, interrompre les lectures des acceleromètres, suspendre les threads etc etc; et sa petite soeur, ResumeFromHibernate qui relance tout ce qui était actif avant.

Ne nous arretons pas là, paske qu'une partie du prog, via SpeedFan et son segment mémoire partagé, me surveille qqs températures /vitesses de ventilo dans le boitier du pc, et que ce bout de code peut me générer plusieurs niveaux d'alerte, en fonction desquels certaines fonctions se désactivent pour alleger le proc, voir au pire en arriver à balancer un ordre de shutdown au PC.

Donc une info part de la partie Hardware vers la form principale, qui détermine ce qu'il faut faire et qui elle doit dispatcher des ordres vers les autres forms....

Ca commence à faire lourd niveau qui observe quoi. Finalement j'avais résolu le truc en utilisant ça comme modele de Forms :

unit ExtendedForm;

interface
uses
Forms;

type
TExtendedForm = class(TForm)
private
{ Déclarations privées }
public
{ Déclarations publiques }
procedure AnalyseThis(Msg:String;Flag:integer);virtual; // Pas oublier le virtual, très important !
end;


implementation

{ TExtendedForm }

procedure TExtendedForm.AnalyseThis(Msg:String;Flag:integer);
begin
// rien
end;

end.

et en ayant dans l'unit qui gere toute les var globales, les fonctions :


...
implementation

//-----------------------------------------------------------
procedure SpreadMsg(aMsg:String;aFlag:integer);
var i: integer;
begin
for i:=NbOfForms downto 0 do
if FormNames[i]<>'' then
with FindGlobalComponent(FormNames[i]) as TExtendedForm
do AnalyseThis(aMsg,aFlag);
end;

//-----------------------------------------------------------
procedure RegisterMe(aName: string;aTag:integer);
begin
FormNames[aTag]:=aName;
end;

//-----------------------------------------------------------
procedure UnRegisterMe(aTag:integer);
begin
FormNames[aTag]:='';
end;




Mais ca restait très séquentiel.... Voila pourquoi je cherchais jadis une forme de communication plus générique, plus dans le style des Post/send Messages windows, donc au choix asynchrone (Fire n'Forget) ou pas.




... Voili voilou...

Tiens au fait, ca existe les Moniteurs en Delphi, les trucs qui permettent de mettre des threads en suspend sur une condition particulière, puis de les réveiller ?
cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 32
28 nov. 2006 à 23:36
Question très pertinente mon cher DeltaFx !

Dans le code source proposé ici, on peut dire que les identifiants uniques des interfaces utilisées ne servent à rien.

En revanche, c'est une bonne habitude de les utiliser si tu dois faire usage de la méthode QueryInterface ou de la fonction Supports qui réclament un identifiant d'interface (IID).

C'est aussi important si tu crées un serveur automation qui a besoin d'être enregistré sur une machine pour être appelé. La base de registres de Windows en est remplie.

On ne choisit pas le contenu des clés mais on l'obtient :
- soit par la combinaison de touches [Shift][Ctrl][G]
- soit par programmation en appelant la fonction CoCreateGuid déclarée dans ActiveX.pas (ou encore CreateGuid déclarée dans SsyUtils.pas) de la façon suivante :
var
Guid: TGUID;
begin
CoCreateGuid(Guid);
Memo1.Lines.Add(GuidToString(Guid));
end;

"Autant je saisis bien tout" : ce genre de commentaire fait bien plaisir.
Merci de porter un intérêt à ce code.
DeltaFX Messages postés 449 Date d'inscription lundi 19 avril 2004 Statut Membre Dernière intervention 8 avril 2009 2
28 nov. 2006 à 15:18
Petite question de la part du noob de service. Autant je saisis bien tout , autant je me demande encore ce que sont et à quoi servent les series alphanumériques dans les codes des interfaces IMeteo, IObservables & IObserver ?

IMeteo = interface
['{83EF5DD2-9F1D-4BE9-8F97-57BE0BDED25C}']
...

IObservable = interface
['{B72C935C-4E37-405F-B778-1C507A8F8BB9}']
...

IObserver = interface
['{8B1211C7-5799-486F-A66C-EF999D087229}']
...


Seraient-ce des clefs de registre (ça y ressemble...) ? Comment les choisit-on ?
cs_pouicky Messages postés 19 Date d'inscription lundi 26 avril 2004 Statut Membre Dernière intervention 4 août 2010
7 mai 2006 à 15:49
Que tu t'interesses à la question est dejà super. Je m'aperçois en effet que pour ce qui est des données, le pattern observer a d'autre implications. Et je me prépare à poster une source sur la réutilisation du code et découplage entre objets et interface dans une application simple en delphi (elle sera imparfaite, et illustrera donc les problemes posés, et peut-etre d'autres)
j'attends tes pistes avec impatience ;). Ce qui manque plus que la technique sur ces problemes c'est l'expérience et j'en manque cruellement.
cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 32
7 mai 2006 à 12:02
Je viens de mettre à jour le code ainsi que le pdf en espérant que cela sera moins "brumeux" pour certains :o)

C'est sûr que quand on parle architecture logicielle, mieux vaut avoir l'esprit clair et un minimum d'expérience dans ce domaine.

Pouicky, je ne t'oublie pas, mais...

L'urgent est déjà parti,
L'impossible est en train de se faire,
Pour les miracles, je demande un délai !
cs_shining Messages postés 304 Date d'inscription lundi 30 décembre 2002 Statut Membre Dernière intervention 10 mars 2012
4 mai 2006 à 20:39
Lol !!!,non en fait je n'ai qu'une petite fenêtre contrairement à vous , qui avez plus de possibilités avec la fenêtre avancée !!!, je suppose que le site fait appel à la java virtual machine où quelque chose comme ça !!! mais bon c'est aussi de mon habitude de faire des fautes :] ça fait fashion parait-il !!!
le ScreenShot me fait penser à ESS MODEL pour faire des diagrammes en UML
c'était jadis un projet commercial, qui par la suite est devenu OpenSource à voir et à télécharger absolument !!!
http://essmodel.sourceforge.net/screenshots.html
cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 32
3 mai 2006 à 00:11
Tu n'as pas choisi n'importe qui comme référence. John COLIBRI est une référence !
Je connaissais son site mais je ne le trouve pas facile à lire. C'est un avis personnel.
Les ouvrages que j'ai cité dans la partie bibliographie sont tous publiés en langue française et ça aide pour bien comprendre les patterns et les maîtriser.

Shining : de même qu'il faut tourner sept fois sa langue dans bouche avant de parler, mieux vaut se relire deux fois avant de cliquer sur le bouton "ajouter votre commentaire", lol.
++
cs_shining Messages postés 304 Date d'inscription lundi 30 décembre 2002 Statut Membre Dernière intervention 10 mars 2012
2 mai 2006 à 21:36
oula c'est quand qu'on pourra editer nos messages ? et retiré les vilaines fautes d'orthographes ? lol
cs_shining Messages postés 304 Date d'inscription lundi 30 décembre 2002 Statut Membre Dernière intervention 10 mars 2012
2 mai 2006 à 21:34
Oui en effet DelphiProg, le ChoicePatterne quant à lui est assez limité dans ses possibilités et l'exemple choisit n'est pas vraiment très reprensative du choice pattern !!, allez pour me faire pardonner voici un lien très intérréssant à ne pas rater, qui d'une certaine façon pourrait-être un complément d'info à ce superbe tutoriel !!!

de la Strategy à l'Iterator tout y est ou presque !!!

http://www.felix-colibri.com/papers/design_patterns/the_lexi_editor/the_lexi_editor.html
@+
Francky23012301 Messages postés 400 Date d'inscription samedi 6 août 2005 Statut Membre Dernière intervention 11 février 2016 1
2 mai 2006 à 00:40
Bon j'ai pas tout compris à ta source vu le niveau mais je dis quand meme : "CHAPEAU MONSIEUR". C'est sans aucun doute du grand art.

Le plus dingue c'est quant te connaissant je suis sur que tu as fais ca en meme pas 1h. Aurais tu avant fais la fameuse incantation de fOxi ??
cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 32
1 mai 2006 à 22:57
Shining : j'ai jeté un oeil sur les liens que tu as donné. L'implémentation du dp observer repose sur l'utilisation de l'interface Observable fournie par Java.
Delphi n'en disposant pas (je suis d'accord qu'on peut facilement la reproduire) et comme il est bon de comprendre les principes qui sous tendent, le code fourni ici permet de mieux saisir les mécanismes en jeu.

J'ai oublié de mentionner dans le tuto que Delphi pour .Net proposait le multicast, variante du dp observer. On peut en parler, mais il n'y aurait pas grand chose à dire puisque tout est déjà fait, un peu comme en Java.

Quant au choice pattern, s'il est présenté comme plus léger que le strategy pattern, l'exemple fourni ne démontre rien à mon avis puisque l'on appelle séquentiellement chacune des interfaces IChoicePattern au lieu de faire le bon choix comme dans le cas du strategy design pattern.
cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 32
1 mai 2006 à 22:42
Ta remarque est tout à fait exacte. Heureusement que la méthode AddObserver vérifie la liste avant d'ajouter un observateur. De ce fait, le nombre d'éléments dans la liste n'est pas incrémenté deux fois mais une seule.
Tu peux donc supprimer ou mettre en commentaire la ligne :
FObservable.AddObserver(StatsMeteoForm);
dans la fiche principale.

Félicitations pour ta perspicacité.
Quant à moi...:o(
cs_pouicky Messages postés 19 Date d'inscription lundi 26 avril 2004 Statut Membre Dernière intervention 4 août 2010
1 mai 2006 à 21:57
Dans l'exemple, il ya 2 fiches Releves et Stats prévues pour observer, et ayant un constructeur qui enregistre leur membre observateur aupres du sujet observable passé en parametre.

Or l'exemple illustre 2 manieres de gérer l'inscription des observateurs au sujet : Pour la fiche de stat, c'est la fiche principale qui l'inscrit sur son propre FObservable. Alors que pour la fiche de releves c'est le constructeur qui inscrit la fiche sur le membre FObservable de la fiche relevé (j'essaie de résumer, et on est bien d'accord que les membre FOBservables des deux fiches sont le même objet, non?).
N'y a t'il pas alors deux inscriptions pour la fiche de stats?
pour verifier cela j'ai saisi testé cela dans l'unité Uobservable

procedure TObservable.AddObserver(Obs: IObserver);
begin
if FObservers.IndexOf(Obs) = -1 then
FObservers.Add(Obs);
ShowMessage(inttostr(fobservers.Count));
end;

procedure TObservable.RemoveObserver(Obs: IObserver);
begin
if FObservers.IndexOf(Obs) <> -1 then
FObservers.Remove(Obs);
ShowMessage(inttostr(fobservers.Count));
end;
et il y a un truc bizarre : le clic sur "listing" est cohérent mais le clic sur "statistiques" provoque deux passages dans AddObservers et avec la meme valeur pour Fobservers.count (s'enregistre sans incrementation?? ya t'il une transmission sans traitement de la liste des observateurs entre la fiche principale et la fiche de stats?)
cs_shining Messages postés 304 Date d'inscription lundi 30 décembre 2002 Statut Membre Dernière intervention 10 mars 2012
1 mai 2006 à 21:31
cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 32
1 mai 2006 à 19:25
Cirec :
Tu as suivi les recommandations et tu as bien fait.
Je ne pouvais pas, à la simple lecture du code source, vous montrer la démarche qui fût la mienne. C'est en cela que les outils de modélisation comme UML apportent un plus en se situant au dessus du code source.

Model Maker fût livré avec Delphi 7. Ce n'est pas indispensable de l'avoir mais c'est bien utile quand même.
En passant, Model Maker permet l'application de certains design patterns dont l'observateur. Un conseil, n'utilisez pas le code généré, vous vous enfermeriez dans une hiérarchie de classes.

Les versions .Net de Delphi sont maintenant livrées avec ToGether.
Notez aussi que ce genre d'outil n'est pas livré avec les éditions perso.

Que Pouicky me pardonne, mais ses questions appellent des réponses plus développées et je lui consacrerai le temps nécessaire un peu plus tard.

Je sens qu'on va avoir un vrai débat de passionnés !
Utilisateur anonyme
1 mai 2006 à 14:06
Salut,
eh ben que dire ...
C'est tout simplement génial
L'exemple est bien fait et le PDF (pour m'a part) m'a apporté la lumière nécessaire à la compréhension du code (il faut absolument lire le PDF en premier)
Du coup j'ai téléchargé les deux exemples disponibles sur le site et j'ai une petite question :

Dans l'autre exemple vous parlez de Model Maker que je n'ais pas trouvé.
Alors est il uniquement disponible avec D7 pro ?
Je possède un D4 Pro et j'ai eu accès à un D9 Pro mais pas de trace de Model Maker.

Merci pour ce code, ça ouvre de nouvelles perspectives.
20/10 Bravo

@+
Cirec
cs_pouicky Messages postés 19 Date d'inscription lundi 26 avril 2004 Statut Membre Dernière intervention 4 août 2010
1 mai 2006 à 12:27
Un super tuto qui élève l'esprit sur des horizons plus larges

J'en avais vu qui expliquaient la méthodologie Composition ou bien le méthodologie interface, mais là tout s'éclaire. Cependant, je me penche en ce moment sur MVC plus prisé en langages web, mais qui me semble tres lié au pattern observer. J'espere que le probleme que je pose maintenant tombe à propos:
Mon but est de faire une appli qui puisse changer de base de données avec un minimum d'efforts. (exemple Le SQL de Oracle et le SQL d'access, qui ne sont pas les mêmes).
Je pense décomposer l'appli en trois parties (Modele-Vue-Controleur:
1- Une classe de composants d'acces aux données (un module qui pourrait etre interchangé selon le sgbd et/ou l'architecture) - Le Modèle
2- Les objets "métiers" qui appelleraient des methodes de cette classe d'acces aux données (composition de composants)-Le controleur
3- Les formulaires qui observeraient les objets métiers, et implementeraient l'ergonomie- la vue

Or tout ce petit monde serait sujet et observateur des autres.
L'interface devrait se tenir au courant de l'état de la base de données et de l'état des objets métiers
Les objets doivent se tenir au courant de l'état de la base et de l'interface lorsque l'utilisateur agit.
Il y aura les acces aux données faits par les objets métiers
Il y aurait les acces aux données par les fiches (dbgrid relié par exemple) (pas tres souhaitable dans l'optique MVC)
Il y aurait autant de commandes sql à envoyer que d'objets modifiés + le retour des resultats à gérer.

Questions:
-Doit-on limiter les rôles sujets observateurs au minimum pour les performances ou cela altere t'il tres peu la fluidité d'une appli.?
-Les meilleurs choix sont il de "mapper les tablesBDD avec des composants DBTables ou plutôt d'utiliser un composant par type d'action :Objet"command", objet "Query" qu'on réutiliserait pour les differents acces??

Je n'aime pas trop les datamodules pleins de TABLES avec Maitre/esclave qui semblent trop proches de la base.
Dans quelles mesures peut on compter sur la puissance des composants BDD de delphi pour refléter l'état des données?
N'ayant pas d'expérience sur le sujet, quelqu'un peut-il m'indiquer une piste?
John Dogget Messages postés 384 Date d'inscription vendredi 18 juin 2004 Statut Membre Dernière intervention 7 mai 2009
1 mai 2006 à 03:13
Moi aussi ça me semble un peu (beaucoup) brumeux :/
Si c'est utile pour un professionnel, un amateur n'y trouvera certes pas son compte, c'est bien trop compliqué.
C'est d'ailleurs pas ça qui l'empechera de pondre une petite appli parfaitement fonctionnelle.
cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 32
30 avril 2006 à 23:42
Merci pour vos remarques et suggestions.

Foxi : le pdf explique les points esentiels du code et la démarche suivie. De plus, j'ai pris la précaution d'écrire sur cette page web : "Le code source n'est volontairement pas commenté. Reportez-vous au document pdf joint à l'archive."

Mais, comme tu l'as dit, c'est du costaud. :o)
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
30 avril 2006 à 22:31
si je puis faire une petite suggestion, on pourrais par exemple, a defaut de commentaire dans le source mettre un simple {voir chapitre X de l'aide}
sur les points importants, ne trouve tu pas ?

mais ça me semble un peu ... brumeux a faire ...
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
30 avril 2006 à 22:29
du beau, du costaud ...

un bel exemple pour apprécier les possibilitées des interfaces, a analyser a tete reposée.

cependant, le code manque de commentaires ou alors ils n'apparraissent pas dans l'editeur du site.
mais bon, vus le publique auquel il s'adresse, plus l'aide PDF fournie qui est de la meilleure qualitée.

cela merite un 20/10 ...
DeltaFX Messages postés 449 Date d'inscription lundi 19 avril 2004 Statut Membre Dernière intervention 8 avril 2009 2
30 avril 2006 à 14:03
Bonne idée les prérequis, étant passablement rouillé niveau POO et total-noob niveau interface, j'ai ramé un poil à l premiere lecture du source :) Forcément, apres avoir révisé, ca passe mieux.
Rejoignez-nous