Page 1 sur 1

Conception Orienté Objet : Avantages ou inconvénients ?

Publié : dim. 17/avr./2005 1:44
par Dräc
J’aimerai lancer ici une réflexion sur les avantages et les inconvénients qu’apporterait un PureBasic proposant une conception Orienté Objet.

Le débat a été initié il y a peu sur le forum anglais ( voir ici, vous pouvez d’ailleurs participer à un vote).
Pourtant, personnellement mon opinion n’est pas faite, certainement par manque de pratique en OO.

Cependant pour l’avoir touché des doigts, l’OO me paraît satisfaisante du point de vue de l’esprit pour construire son code.

Puisque l’un des points communs des utilisateurs de Pure est disposer d’un langage le plus performant pour écrire rapidement un code, quel part l’OO peut apporter à PureBasic selon vous?

Publié : dim. 17/avr./2005 3:11
par Guimauve
L'Orienté Objet à l'avantage de pouvoir modifier facilement l'organisation
des données sans modifier tout les programmes qui utilisent les même objet. Ça
permet de mettre à jour plus facilement le fonctionnement d'un programme.

Prenons le développement des Gadget dans PureBasic par exemple.

Est-ce qu'il est mieux que Fred donne directement la Structure qui contient toute
les informations sur les gadgets et qu'on fasse tout le travaille pour tout initialiser
correctement pour que ça fonctionne ?

Ou est-ce qu'il est mieux d'utiliser les commandes que Fred à fait pour creer des
gadget ou modifier le contenu des gadgets ?

Imaginer tout le travaille à faire si Fred doit modifier la Structure pour la création
des Gadget. (Remplacer des champs, en ajouter, en enlever, etc)
Ça voudrait dire ouvrir les 2 000 000 000 de code sources programmes pour faire
toute les mises à jour qui s'impose. :mad:

Tandis que si on utilise les commandes pour manipuler les gadgets et que Fred à
bien fait tout les mises à jour sur ces commandes alors les 2 000 000 000 de codes
sources vont encore compiler à quelques exceptions près.

C'est ça le but de la représentation caché et c'est pour cette raison que la POO
est apparue.

Alors oui, c'est beaucoup plus long à écrire le code en POO au départ, mais c'est
combien de fois plus rapide pour mettre à jour les codes.

En programmation, on écrit le code 1 fois et on le met à jour 10 000 fois.

Dans mon cas, ça fait un peu plus d'un an et demi que je travaille avec PB et je
fais encore aujourd'hui des mises à jour sur mes premiers programmes.

Parcontre la POO n'est vraiment nécessaire si le programme est tout petit. Un jeu
en 3D, en incluant le moteur 3D, l'intelligence artificielle, le moteur de jeu, etc
mérite d'être en OO. Ce sera plus facile de faire évoluer le développement du jeu,
de faire des amélioration et des mises à jour.

C'est mon point de vue sur la question.

A+
Guimauve

Publié : jeu. 21/avr./2005 14:51
par KarLKoX
J'ai convertis un moteur de lecture de fichiers mod (protracker) du Java en PureBasic tout en essayant de garder tout le côté orienté objet : cela montre que l'on peut "simuler" de l'OO.
L'avoir de manière native dans PureBasic ? Cela va sans dire : non.
Pourquoi ? Tout simplement parce qu'on s'éloignerais trop de l'esprit des langages basic.
Je suis pourtant tres orienté OO depuis que je m'y suis mis un peu plus sérieusement mais il faut savoir définir des limites quand à la conception et à l'avenir d'un langage : je ne pense pas qu'il soit saint de trop s'éloigner des objectifs que l'on s'est fixé, en tout cas, tant que tous ses objectifs ne sont pas atteints.
Par contre, proposer, plus tard, une version permettant de programmer en OO (via une lib par exemple) serait interessant.
Just my 2 cents.

Publié : jeu. 05/mai/2005 15:50
par Dräc
Merci déjà à Guimauve et KarLKoX pour votre réaction.

Après une recherche approfondit de ma part (voir notamment mon tuto sur le POO en PB), voici mon premier avis sur la question :
Le gros avantage de la POO se place sur l’obligation de conceptualiser son code. C’est à dire que l’on va pouvoir architecturer son code afin de faire des regroupements par concept de telle sorte que les redondances de codes soient limitées au possible.
Il en découle :
- Une meilleure vision du code (pour la lisibilité c'est différent :wink: )
- Une meilleure maintenance (c’est l’un des points forts apprécié, notamment par l’industrie)
- Un travail en groupe facilité
etc…

Par contre, on devrait perdre en performance puisque les appels de fonctions (ici des méthodes) sont véritablement l’articulation du fonctionnement du programme.

D’autre part, le fait meme d’etre obligé à bien réfléchir à son code, peut prendre du temps et je comprends mieux qu’il soit plus pratique de faire du procédural sur des petits projets.

Cependant, réfléchir à son code, on y est tous obligé tout ou tard. Cette obligation est plus pressante en POO voila tout.
Personnellement, je pense qu’au fil de temps, le programmeur toujours plus expérimenté et amené assez naturellement à intégrer des concepts OO dans sa programmation, fusse sans s’en apercevoir ;)

Publié : jeu. 05/mai/2005 16:07
par Cagou-77
Tout à Fait d'accord avec Toi
Merci

Publié : mar. 25/sept./2007 17:48
par Ollivier
Je reviens sur le sujet parce que je n'y connais que trop peu à l'OO. Or, je viens de voir un petit exemple simple et concret que je vous poste ici.

Pour certains, ça ne leur apprendra rien, mais pour moi, tout ce qui touche à la souplesse d'un programme, je trouve ça intéressant.

Mettre en accord données et code en évitant les pièges du plantage, etc...

Code : Tout sélectionner

 ;Created by <David.C#S4701L> 2007 
  ;If you wish to redistribute please ask first! :) 
  ;Official Topic: http://www.purebasic.fr/english/viewtopic.php?t=28818 
  
  Global oMax = 5 ;Your maximum amount of objects 
  Global Dim Object(oMax) 
  
  Enumeration 
    #Create 
    #Step 
    #Destroy 
  EndEnumeration 
  
  Procedure Test(InstanceId.l,Type.l=0) 
    Select Type 
      Case #Create       ;Run straight after the object is made 
        MessageRequester("Hi","Hello there.") 
      Case #Step          ;Run every "Step" 
         Debug "Object: Test - made event Step." 
      Case #Destroy      ;Run when we want to remove the object 
         MessageRequester("MAYDAY!","I'm going down! I'm going down!!") 
    EndSelect 
  EndProcedure 
  
  Procedure EventInstance() 
    Repeat 
      For i=0 To oMax 
        If Object(i) <> 0 
          CallFunctionFast(Object(i),i,#Step) 
        EndIf 
      Next 
      Delay(16) 
    ForEver 
  EndProcedure 
  
  Procedure CreateInstance(CodeAddress.l) 
    For i=0 To oMax 
      If Object(i)=0 
        Object(i)=CodeAddress.l 
        CallFunctionFast(Object(i),i,#Create) 
        ProcedureReturn i 
      EndIf 
    Next 
    ProcedureReturn -1 
  EndProcedure 
  
  Procedure DestroyInstance(InstanceId) 
    For i=0 To oMax 
      If Object(i) = InstanceId 
        CallFunctionFast(Object(i),#Destroy) 
        Object(i) = 0 
        ProcedureReturn 1 
      EndIf 
    Next 
    ProcedureReturn 
  EndProcedure 
  
  Object1 = CreateInstance(@Test()) 
  ObjectThreadID = CreateThread(@EventInstance(),"") 

  Repeat 
     Delay(16) 
  ForEver 

Publié : mar. 25/sept./2007 18:15
par Patrick88
à l'époque, j'aimais programmer en pascal (tp55 puis tp7) quand ils sont passé à windows / delphi, j'ai suivi le mouvement...
mais la programmation par objets , j'ai jamais bien compris à quoi cela servait... surtout que purebasic fait aussi bien sans en utiliser...

pat

Publié : mar. 25/sept./2007 18:35
par Ollivier
Je pense que c'est parce qu'on manque d'exemples concrets sur les aspects bénéfiques de l'OO.

C'est pas évident de débarquer avec un gros projet pour exemple, dire «ben voilà, vous voyez ce gros code de bourbon, je souhaite ajouter telle fonctionnalité, voici comment je m'y prends. Voilà, c'est fait ! Maintenant je reprends ma version initiale et je reviens 6 mois plus tard, le temps de convertir le projet en procédural et de vous montrer après ces 6 mois de galère, comment je vais en chier pour ajouter ma nouvelle fonctionnalité en procédural !»

Publié : mar. 25/sept./2007 19:15
par wolfjeremy
Ollivier a écrit :«...vous montrer après ces 6 mois de galère, comment je vais en chier pour ajouter ma nouvelle fonctionnalité en procédural !»
D'accord avec toi, le procédural c'est pas du tout évolutif.
Après quelques mois, je n'esseye même plus de retoucher mon code, surtout que j'ai la facheuse tendance à presque pas commenté tout ça...
C'est pour ça que je trouve la POO interessante, d'ailleur ça fait longtemp que je me suis dit que je mis esseyerais sur PB.

Publié : mar. 25/sept./2007 21:22
par Dr. Dri
En procédural pour être évolutif il faut une programmation orientée composant. Après on peut faire évoluer les composants comme on le souhaite, mais il faut avoir à la base conçu son appli pour être évolutive sinon effectivement on bloque. L'objet et le procédural ne sont rien sans une architecture solide... Je préfère de loin un projet procédural bien conçu que le même objet et désordonné. La conception orientée objet a l'avantage sur procédural d'être plus facilement structurable mais pas forcément plus.

Dri

Publié : mer. 26/sept./2007 20:03
par Ollivier
Saluw!

Bon, voici un code inspiré du précédent. Pour rester compatible avec les DLLs, il est au norme ISO 9000 Guimauve 2.

Code : Tout sélectionner

;{ Directives }

EnableExplicit

;}
;{ Constantes }
Enumeration
      
      #CREATE
      #EXTEND
      #MANAGE
      #REDUCE
      #RESET

EndEnumeration

;}
;{ Mémoire }

Structure DWORD

      DW.L[16384]
      
EndStructure

;}
;{ Objets }
Structure OBJDESC

    Adress.L

EndStructure

Structure HOBJ
  
      pList.L  ; Pointe vers la liste des adresses des objets
      Quant.L  ; Quantité d'objets
      Limit.L  ; Limite du nombre d'objets avant réallocation de la table
      pPipe.L  ; Pointe vers le buffer E/S de l'objet (taille = SizeOf(OBJECTMANAGING) )
         ID.L  ; Index de l'objet en cours d'exécution
        
EndStructure

Structure OBJECTMANAGING

    Action.L   ; Doit toujours rester le 1er membre
    Adress.L   ; Doit toujours rester le 2nd membre
    
EndStructure
;{ Déclaration des objets }
Declare TestA(*hObj.HOBJ)
Declare TestB(*hObj.HOBJ)
;}

Procedure Objects(Action.L, *hObj.HOBJ)

      With *hObj
            Select Action.L
      
                  Case #CREATE
                        \pList     = AllocateMemory(1024)
                        ; SECURITY ^^
                        \Quant      = 0
                        \Limit    = 256
                        \pPipe    = AllocateMemory(SizeOf(OBJECTMANAGING) )
            
                  Case #EXTEND
                        \Limit << 1
                        \pList = ReAllocateMemory(\pList, \Limit << 2)
                        ; SECURITY ^^
                  
                  Case #REDUCE
                        ; SECURITY
                        \Limit >> 1
                        \pList = ReAllocateMemory(\pList, \Limit << 2)
                        
                  Case #DELETE
                        FreeMemory(\pPipe)
                        FreeMemory(\pList)
                        FreeMemory(*hObj)
      
            EndSelect
      EndWith

EndProcedure
;}

;{ Objet }
Procedure Obj(*hObj.HOBJ)

      Protected *Obj.OBJECTMANAGING
      Protected *M.DWORD
      Protected ID.L
      Protected Base.L
      
      With *hObj
      
            *Obj = \pPipe
            *M   = \pList
      
            Select *Obj\Action
            
                  Case #CREATE
                        *M\DW[\Quant] = *Obj\Adress
                        CallFunctionFast(*Obj\Adress, *hObj)
                        \Quant + 1
                        If \Quant = \Limit: Objects(#EXTEND, *hObj): EndIf
                  
                  Case #MANAGE                       
                        \ID = 0
                        Repeat
                              CallFunctionFast(*M\DW[\ID], *hObj)
                              \ID + 1
                        Until \ID => \Quant
                        
                  Case #DELETE, #RESET
                        For ID = 0 To \Quant - 1                              
                              If *M\DW[ID] = *Obj\Adress
                                    CallFunctionFast(*Obj\Adress, *hObj)
                                    Base = @*M\DW[ID]
                                    MoveMemory(Base + SizeOf(OBJDESC), Base, ( (\Quant - ID) - 1) * SizeOf(OBJDESC) )
                                    \Quant - 1
                                    \ID - 1
                              EndIf
                        Next
                        If \Quant << 2 <= \Limit: Objects(#REDUCE, *hObj): EndIf
                        If *Obj\Action = #DELETE: *Obj\Action = #MANAGE: EndIf
            EndSelect
            
      EndWith
      
EndProcedure
;}

Procedure ObjectsStart()
      Protected *hObj.HOBJ = AllocateMemory(SizeOf(HOBJ) )
      ; SECURITY ^^
      
      Objects(#CREATE, *hObj)
      
            Protected *Obj.OBJECTMANAGING = *hObj\pPipe
            
            *Obj\Action = #CREATE
            *Obj\Adress = @TestA(): Obj(*hObj)
            *Obj\Adress = @TestB(): Obj(*hObj)
            
            Repeat
                  *Obj\Action = #MANAGE
                  Obj(*hObj)
            Until *Obj\Action = #RESET            
            
            *Obj\Action = #DELETE
            *Obj\Adress = @TestA(): Obj(*hObj)
            *Obj\Action = #DELETE
            *Obj\Adress = @TestB(): Obj(*hObj)
            
      Objects(#DELETE, *hObj)
EndProcedure

      ObjectsStart()
      
      ; Si on arrive ici, c'est qu'il y a eu une action RESET
      ; Dans ce cas, toutes les zones mémoire utilisées sont libérées
      ; On peut écrire un programme habituel

;____________________________________________________________________________ 
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 
;  Exemple avec 2 objets TestA() et TestB()
;____________________________________________________________________________ 
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 
Procedure TestA(*hObj.HOBJ)

      Protected *Obj.OBJECTMANAGING = *hObj\pPipe
      
      Select *Obj\Action
          
            Case #CREATE
            
                  Debug "Bonjour"
                
            Case #MANAGE
            
                  Debug "Coucou"
                                  
            Case #DELETE
            
                  Debug "Au revoir"
          
      EndSelect
        
EndProcedure


Procedure TestB(*hObj.HOBJ)

      Protected *Obj.OBJECTMANAGING = *hObj\pPipe
      
      Select *Obj\Action
          
            Case #CREATE
            
                  Debug "Bonjour2"
                
            Case #MANAGE
            
                  Debug "Coucou2"

                  *Obj\Action = #DELETE   ; Ces 3 lignes tuent la procédure voisine dès le départ!
                  *Obj\Adress = @TestA()  ; Commentez-les pour éviter ce drame
                  Obj(*hObj)              ; Ou bien changez @TestA() en @TestB() pour obtenir un «suicide»
                
;                  *Obj\Action = #RESET   ; En décommentant cette ligne, tout le programme objet est stoppé
                                          ; Chaque objet est détruit
                  
            Case #DELETE
            
                  Debug "Au revoir2"
          
      EndSelect
        
EndProcedure