Methode et beauté du code
Methode et beauté du code
lorsque je code , j'utilise quasiment tout le temps ce type d'architecture :
***************
Structures
initialisation des variables
Declaration des Procedures
*****************
Creation de l'interface utilisateur (hors procedure )
************************
Boucle principale (Events )
***********************
Zone des procedures
************************
DataSection
************************
-----------------------------------------------------------------------------------------------------------
les procedures toujours en fin de code !
cela evite d'avoir a parcourir 3 plombe un code pour arriver a la boucle principale ....
je considere les procedures comme des "accessoire" au programme ... donc il vont a la fin
l'appel se faisant la plupart du temp dans la boucle principale
pour ce qui concerne l'ecriture des variables :
pour les flags, j'utilise toujours le mot "flag_" en debut de nom d'un Flag
je Type en permanence toutes mes variables , comme ça si au milieu d'un code, je vois toto.l , je connais son type
et ceux meme si Purebasic permet de typer une seule fois en debut de code une variable, je garde le type affiché
tout au long du code
j'ajoute qu'il m'arrive d'utiliser des variables "Poubelle" , des variables qui ne servent que temporairement et tres localement
dans un code , ces variables, je leur donne un nom qui ne veux rien dire genre "qdfqf.s" ... lorsque je vois ce type de variable , je sais qu'elle me sert que dans les 10 prochaines lignes maximum ...
on peut aussi (mais je ne le fait pas ) ajouter une lettre devant le nom de la variable pour connaitre son type
genre L_toto.s (le "L" signifiant qu'elle est Local )
ou bien G_toto.s (le "G" signifiant qu'elle est Global ) etc ...
je n'utilise quasiment jamais les Includes ... (l'action de séparer un gros programme en plusieurs fichiers)
car .. je me suis rendu compte qu'au moment de debugger un prg fait ainsi , c'etait parfois tres difficile de savoir
ou se trouve un Bug ! ....
l'erreur apparait dans un fichier ... alors qu'en fait elle est généré par un autre fichier ...
comme dirai l'autre "Cherchez l'erreur"
alors qu'en ayant tout le code dans le meme Editeur ... c’est limpide ...
***************
Structures
initialisation des variables
Declaration des Procedures
*****************
Creation de l'interface utilisateur (hors procedure )
************************
Boucle principale (Events )
***********************
Zone des procedures
************************
DataSection
************************
-----------------------------------------------------------------------------------------------------------
les procedures toujours en fin de code !
cela evite d'avoir a parcourir 3 plombe un code pour arriver a la boucle principale ....
je considere les procedures comme des "accessoire" au programme ... donc il vont a la fin
l'appel se faisant la plupart du temp dans la boucle principale
pour ce qui concerne l'ecriture des variables :
pour les flags, j'utilise toujours le mot "flag_" en debut de nom d'un Flag
je Type en permanence toutes mes variables , comme ça si au milieu d'un code, je vois toto.l , je connais son type
et ceux meme si Purebasic permet de typer une seule fois en debut de code une variable, je garde le type affiché
tout au long du code
j'ajoute qu'il m'arrive d'utiliser des variables "Poubelle" , des variables qui ne servent que temporairement et tres localement
dans un code , ces variables, je leur donne un nom qui ne veux rien dire genre "qdfqf.s" ... lorsque je vois ce type de variable , je sais qu'elle me sert que dans les 10 prochaines lignes maximum ...
on peut aussi (mais je ne le fait pas ) ajouter une lettre devant le nom de la variable pour connaitre son type
genre L_toto.s (le "L" signifiant qu'elle est Local )
ou bien G_toto.s (le "G" signifiant qu'elle est Global ) etc ...
je n'utilise quasiment jamais les Includes ... (l'action de séparer un gros programme en plusieurs fichiers)
car .. je me suis rendu compte qu'au moment de debugger un prg fait ainsi , c'etait parfois tres difficile de savoir
ou se trouve un Bug ! ....
l'erreur apparait dans un fichier ... alors qu'en fait elle est généré par un autre fichier ...
comme dirai l'autre "Cherchez l'erreur"
alors qu'en ayant tout le code dans le meme Editeur ... c’est limpide ...
Dernière modification par Backup le lun. 28/avr./2014 9:56, modifié 13 fois.
avant de faire du basic, je suis passé par la case Pascal en autodidacte sur cpc6128 (je savais meme pas faire une boucle for/next à l'époque...)
pis un collègue lâsser de mes réparties moqueuse m'a assené un grand coup de "la bible de turbo pascal" sur le sommet de la tête...
et depuis bizarrement quel que soit le langage,
constante
type
enregistrement
variable globale
déclare (s'il y a lieu)(très rarement en fait)
fonction (procedure qui renvoie un argument)
procedure
init
programme principal
fin
pat
pis un collègue lâsser de mes réparties moqueuse m'a assené un grand coup de "la bible de turbo pascal" sur le sommet de la tête...
et depuis bizarrement quel que soit le langage,
constante
type
enregistrement
variable globale
déclare (s'il y a lieu)(très rarement en fait)
fonction (procedure qui renvoie un argument)
procedure
init
programme principal
fin
pat
comme je l'ai dit dans l'autre post ta structure ne marche pas dobro
L'IDE de pure me renvoie une erreur car il faut déclarer les structure avant.
sur Chronos le precompilateur génère un code comme ceci :
Sinon je vous conseille EnableExplicit qui vous obligera a déclarer chaque variable ce qui évite les erreurs.
Code : Tout sélectionner
Declare test(*chose.test)
Structure test
test.s
EndStructure
Procedure test(*chose.test)
EndProcedure
sur Chronos le precompilateur génère un code comme ceci :
Code : Tout sélectionner
;===========================================================;
;
; Main File : main.pb
; Code generated by chronos
;
;===========================================================;
EnableExplicit
IncludeFile "Constant.pbi" ;constante
IncludeFile "Structure.pbi" ;structure
IncludeFile "Global.pbi" ;variables globales
IncludeFile "Declaration.pb" ;déclaration des procédures
IncludeFile "Procedure.pb" ;Procédure et macro
repeat
forever
;data
Je suis 90% d'accord avec Patrick88, les 10% c'est parce que je ne sais pas à quoi correspond la zone enregistrement.
Je met toujours toujours les procedures avant d'écrire le code de la boucle.
Je rajoute que je met la datasection complètement à la fin.
J'ai pris l'habitude de commenter presque chaque ligne de code, ça ne prend que peut de temps et c'est pratique si on revient dessus plusieurs mois plus tard. Lorsqu'un truc me parait important , j'ajoute des lignes de commentaire pour expliquer.
aujourd'hui j'évite d'imbriquer des if dans des if dans des if dans des if ... car sur de grands codes, on s'y perd et si une erreur intervient, c'est pas toujours simple à retrouver.
Je vous met une procedure extraite du code sur lequel je travaille, beaucoup de tests et de procedureReturn, mais c'est simple, clair et ça marche bien.
Je ne dis pas que c'est la meilleure manière mais elle me convient et a l'avantage à mes yeux de clarifier le code.
J'utilise un décalage de 5 espaces, ça améliore la lecture.
Je met toujours toujours les procedures avant d'écrire le code de la boucle.
Je rajoute que je met la datasection complètement à la fin.
J'ai pris l'habitude de commenter presque chaque ligne de code, ça ne prend que peut de temps et c'est pratique si on revient dessus plusieurs mois plus tard. Lorsqu'un truc me parait important , j'ajoute des lignes de commentaire pour expliquer.
aujourd'hui j'évite d'imbriquer des if dans des if dans des if dans des if ... car sur de grands codes, on s'y perd et si une erreur intervient, c'est pas toujours simple à retrouver.
Je vous met une procedure extraite du code sur lequel je travaille, beaucoup de tests et de procedureReturn, mais c'est simple, clair et ça marche bien.
Je ne dis pas que c'est la meilleure manière mais elle me convient et a l'avantage à mes yeux de clarifier le code.
J'utilise un décalage de 5 espaces, ça améliore la lecture.
Code : Tout sélectionner
Procedure.i IS_Format_NE(hModule)
;///////////////////////////////////////////////////////////////////////////////////////////////////
;//
;// FONCTION: IS_Format_NE()
;//
;// BUT: tester une partie du header du fichier en mémoire pour déterminer si ce fichier
;// est un fichier 16 bits (format NE - Windows 3.x)
;//
;// PARAMS: hModule - pointeur sur le premier octet de la mémoire allouée pour charger le fichier icl
;//
;// RETOURNE: #True si le fichier est au format NE
;// #Return_Error (= #Fasle) si le fichier n'est pas au format NE
;//
;// UTILISATION : Typiquement, on l'utilise immédiatement après avoir chargé le fichier en mémoire
;// Plusieurs fonctions utilisent une partie de ce code mais sans en faire les tests car
;// ils ont été faits dans cette procedure
;//
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// mémorise l'adresse du contenu de la ressource, à partir du début du fichier modifié dans chaque boucle
Protected *Memory_Add_temp
;// memorise la dernière adresse valide du fichier en mémoire pour vérifier le non dépassement
Protected *LastMemoryAdress
;// mémorise l'offset de la zone NE depuis le début du fichier (pas l'adresse, l'offset depuis le début du fichier)
Protected Offset_NE_Header
;// mémorise l'offset de la Resource Table (pas l'adresse, l'offset depuis le début du fichier)
Protected Offset__Resource_Table
;// mémorise le coefficient de mutiplication de l'offset permettant de multiplier les valeurs virtuelles pour obtenir les valeurs réeelles
Protected rscAlignShift
;// on teste si le pointeur est nul, on stoppe si null
If hModule = #Null
SetError_Code(#Error_Code_Pointeur_Null)
ProcedureReturn #Return_Error
EndIf
;// mémorise la valeur du pointeur, ce pointeur va évoluer
*Memory_Add_temp = hModule
;// teste la taille de la mémoire qui doit valoir au moins 2 octets pour lire #IMAGE_DOS_SIGNATURE
If MemorySize(*Memory_Add_temp)<SizeOf(word)
SetError_Code(#Error_Code_Reading_Over_LastMemoryFileAdress)
ProcedureReturn #Return_Error
EndIf
;// on avance le pointeur sur la zone d'énumération après avoir testé le header
;// Lecture et vérification de la signature MS-DOS du fichier, "MZ"
If UPeekW(*Memory_Add_temp)<>#IMAGE_DOS_SIGNATURE
SetError_Code(#Error_Code_IMAGE_DOS_SIGNATURE)
ProcedureReturn #Return_Error
EndIf
;// définition de la dernière adresse de la mémoire, ne pas écrire après !
*LastMemoryAdress = *Memory_Add_temp + MemorySize(*Memory_Add_temp)-1
;// vérifie que les adresses de la zone IMAGE_DOS_HEADER sont définies
If (*Memory_Add_temp + SizeOf(IMAGE_DOS_HEADER))>*LastMemoryAdress
SetError_Code(#Error_Code_Reading_Over_LastMemoryFileAdress)
ProcedureReturn #Return_Error
EndIf
;// lecture de l'offset du NE header
Offset_NE_Header = PeekL(*Memory_Add_temp + OffsetOf(IMAGE_DOS_HEADER\e_lfanew))
;// teste que l'offset est différent de 0 sinon erreur
If Offset_NE_Header = 0
SetError_Code(#Error_Code_OFFSET_NULL_ICL_NE)
ProcedureReturn #Return_Error
EndIf
;// avance le pointeur pour arriver sur la zone IMAGE_OS2_HEADER
;// cette zone commence à l'adresse de base + la valeur de la variable Offset_NE_Header
*Memory_Add_temp + Offset_NE_Header
;// vérifie que les adresses de la zone IMAGE_OS2_HEADER sont définies
If (*Memory_Add_temp + SizeOf(IMAGE_OS2_HEADER)>*LastMemoryAdress)
SetError_Code(#Error_Code_Reading_Over_LastMemoryFileAdress)
ProcedureReturn #Return_Error
EndIf
;// vérification de la signature, élément ne_magic.w (Magic number) de la structure IMAGE_OS2_HEADER
If UPeekW(*Memory_Add_temp)<>#IMAGE_OS2_SIGNATURE
SetError_Code(#Error_OS2_SIGNATURE)
ProcedureReturn #Return_Error
EndIf
;// lecture de l'offset de la table des ressources
Offset__Resource_Table = UPeekW(*Memory_Add_temp + OffsetOf(IMAGE_OS2_HEADER\ne_rsrctab))
If Offset__Resource_Table = #Null
SetError_Code(#Error_Offset__Resource_Table_Null)
ProcedureReturn #Return_Error
EndIf
;// on positionne le pointeur sur la Resource Table
*Memory_Add_temp + Offset__Resource_Table
;// vérifie que les adresses de la zone RESOURCE_TABLE sont définies
If (*Memory_Add_temp + SizeOf(RESOURCE_TABLE)>*LastMemoryAdress) Or (Offset__Resource_Table<1)
SetError_Code(#Error_Code_Reading_Over_LastMemoryFileAdress)
ProcedureReturn #Return_Error
EndIf
;// Lecture du décalage, élément de la table de ressources
rscAlignShift = UPeekW(*Memory_Add_temp + OffsetOf(RESOURCE_TABLE\rscAlignShift))
;// teste que le décalage existe et limite à 1Go la taille possible avec un décalage de 14
If (rscAlignShift<0) Or (rscAlignShift>14)
SetError_Code(#Error_RESOURCE_TABLE_rscAlignShift)
ProcedureReturn #Return_Error
EndIf
ProcedureReturn #True
EndProcedure
en fait, en pascal c'est dans la zoneDenis a écrit :Je suis 90% d'accord avec Patrick88, les 10% c'est parce que je ne sais pas à quoi correspond la zone enregistrement.
Code : Tout sélectionner
TYPE
T_mon_enregistrement = record
...
end;
dure de respecter cette structuration du code avec le LISP par exemple
pat
personellement je construit toujours mon code avec les procedures a la fin, je trouves cela plus clair.
en gros
1/ structures
2/ initialisaton des variables
3/declaration procedures
4/boucle principale
5/procedures
6/data
je commente mon code, je met noir de commentaires a droite des lignes de code
je balise mon code
je met encore des commentaires sur le fonctionnement du code
j'explique a quoi servent les variables
par exemple :
en pb j'abuse des balisage de type
en mettant un ;- le commentaire deviens visible dans l'explorateur de l'ide dans les procedures un simple clic et je retrouve la bonne section du code
en gros
1/ structures
2/ initialisaton des variables
3/declaration procedures
4/boucle principale
5/procedures
6/data
je commente mon code, je met noir de commentaires a droite des lignes de code
je balise mon code
je met encore des commentaires sur le fonctionnement du code
j'explique a quoi servent les variables
par exemple :
Code : Tout sélectionner
Global NewList canaux.canal() ; garde les canaux disponibles
Code : Tout sélectionner
;- procedures
Code : Tout sélectionner
;- structure
-
-
-
;- gloabales
-
-
-
;- declaration procedures
-
-
-
-
-
;-boucle principale
-
-
-
-
;-procedures
-
-
-
;-datas
-
-
-
-
Comme Denis, je programme depuis presque 30 ans, j'en ai même fait des études.
Alors je construit toujours mes programmes de la même façon (ou presque car avec l'assembleur c'est pas pareil) :
Je décomposes par type (les constantes, globales, Structures, DataSection, puis les procédures), puis le programme principal fait les includes de toute ce petit monde.
Bien sur c'est pour le cas ou le projet est important, pour un petit programmes, les déclarations, les constantes, les procédures, la boucle principale et les datasections, c'est une méthode comme une autre, l'important c'est de s'y retrouver, sauf si on veut faire du travail collaboratif et la, je ne le répéterais jamais assez : "commentez le plus possible ce que vous faites dans vos procédures"
Alors je construit toujours mes programmes de la même façon (ou presque car avec l'assembleur c'est pas pareil) :
Je décomposes par type (les constantes, globales, Structures, DataSection, puis les procédures), puis le programme principal fait les includes de toute ce petit monde.
Bien sur c'est pour le cas ou le projet est important, pour un petit programmes, les déclarations, les constantes, les procédures, la boucle principale et les datasections, c'est une méthode comme une autre, l'important c'est de s'y retrouver, sauf si on veut faire du travail collaboratif et la, je ne le répéterais jamais assez : "commentez le plus possible ce que vous faites dans vos procédures"
Dernière modification par flaith le mer. 28/janv./2009 21:43, modifié 2 fois.
-
- Messages : 4312
- Inscription : mer. 28/janv./2004 20:58
- Localisation : Clermont ferrand OU Olsztyn
- Contact :
hum, et bien moi, un comme gnozal, je crois, je préfère la méga source avec tout dedans
mais j'adopte une architecture par fonction
en gros je groupe les globales, list, data et procedure de chaque fonction du programme
et je sépare avec des lignes vierges
un peu comme si j'avais copier coller les includes dans le programmes principal
chacun son truc, moi, je préfère remonter dans le code (surtout avec le pliage de procédure, c'est tres facile) que chercher dans quel fichier j'ai bien pu foutre la fichu fonction que je veux modifier
mon plus gros code fait 7300 lignes, et je m'y retrouve très bien comme ça
Mais, il m'arrive d'utiliser des includes, notamment pour les procedures de chargement de fichier (pour les jeux surtout)
parceque c'est volumineux et pas utile quand on code
c'est bien le seul cas pour l'instant.
En gros include pour ce qui sert pratiquement jamais, et tout le reste dans le fichier principal
mais j'adopte une architecture par fonction
en gros je groupe les globales, list, data et procedure de chaque fonction du programme
et je sépare avec des lignes vierges
un peu comme si j'avais copier coller les includes dans le programmes principal
chacun son truc, moi, je préfère remonter dans le code (surtout avec le pliage de procédure, c'est tres facile) que chercher dans quel fichier j'ai bien pu foutre la fichu fonction que je veux modifier
mon plus gros code fait 7300 lignes, et je m'y retrouve très bien comme ça
Mais, il m'arrive d'utiliser des includes, notamment pour les procedures de chargement de fichier (pour les jeux surtout)
parceque c'est volumineux et pas utile quand on code
c'est bien le seul cas pour l'instant.
En gros include pour ce qui sert pratiquement jamais, et tout le reste dans le fichier principal
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?
[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
-
- Messages : 4312
- Inscription : mer. 28/janv./2004 20:58
- Localisation : Clermont ferrand OU Olsztyn
- Contact :
Moi c'est la technique de l'oignon que l'on épluche couche après couche...
C'est toujours agréable un programme plié
Ou la technique du champignon. Le code est immangeable puisqu'il est généré par d'autres codes. Avec ça, c'est le dicton "Quand on veut, on peut"
Ou enfin la technique du ni vu ni connu. Macros à bloc.
Conclusion: Entre les oignons, les champignons et les maquereaux, il y a le choix du menu.
C'est toujours agréable un programme plié
Code : Tout sélectionner
{ En-tête }
Main()
Ou enfin la technique du ni vu ni connu. Macros à bloc.
Conclusion: Entre les oignons, les champignons et les maquereaux, il y a le choix du menu.
Pour parler du sujet,
c'est vrai que d'instaurer une norme pour le codage parementerai de gagner énormément de temps.
mais comme je viens de lire dans les posts précédents, "les vieux" ont et garderont leurs habitudes. ( j'ai mis entre guillemet )
donc il y aura toujours conflits.
exemple moi j'évite les procédures tant que je peut.
mais bon sa serai tellement plus compréhensible ainsi.
@++
c'est vrai que d'instaurer une norme pour le codage parementerai de gagner énormément de temps.
mais comme je viens de lire dans les posts précédents, "les vieux" ont et garderont leurs habitudes. ( j'ai mis entre guillemet )
donc il y aura toujours conflits.
exemple moi j'évite les procédures tant que je peut.
mais bon sa serai tellement plus compréhensible ainsi.
@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
GPU : radeon HD6370M, CPU : p6200 2.13Ghz