Page 1 sur 1

Besoin de l'avis d'un expert

Publié : sam. 30/avr./2005 16:48
par Guimauve
Je finalise un petit programme qui génère du code PureBasic automatique.
Il sert à créer toute les méthodes pour manipuler une structure simple de données.

Bref, c'est pour faire soit de la Programmation Basé Objet (PBO), soit de la Programmation Orienté Objet (POO).

La seule différence entre la PBO et la POO c'est qu'il n'y a pas de classe pour l'objet dans la PBO. Mais le fonctionnment est le même. C'est à la fois un avantage et un inconvéniant. En POO l'objet est protègé alors qu'en PBO il faut faire gaffe, on peut écrire des données par erreur dans l'objet. En revanche, on peut facilement ajouter des méthodes pour manipuler l'objet sans se casser la tête à les inclures dans l'interface.

Les entrées du programme :

Le nom de la Structure :
Info

Les champs :
Nom.s
Prenom.s
Age.b

Le nom des pointeurs :
*Alpha
*Beta

Le nom du paramètre :
Variable

Le nom de l'interface :
Methode

Le nom de la structure de l'interface :
StructMethode

Et voiçi le code généré :

Code : Tout sélectionner

Structure Info

    *Next.Info
    *Previous.Info
    Nom.s
    Prenom.s
    Age.b

EndStructure

Procedure.s GetInfoNom(*Alpha.Info)
    ProcedureReturn *Alpha\Nom
EndProcedure

Procedure.s GetInfoPrenom(*Alpha.Info)
    ProcedureReturn *Alpha\Prenom
EndProcedure

Procedure.b GetInfoAge(*Alpha.Info)
    ProcedureReturn *Alpha\Age
EndProcedure

Procedure SetInfoNom(*Alpha.Info, Variable.s)

    *Alpha\Nom = Variable

    ProcedureReturn *Alpha
EndProcedure

Procedure SetInfoPrenom(*Alpha.Info, Variable.s)

    *Alpha\Prenom = Variable

    ProcedureReturn *Alpha
EndProcedure

Procedure SetInfoAge(*Alpha.Info, Variable.b)

    *Alpha\Age = Variable

    ProcedureReturn *Alpha
EndProcedure

Procedure UpdateInfo(*Alpha.Info, Nom.s, Prenom.s, Age.b)

    *Alpha\Nom = Nom
    *Alpha\Prenom = Prenom
    *Alpha\Age = Age

    ProcedureReturn *Alpha
EndProcedure

Procedure TransferInfo(*Alpha.Info, *Beta.Info)

    *Alpha = *Beta

    FreeMemory(*Beta)

    ProcedureReturn *Alpha
EndProcedure

Procedure InitInfo()

    *Alpha.Info = AllocateMemory(SizeOf(Info))

    ProcedureReturn *Alpha
EndProcedure

Procedure CreateInfo(Nom.s, Prenom.s, Age.b)

    *Alpha.Info = AllocateMemory(SizeOf(Info))

    *Alpha\Nom = Nom
    *Alpha\Prenom = Prenom
    *Alpha\Age = Age

    ProcedureReturn *Alpha
EndProcedure

Interface MethodeInfo

    GetInfoNom(*Alpha.Info)
    GetInfoPrenom(*Alpha.Info)
    GetInfoAge(*Alpha.Info)
    SetInfoNom(*Alpha.Info, Variable.s)
    SetInfoPrenom(*Alpha.Info, Variable.s)
    SetInfoAge(*Alpha.Info, Variable.b)
    UpdateInfo(*Alpha.Info, Nom.s, Prenom.s, Age.b)
    TransferInfo(*Alpha.Info, *Beta.Info)
    InitInfo()
    CreateInfo(Nom.s, Prenom.s, Age.b)

EndInterface

Structure StructMethode

    GetInfoNom.l
    GetInfoPrenom.l
    GetInfoAge.l
    SetInfoNom.l
    SetInfoPrenom.l
    SetInfoAge.l
    UpdateInfo.l
    TransferInfo.l
    InitInfo.l
    CreateInfo.l

EndStructure
Je remercie tout ceux qui prendront le temps de faire une analyse du code.

A+
Guimauve

Publié : sam. 30/avr./2005 20:11
par Droopy
Une fois que tu auras fini ton soft, te serait-il possible d'y inclure un exemple simple

avec 2 versions :

1 en PureBasic classique
1 en PureBasic avec POO

ceci afin que je comprenne ( et d'autre aussi je pense ) comment programmer en POO ( et voir si l'investissement par rapport à la façon de programmer classique est rentable )

Merci

Publié : sam. 30/avr./2005 21:35
par Heis Spiter
J'essairais de voir demain ;)
@Droopy : j'ai posté un exemple + un tuto, ça doit être clair, non ? :).

Publié : sam. 30/avr./2005 21:44
par Droopy
Désolé j'avais décroché après la partie théorique de ton tuto :oops:
Il y a effectivement un exemple :)

Merci

Publié : dim. 01/mai/2005 10:02
par Dräc
Salut Guimauve,

Je n’ai pas eu l’occasion de te remercier pour ton intervention sur le sujet « POO : avantages ou inconvénient». Je le fais au moins là!
Si tu y es intervenu, c’est aussi que tu possèdes certaines connaissances et une pratique de la POO.

Pour en venir à ton sujet, ton exemple me semble incomplet, voir inachevé.
Probablement qu’un exemple serait très utile pour le comprendre exactement, car à mes yeux il y a quelques incohérences.
Il est évident que l’objet que tu proposes de manipuler est de type MethodeInfo.
Aussi comment comptes-tu, par exemple, initialiser (créer + initialisation) ton objet ?
Tel que construit, l’intanciation est une methode de l’objet. Difficile alors de l’utiliser avant d’avoir créer l’objet. Il y a donc un problème !
Incomplète, car tu n’utilises pas la structure StructMethode ! Pourquoi existe-elle si ce n’est pour indiquer au compilateur les methodes de l’objet ?
Inachevé, car que fais-tu des champs *Next et *Pevious que tu imposes ? Bien que l’on imagine où tu veux en venir, ils ne sont pas gérés…
Je m’attends aussi à ce que l’expression « *Alpha.Info » disparaisse des arguments des méthodes lors de leurs déclarations dans l’interface.

Bref, je pense qu’un exemple d’utilisation devrait accompagner ta méthodologie de gestion de structure, pour y permet d’y voir plus clair… :wink:

Publié : dim. 01/mai/2005 12:22
par Guimauve
:( Je vois que ce que je demande n'est vraimant pas clair.
Dräc a écrit :Si tu y es intervenu, c’est aussi que tu possèdes certaines connaissances et une pratique de la POO.
Je comprends le principe de base de la POO mais je ne sais pas comment l'implanter dans PureBasic. C'est pour cette raison que je fais de la PBO, qui est le concept de programmation à l'origine de la POO. Ça marche bien dans PureBasic sans trop se poser de questions.

Je fais cet éditeur parce que je suis paresseux.

JE SUIS TROP CHEAP POUR TAPER LE CODE SUIVANT DANS L'ÉDITEUR :

Code : Tout sélectionner

Procedure.s GetInfoNom(*p.Info)
    ProcedureReturn *p\Nom
EndProcedure
ET J'AI ENCORE MOIN ENVIE DE TAPER LES AUTRES MÉTHODES.
JE DEMANDE A UN PROGRAMME DE LE FAIRE À MA PLACE.


Ce que je vous demande :

Est-ce qu'avec le code fourni, seriez-vous en mesure de continuer votre programme sans modifier le code générer automatiquement ?
Inachevé, car que fais-tu des champs *Next et *Pevious que tu imposes ? Bien que l’on imagine où tu veux en venir, ils ne sont pas gérés…
Ce n'est pas imposé, on peut signaler à mon éditeur de l'ajouter ou non dans la définition de la Structure, l'option s'appelle : Préparer la structure pour une LinkedList()

Dans le code généré, il était certain que l'objet allait se retrouver dans une liste chainée. Et étant donnée que ces champs sont gérés par les commandes de la librairie LinkedList de PB. Il est mieux de ne pas y avoir accès afin d'éviter de détruire la liste chainée.

Je pense que le mieux serait de vous envoyer la version beta de mon éditeur pour que vous puissez voir de quoi il en retourne.

A+
Guimauve

Publié : dim. 01/mai/2005 12:56
par Cagou-77
Bonjour,

j'ai une question au niveau de la POO
peut -on utiliser une librairie crée en 1991 servant a créer des classes sous
Clipper bien sur en adaptant le code à PureBasic .
exemple de fichier Include pour créer les objets.

Code : Tout sélectionner

/*
        class(y).ch - v1.05

        Copyright (c) 1991 Anton van Straaten.
        All rights reserved.
*/

#define CLASSY_VER100


#xcommand   CLASS <className> [FROM <superClass>]   ;
                =>                                  ;
                CREATE CLASS <className> [FROM <superClass>]

#xcommand   CREATE CLASS <className> [FROM <superClass>]    ;
                =>                                          ;
                function <className>                        ;;
                static self                                 ;;
                local clsMkr                                ;;
                if self == NIL                              ;;
                clsMkr := ClassMaker():new(<"className">, [<superClass>()]) ;;
                method new constructor                     ;;
                hidden:

#command    INITIALIZE [CLASS] :    =>  self := clsMkr:makeClass; csyMethify(self)

#xcommand   END CLASS                           ;
                =>                              ;
                if self == nil                  ;;
                    self := clsMkr:makeClass    ;;
                else                            ;;
                    csyMethify()                ;;
                end; end                        ;;
                return self                     ;;
                #include "endclass.ch"

#xcommand   ENDCLASS    =>      END CLASS

#command    EXPORTED:   =>      ClassMaker():scope(1)
#command    VISIBLE:    =>      ClassMaker():scope(1)

#command    HIDDEN:     =>      ClassMaker():scope(2)
#command    LOCAL:      =>      HIDDEN:
#command    PRIVATE:    =>      HIDDEN:

#command    PROTECTED:  =>      ClassMaker():scope(4)

#command    VAR <(name1)> [, <(nameN)>] [<ro: READONLY, RO, NOASSIGN>]  ;
                =>                                                      ;
                clsMkr:variable({ <(name1)> [, <(nameN)>] }, .f., !<.ro.>)

#xcommand   CLASS VAR <(name1)> [, <(nameN)>] [<ro: READONLY, RO, NOASSIGN>] ;
                =>                                                           ;
                clsMkr:variable({ <(name1)> [, <(nameN)>] }, .t., !<.ro.>)

#command    INSTVAR <*details*>    =>  VAR <details>
#xcommand   CLASSVAR <*details*>   =>  CLASS VAR <details>

#command    MESSAGE <message1> [, <messageN>] [<ct: CONSTRUCTOR, CTOR>] ;
                =>                                                      ;
                clsMkr:method({ { <"message1">, { || <message1>() } }   ;
                             [, { <"messageN">, { || <messageN>() } }] }, <.ct.>, <.ct.>)

#command    MESSAGE <message> METHOD <method> [<ct: CONSTRUCTOR, CTOR>] ;
                =>                                                      ;
                clsMkr:method({{ <"message">, { || <method>() } }}, <.ct.>, <.ct.>)

#command    MESSAGE <message1> [, <messageN>] <def: DEFERRED, NULL>	;
                =>                                                      ;
                clsMkr:method({ { <"message1">, nil }                   ;
                             [, { <"messageN">, nil }] }, .f., .f.)

#xcommand   METHOD <method1> [, <methodN>] [<ct: CONSTRUCTOR, CTOR>]    ;
                =>                                                      ;
                MESSAGE <method1> [, <methodN>] <ct>

#xcommand   METHOD <msg1> = <mth1> [, <msgN> = <mthN>] [<ct: CONSTRUCTOR, CTOR>] ;
                =>                                                      ;
                MESSAGE <msg1> METHOD <mth1> <ct>                       ;
             [; MESSAGE <msgN> METHOD <mthN> <ct>]

#xcommand   METHOD <message> = <method> <ct: CONSTRUCTOR, CTOR>    ;
                =>                                                      ;
                MESSAGE <message> METHOD <method> <ct>

#xcommand   METHOD <method1> [, <methodN>] <def: DEFERRED, NULL>   ;
                =>                                                      ;
                MESSAGE <method1> [, <methodN>] <def>

#xcommand   CLASS MESSAGE <message1> [, <messageN>] ;
                =>                                  ;
                clsMkr:method({ { <"message1">, { || <message1>() } } ;
                             [, { <"messageN">, { || <messageN>() } }] }, .t., .f.)

#xcommand   CLASS MESSAGE <message> METHOD <method> ;
                =>                                  ;
                clsMkr:method({{ <"message">, { || <method>() } }}, .t., .f.)

#xcommand   CLASS MESSAGE <message1> [, <messageN>] <def: DEFERRED, NULL>   ;
                =>                                                          ;
                clsMkr:method({ { <"message1">, nil }                       ;
                             [, { <"messageN">, nil }] }, .t., .f.)

#command    CLASS METHOD <method1> [, <methodN>]   ;
                =>                                      ;
                CLASS MESSAGE <method1> [, <methodN>]

#command    CLASS METHOD <message> = <method>      ;
                =>                                      ;
                CLASS MESSAGE <message> METHOD <method>

#command    CLASS METHOD <method1> [, <methodN>] <def: DEFERRED, NULL> ;
                =>                                                          ;
                CLASS MESSAGE <method1> [, <methodN>] <def>

#command    _CYCTOR <name>([<params,...>])[()]              ;
                =>                                          ;
                __cyMethodType procedure <name> (<params>)

#command    _CYCTOR ([<params,...>])[()]                    ;
                =>                                          ;
                __cyMethodType procedure new (<params>)

#command    _CYSUPCTOR ([<params,...>])[()]                 ;
                =>                                          ;
                local __csyDummy := qself():super:new(<params>)

#command    _CYSUPCTOR <name>([<params,...>])[()]           ;
                =>                                          ;
                local __csyDummy := qself():super:<name>(<params>)

#command    CONSTRUCTOR <ctor> [, <superCtor> ]     ;
                =>                                  ;
                _CYCTOR <ctor>()                    ;;
                _CYSUPCTOR <superCtor>()            ;;
                local self := qself()

#command    INIT <ctor> [, <superCtor> ]     ;
                =>                                  ;
                _CYCTOR <ctor>()                    ;;
                _CYSUPCTOR <superCtor>()            ;;
                local self := qself()

#command    METHOD PROCEDURE <name>             ;
                =>                              ;
                __cyMethodType procedure <name> ;;
                local self := qself()

#command    METHOD FUNCTION <name>              ;
                =>                              ;
                __cyMethodType function <name>  ;;
                local self := qself()

#define __cyMethodType

#translate  ::  =>  self:

#translate  @:<methodName>([<param1>] [, <paramN>]) ;
                =>                                  ;
                <methodName>(_cyPshSelf(<param1>) [, <paramN>])

// eof class(y).ch
Si oui j'ai la librairie qu'il faut .

Merci pour vos réponses .

Publié : dim. 01/mai/2005 13:09
par Dräc
Guimauve,

Je pense que ce serait mieux que tu nous exposes dans un exemple comment toi tu travaillerais avec le code que tu proposes.

De nous passer le programme pour que l’on y voit mieux ni changera pas grand chose sans l’explication de comment utiliser le code généré.

Je pense qu’un exemple devrait te permettre de répondre à certaines questions que je t’ai posées dans ma précédente réponse.

Pour ce qui est d’implémenter les concepts POO, certains exemples existent sur le forum ou CodeArchive (sur PureArea).
Par contre, je suis d’accord avec toi, ces exemples n’exposent pas explicitement la théorie POO sous-jacente, ni ne présentent séparément tous les concepts.
Je peux faire un tuto dans ce sens…

Rassures-toi, je comprends aussi ta démarche. Dés que l’on veux appliquer les concepts POO en Pure, on est amené à gérer soit-même les structures d’un objet et cela peut vite être fastidieux, mais on l'accepte du moment qu’on garde en tête la raison de ce choix.
Cenpendant, il est tout naturel de se simplifier la tache en cherchant à créer des « Patrons » pour construire ses Objets.

Quelque part, l’aboutissement de ton projet pourrait etre le suivant :
Disposer d’un logiciel graphique permettant de construire des graphes selon la norme UML et capable de générer le code OO adapté en PureBasic.

Un tel outil existe déjà pour les langages C++, Delphi, Java…
En soit c’est fort intéressant, mais il est a penser que peu de gens s’en serviraient vraiment, car cela exige de conceptualiser son approche de la programmation et de la faire selon une norme.



PS :
Tu dis que ton exemple « Préparer la structure pour une LinkedList() » et que cette LinkedList() est au sens de la librairy standard PureBasic.
Je suis donc surpris de voir *Next/*Previous car ces pointeurs sont générés et gérés automatiquement par la librairie elle-même!

Publié : dim. 01/mai/2005 13:46
par Guimauve
Dis moi si le Deboggeur Affiche Guimauve quelque part :

Code : Tout sélectionner

Structure annuaire
   
   ; *Next.annuaire
   ; *previous.annuaire
   Nom2.s
   age2.b
   
EndStructure

Procedure.s GetannuaireNom(*p.annuaire)
   ProcedureReturn * p\Nom2
EndProcedure

Procedure.b Getannuaireage(*p.annuaire)
   ProcedureReturn * p\age2
EndProcedure

Procedure SetannuaireNom(*p.annuaire, Variable.s)
   
   *p\Nom2 = Variable
   
   ProcedureReturn * p
EndProcedure

Procedure Setannuaireage(*p.annuaire, Variable.b)
   
   *p\age2 = Variable
   
   ProcedureReturn * p
EndProcedure

Procedure Initannuaire()
   
   *p.annuaire = AllocateMemory(SizeOf(annuaire))
   
   ProcedureReturn * p
EndProcedure

Procedure Createannuaire(Nom.s, age.b)
   
   *p.annuaire = AllocateMemory(SizeOf(annuaire))
   
   *p\Nom2 = Nom
   *p\age2 = age
   
   ProcedureReturn * p
EndProcedure


Procedure Transferannuaire(*p.annuaire, *q.annuaire)

  *p = SetannuaireNom(*p, GetannuaireNom(*q))
  *p = Setannuaireage(*p,Getannuaireage(*q))
  
  FreeMemory(*q)

  ProcedureReturn *p
EndProcedure 

NewList agenda.annuaire()

*test.annuaire

*test = AddElement(agenda())

*test = Transferannuaire(*test, Createannuaire("Guimauve",26))

*test = AddElement(agenda())
*test = SetannuaireNom(*test, "Anna")
*test = Setannuaireage(*test, 21)

ResetList(agenda())

*test = NextElement(agenda())
; NextElement(agenda())
; *test=agenda() -8
Debug GetannuaireNom(*test)
Debug Getannuaireage(*test)

; *test=NextElement(agenda())
NextElement(agenda())
*test = agenda() - 8
Debug GetannuaireNom(*test)
Debug Getannuaireage(*test)
Moi ça ne marche pas si les champs *Next.annuaire ,*previous.annuaire sont en commentaire. Parce que la structure de donnée est différente. Donc si on les ajoutes, la Structure de données devient identique, et comme par hasard ça fonctionne. Le problème vient de la manière que la LinkedList fonctionne.

Pour un exemple, je vais en préparer un aujourd'hui et le poster ce soir. Ce sera un exemple de PBO.

A+
Guimauve

Publié : dim. 01/mai/2005 13:51
par Dräc
Cagou-77 a écrit :Bonjour,

j'ai une question au niveau de la POO
peut -on utiliser une librairie crée en 1991 servant a créer des classes sous
Clipper bien sur en adaptant le code à PureBasic .
En purebasic (comme en C d’ailleurs) on peut recréer les concepts OO comme la Classe d’un objet (ce qui est un minimum).
Par contre on ne bénéficiera pas de la notation.

Je ne vois pas comment une librairie pourrait apporter le jeu d’instructions nécessaires.
Car simplifier l’écriture d’un code OO en Pure passe par des instructions supplémentaires au niveau compilateur. Lorsqu’il les trouve, le compilateur les remplace par le code approprié.

Or, quand on utilise une librairie, on appèle des fonctions/procedures pas des instructions.
L’autre solution est celle que prend Guimauve : générer le code approprié avant compilation.

L’instruction Interface/EndInterface illustre ce propos : comment aurait on pu le crée sous forme de libraire ?
Personnellement, c’est grâce à elle que j’envisage la POO en PureBasic supportable (dans tous les sens du terme :lol: )

Publié : dim. 01/mai/2005 14:25
par Dräc
Dans ton exemple le soucis ne vient pas de la maniere dont LinkedList est fait mais plus de la maniere dont tu souhaites l’utiliser.
Effectivement tel quel, cela ne marcher pas et tu as besoin des deux pointeurs.

L’utilisation standard, si je puis dire, serait cela :

Code : Tout sélectionner

AddElement(agenda())
Transferannuaire(@agenda(), Createannuaire("Guimauve",26))
Mais c’est une question de gout. Donc ca ne s’explique pas et je suis d’accord pour dire que ta structure est correcte du point de vue du fonctionnement
Par contre, il est gênant, si tu cherches à faire de l’OO, d’avoir accès aux pointeurs *Next/*Previous en dehors de l’objet LinkedList() ;)
Tu es d’accord pour dire que normalement tu ne devrais pas te soucier de comment est implémenté la LinkedList, ce que respecte la notation que je te propose.

Si les gens ont la meme vision que toi, ils pourront se servir de ton code. Dans le cas contraire ils n’en feront probablement rien.
Je pense qu’il faut limiter les choses à leur strict essentiel au risque d’imposer.

Voici le code adapté :

Code : Tout sélectionner

Structure annuaire 
  
  ; *Next.annuaire 
  ; *previous.annuaire 
  Nom2.s 
  age2.b 
  
EndStructure 

Procedure.s GetannuaireNom(*p.annuaire) 
  ProcedureReturn * p\Nom2 
EndProcedure 

Procedure.b Getannuaireage(*p.annuaire) 
  ProcedureReturn * p\age2 
EndProcedure 

Procedure SetannuaireNom(*p.annuaire, Variable.s) 
  
  *p\Nom2 = Variable 
  
  ProcedureReturn * p 
EndProcedure 

Procedure Setannuaireage(*p.annuaire, Variable.b) 
  
  *p\age2 = Variable 
  
  ProcedureReturn * p 
EndProcedure 

Procedure Initannuaire() 
  
  *p.annuaire = AllocateMemory(SizeOf(annuaire)) 
  
  ProcedureReturn * p 
EndProcedure 

Procedure Createannuaire(Nom.s, age.b) 
  
  *p.annuaire = AllocateMemory(SizeOf(annuaire)) 
  
  *p\Nom2 = Nom 
  *p\age2 = age 
  
  ProcedureReturn *p 
EndProcedure 


Procedure Transferannuaire(*p.annuaire, *q.annuaire) 
  
  *p = SetannuaireNom(*p, GetannuaireNom(*q)) 
  *p = Setannuaireage(*p,Getannuaireage(*q)) 
  
  FreeMemory(*q) 
  
  ProcedureReturn *p 
EndProcedure 

NewList agenda.annuaire() 

AddElement(agenda())

Transferannuaire(@agenda(), Createannuaire("Guimauve",26)) 

AddElement(agenda())
SetannuaireNom(@agenda(), "Anna") 
Setannuaireage(@agenda(), 21) 

ResetList(agenda()) 

NextElement(agenda())
; NextElement(agenda()) 
; *test=agenda() -8 
Debug GetannuaireNom(@agenda()) 
Debug Getannuaireage(@agenda()) 

; *test=NextElement(agenda()) 
NextElement(agenda()) 
Debug GetannuaireNom(@agenda()) 
Debug Getannuaireage(@agenda())
N’est-il pas plus lisible ?
En fait *test n’etait pas necessaire…

Ps: beaucoup d'affectations dans ton code. Tu peux simplifier Transferannuaire() par exemple:

Code : Tout sélectionner

Procedure Transferannuaire(*p.annuaire, *q.annuaire) 
  
  SetannuaireNom(*p, GetannuaireNom(*q)) 
  Setannuaireage(*p,Getannuaireage(*q)) 
  
  FreeMemory(*q) 
  
  ProcedureReturn *p 
EndProcedure
A l'extreme supprimer "ProcedureReturn *p"

Publié : dim. 01/mai/2005 16:58
par Guimauve
Bon très bien j'abandonne !

A+
Guimauve

Publié : dim. 01/mai/2005 17:30
par Backup
ben c'est domage !!

tu demande l'avis d'un expert !
t'en a un qui te répond , et toi t'abandonne ?? 8O

pas tout compris la !! :lol:

Publié : lun. 02/mai/2005 2:03
par Guimauve
Chose promise, chose dû, un exemple de programmation basé objet.

Créer un répertoire et sauvegarder ce code avec le nom : Exemple PBO.pb

Code : Tout sélectionner

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Exemple de Programmation Basé Objet -- Source principal
; Version 1.0.0
; Programmation = À compléter
; Programmé par : Guimauve
; Date : 1er mai 2005
; Mise à jour : 1er mai 2005
; Codé avec PureBasic V3.93
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

IncludeFile "Constantes.pb"
IncludeFile "ObjetINI.pb"
IncludeFile "Procédures.pb"

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Création d'un objet de paramètres par défaut pour initialiser le 
; On fait une vérification de routine au départ :
; Fichier INI, Répertoire de ressources, etc.
; Et on retourne un pointeur de la zone des informations INI à utiliser

*INIUtilisateur = VerificationDepart(CreateINI_Param("Exemple PBO.ini", 400, 300, 1))

; On extrait les informations pour les utiliser

Largeur = GetINI_ParamLargeurFenetre(*INIUtilisateur)
Hauteur = GetINI_ParamHauteurFenetre(*INIUtilisateur)
ToujoursVisible = GetINI_ParamToujoursVisible(*INIUtilisateur)

; On ouvre la fenètre

If OpenWindow(#Main_Win, 0, 0, Largeur, Hauteur, #Style, "Exemple PBO") <> 0
  
  ; On créer la liste de gadget
  
  If CreateGadgetList(WindowID(#Main_Win)) <> 0
    
    TextGadget(#Text_LargeurFenetre, 5, 5, 100, 20, "Largeur fenètre")
    TextGadget(#Text_HauteurFenetre, 5, 30, 100, 20, "Hauteur fenètre")
    StringGadget(#String_LargeurFenetre, 110, 5, 100, 20, Str(Largeur))
    StringGadget(#String_HauteurFenetre, 110, 30, 100, 20, Str(Hauteur))
    
    ButtonGadget(#Btn_Quitter, Largeur - 103, Hauteur - 28, 100, 25, "Quitter")
    
  EndIf
  
EndIf

; La gestion des évènements

Repeat
  
  EventID = WaitWindowEvent()
  
  Select EventID
    
    Case #PB_EventGadget
      
      Select EventGadgetID()
        
        Case #Btn_Quitter
          ; On passe les paramètres ini pour mettre à jour le fichier INI
          VerificationSortie(*INIUtilisateur)
          EventID = #PB_EventCloseWindow
          
      EndSelect
      
    Case #PB_EventMenu
      
      Select EventMenuID()
        
        
        
      EndSelect
      
  EndSelect
  
Until EventID = #PB_EventCloseWindow

End
Celui ci sous le nom : Constantes.pb

Code : Tout sélectionner

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Exemple de Programmation Basé Objet -- Constantes, Variables
; Version 1.0.0
; Programmation = À compléter
; Programmé par : Guimauve
; Date : 1er mai 2005
; Mise à jour : 1er mai 2005
; Codé avec PureBasic V3.93
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Enumeration
  
  
  #Main_Win
  
  #Text_LargeurFenetre
  #Text_HauteurFenetre
  #String_LargeurFenetre
  #String_HauteurFenetre
  
  #Btn_Quitter
  
  
EndEnumeration

#Style = #PB_Window_ScreenCentered | #PB_Window_SystemMenu
Celui ci sous le nom : Objet INI

Code : Tout sélectionner

Structure INI_Param

    NomFichier.s
    LargeurFenetre.w
    HauteurFenetre.w
    ToujoursVisible.b

EndStructure

Procedures GetINI_ParamNomFichier(*p.INI_Param)
    ProcedureReturn *p\NomFichier
EndProcedure

Procedurew GetINI_ParamLargeurFenetre(*p.INI_Param)
    ProcedureReturn *p\LargeurFenetre
EndProcedure

Procedurew GetINI_ParamHauteurFenetre(*p.INI_Param)
    ProcedureReturn *p\HauteurFenetre
EndProcedure

Procedureb GetINI_ParamToujoursVisible(*p.INI_Param)
    ProcedureReturn *p\ToujoursVisible
EndProcedure

Procedure SetINI_ParamNomFichier(*p.INI_Param, NomFichier.s)

    *p\NomFichier = NomFichier

    ProcedureReturn *p
EndProcedure

Procedure SetINI_ParamLargeurFenetre(*p.INI_Param, LargeurFenetre.w)

    *p\LargeurFenetre = LargeurFenetre

    ProcedureReturn *p
EndProcedure

Procedure SetINI_ParamHauteurFenetre(*p.INI_Param, HauteurFenetre.w)

    *p\HauteurFenetre = HauteurFenetre

    ProcedureReturn *p
EndProcedure

Procedure SetINI_ParamToujoursVisible(*p.INI_Param, ToujoursVisible.b)

    *p\ToujoursVisible = ToujoursVisible

    ProcedureReturn *p
EndProcedure

Procedure UpdateINI_Param(*p.INI_Param, NomFichier.s, LargeurFenetre.w, HauteurFenetre.w, ToujoursVisible.b)

    *p = SetINI_ParamNomFichier(*p, NomFichier)
    *p = SetINI_ParamLargeurFenetre(*p, LargeurFenetre)
    *p = SetINI_ParamHauteurFenetre(*p, HauteurFenetre)
    *p = SetINI_ParamToujoursVisible(*p, ToujoursVisible)

    ProcedureReturn *p
EndProcedure

Procedure TransferINI_Param(*p.INI_Param, *q.INI_Param)

    *p = SetINI_ParamNomFichier(*p, GetINI_ParamNomFichier(*q))
    *p = SetINI_ParamLargeurFenetre(*p, GetINI_ParamLargeurFenetre(*q))
    *p = SetINI_ParamHauteurFenetre(*p, GetINI_ParamHauteurFenetre(*q))
    *p = SetINI_ParamToujoursVisible(*p, GetINI_ParamToujoursVisible(*q))

    FreeMemory(*q)

    ProcedureReturn *p
EndProcedure

Procedure InitINI_Param()

    *p.INI_Param = AllocateMemory(SizeOf(INI_Param))

    ProcedureReturn *p
EndProcedure

Procedure CreateINI_Param(NomFichier.s, LargeurFenetre.w, HauteurFenetre.w, ToujoursVisible.b)

    *p.INI_Param = AllocateMemory(SizeOf(INI_Param))

    *p = SetINI_ParamNomFichier(*p, NomFichier)
    *p = SetINI_ParamLargeurFenetre(*p, LargeurFenetre)
    *p = SetINI_ParamHauteurFenetre(*p, HauteurFenetre)
    *p = SetINI_ParamToujoursVisible(*p, ToujoursVisible)

    ProcedureReturn *p
EndProcedure

Procedure FreeINI_Param(*q.INI_Param)
  FreeMemory(*q)
EndProcedure 
Et finalement celui ci sous le nom : Procédures.pb

Code : Tout sélectionner

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Exemple de Programmation Basé Objet -- Procédures
; Version 1.0.0
; Programmation = À compléter
; Programmé par : Guimauve
; Date : 1er mai 2005
; Mise à jour : 1er mai 2005
; Codé avec PureBasic V3.93
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Procedure CreerFichierINI(*Alpha.INI_Param)
  
  ; Création du fichier INI
  CreatePreferences(GetINI_ParamNomFichier(*Alpha))
  
  ; Écriture des informations
  PreferenceComment("Les dimensions de la fenètre")
  WritePreferenceLong("Largeur Fenètre", GetINI_ParamLargeurFenetre(*Alpha))
  WritePreferenceLong("Hauteur Fenètre", GetINI_ParamHauteurFenetre(*Alpha))
  PreferenceComment("Toujous Visible = 0 : La fenètre n'est toujours au dessus des autres")
  PreferenceComment("Toujous Visible = 1 : La fenètre est toujours au dessus des autres")
  WritePreferenceLong("Toujours Visible", GetINI_ParamToujoursVisible(*Alpha))
  
  ; On ferme le fichier INI
  ClosePreferences()
  
EndProcedure

Procedure OuvrirFichierINI(*Alpha.INI_Param)
  
  Nomfichier$ = GetINI_ParamNomFichier(*Alpha)
  
  *User = InitINI_Param()
  
  ; *User est vide on lui ajoute le Nomfichier
  *User = SetINI_ParamNomFichier(*User, Nomfichier$)
  
  ; On lit les valeurs depuis le fichier iNI et on écrit les valeurs dans *User
  OpenPreferences(Nomfichier$)
  
  *User = SetINI_ParamLargeurFenetre(*User, ReadPreferenceLong("Largeur Fenètre", GetINI_ParamLargeurFenetre(*Alpha)))
  *User = SetINI_ParamHauteurFenetre(*User, ReadPreferenceLong("Hauteur Fenètre", GetINI_ParamHauteurFenetre(*Alpha)))
  *User = SetINI_ParamToujoursVisible(*User, ReadPreferenceLong("Toujours Visible", GetINI_ParamToujoursVisible(*Alpha)))
  
  ; On ferme le fichier INI
  ClosePreferences()
  
  ProcedureReturn *User
EndProcedure 


Procedure VerificationDepart(*Alpha.INI_Param)
  
  Nomfichier$ = GetINI_ParamNomFichier(*Alpha)

  If FileSize(Nomfichier$) = -1
    
    ; Le fichier n'existe pas, on creer celui par défault
    CreerFichierINI(*Alpha)
    
    ; La méthode TransferINI_Param va effectuer un transfer de *Alpha
    ; vers une zone mémoire puis va retourner un pointeur vers la zone
    ; mémoire des informations. Ce transfer évite de redémarrer le programme
     
    *Gamma = TransferINI_Param(InitINI_Param(), *Alpha)
    
  Else
    
    ; Le fichier existe, on prend les informations depuis le fichier
    ; *Alpha est nécessaire à l'ouverture du fichier INI dans l'éventualité
    ; que ou le mot clef ou la valeur soit absente dans le fichier INI
    *Gamma = OuvrirFichierINI(*Alpha)
    
    ; *Alpha est maintenant inutile, on le détruit
    FreeINI_Param(*Alpha)
    
  EndIf
  
  ProcedureReturn *Gamma
  
EndProcedure

Procedure VerificationSortie(*Alpha.INI_Param)
  
  ; On Recreer le fichier INI avec les paramètres de l'utilisateur 
  ; pour le prochain démarrage du programme.
  
  Nomfichier$ = GetINI_ParamNomFichier(*Alpha)
  Largeur.w = Val(GetGadgetText(#String_LargeurFenetre))
  Hauteur.w =  Val(GetGadgetText(#String_HauteurFenetre))
  ToujoursVisible.b = 1 
  
  CreerFichierINI(UpdateINI_Param(*Alpha, Nomfichier$, Largeur, Hauteur, ToujoursVisible))
  
EndProcedure 
Ici l'objet contient les paramètres INI pour le programme. L'exemple n'est pas très bon parce que les paramètres ini sont très spécifique à un seul programme.

Le concept serait le même pour les informations au sujet d'un chasseur dans un jeu par exemple. Où à la fois l'objet est utilisé par l'editeur de vaisseau et bien entendu le jeu. En incluant le même fichier dans le 2 source on est certain que la mise à jour se fait dans les 2 programmes. Et c'est le but visé surtout s'il y a beaucoup de modification à la Structure de données.

Exemple, au départ une variable de type byte semblait suffisante mais on éprouve un problème de débordement mémoire. En modifiant la Strucutre et les méthodes on corrige partout dans les 2 programmes en même temps. Si le même objet se retrouve dans 3 programmes, les corrections sont effectives dans les 3 programmes et sa continue autant de fois que l'objet est utilisé. Et c'est encore plus important si les Structures sont imbriquées les une dans les autres.

Guimauve

Publié : lun. 02/mai/2005 19:47
par Guimauve
Mise à jour du code précédent :

Code : Tout sélectionner

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Exemple de Programmation Basé Objet -- Objet INIParam Et Méthodes
; Version 2.0.0
; Programmation = À compléter
; Programmé par : Guimauve
; Date : 1er mai 2005
; Mise à jour : 2 mai 2005
; Codé avec PureBasic V3.93
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Structure INI_Param
  
  NomFichier_string.s
  LargeurFenetre_word.w
  HauteurFenetre_word.w
  ToujoursVisible_byte.b
  
EndStructure

Procedure.s GetINI_ParamNomFichier(*p.INI_Param)
  ProcedureReturn *p\NomFichier_string
EndProcedure

Procedure.w GetINI_ParamLargeurFenetre(*p.INI_Param)
  ProcedureReturn *p\LargeurFenetre_word
EndProcedure

Procedure.w GetINI_ParamHauteurFenetre(*p.INI_Param)
  ProcedureReturn *p\HauteurFenetre_word
EndProcedure

Procedure.b GetINI_ParamToujoursVisible(*p.INI_Param)
  ProcedureReturn *p\ToujoursVisible_byte
EndProcedure

Procedure SetINI_ParamNomFichier(*p.INI_Param, NomFichier.s)
  
  *p\NomFichier_string = NomFichier
  
  ProcedureReturn *p
EndProcedure

Procedure SetINI_ParamLargeurFenetre(*p.INI_Param, LargeurFenetre.w)
  
  *p\LargeurFenetre_word = LargeurFenetre
  
  ProcedureReturn *p
EndProcedure

Procedure SetINI_ParamHauteurFenetre(*p.INI_Param, HauteurFenetre.w)
  
  *p\HauteurFenetre_word = HauteurFenetre
  
  ProcedureReturn *p
EndProcedure

Procedure SetINI_ParamToujoursVisible(*p.INI_Param, ToujoursVisible.b)
  
  *p\ToujoursVisible_byte = ToujoursVisible
  
  ProcedureReturn *p
EndProcedure

Procedure UpdateINI_Param(*p.INI_Param, NomFichier.s, LargeurFenetre.w, HauteurFenetre.w, ToujoursVisible.b)
  
  SetINI_ParamNomFichier(*p, NomFichier)
  SetINI_ParamLargeurFenetre(*p, LargeurFenetre)
  SetINI_ParamHauteurFenetre(*p, HauteurFenetre)
  SetINI_ParamToujoursVisible(*p, ToujoursVisible)
  
  ProcedureReturn *p
EndProcedure

Procedure TransferINI_Param(*p.INI_Param, *q.INI_Param)
  
  SetINI_ParamNomFichier(*p, GetINI_ParamNomFichier(*q))
  SetINI_ParamLargeurFenetre(*p, GetINI_ParamLargeurFenetre(*q))
  SetINI_ParamHauteurFenetre(*p, GetINI_ParamHauteurFenetre(*q))
  SetINI_ParamToujoursVisible(*p, GetINI_ParamToujoursVisible(*q))
  
  FreeMemory(*q)
  
  ProcedureReturn *p
EndProcedure

Procedure InitINI_Param()
  
  *p.INI_Param = AllocateMemory(SizeOf(INI_Param))
  
  ProcedureReturn *p
EndProcedure

Procedure CreateINI_Param(NomFichier.s, LargeurFenetre.w, HauteurFenetre.w, ToujoursVisible.b)
  
  *p.INI_Param = AllocateMemory(SizeOf(INI_Param))
  
  SetINI_ParamNomFichier(*p, NomFichier)
  SetINI_ParamLargeurFenetre(*p, LargeurFenetre)
  SetINI_ParamHauteurFenetre(*p, HauteurFenetre)
  SetINI_ParamToujoursVisible(*p, ToujoursVisible)
  
  ProcedureReturn *p
EndProcedure

Procedure FreeINI_Param(*p.INI_Param)
  
  FreeMemory(*p)
  
EndProcedure
Vous remarquerez que j'ai modifié le noms des champs dans la structure et sans aucune autre modification au code du programme principale, ça fonctionne toujours.

A+
Guimauve