1. Préambule.▲
Je suis accoutumé à relire et à corriger du code, à l'enseigner dans notre équipe de travail et à
reprendre des sources fournis par des prestataires de service, souvent bourrés d'erreurs et manquant de
sécurités, alors qu'ils devraient justement s'appliquer pour que leurs clients puissent reprendre le
code avec le moins de peine possible, donc avec moins de perte de temps.
Je me limiterais ici à donner quelques conseils d'écriture, dont je me suis fait des règles.
Voici ce qui représente un véritable cauchemar pour ceux qui doivent reprendre du code pour
le corriger, le compléter ou tout simplement l'analyser pour apprendre. Inutile de préciser que si
vous imposez cette façon d'écrire à un collègue, vous serez maudit et risquez fort de vous faire
injurier. J'ai vu (et corrigé) des codes écrits de cette façon sur plus de 400 lignes.
procedure
TBDlisteImage.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer
);
var
n:integer
;
begin
inherited
mousedown(button,shift,x,y);
n:=x div
wfixe;
n:=n + (colcount * ( y div
hfixe));
if
button=mbLeft then
begin
if
(n<>indexcourant) and
((indexbase+n)<=listephoto.Count-1
) then
setindexcourant(n)
else
if
((indexbase+n)<=listephoto.Count-1
) then
affiche(self
);
end
else
if
(button=mbRight) and
((indexbase+n)<=listephoto.Count 1
) then
begin
imprime_image;
end
;
end
;
Ceci montre un exemple court, qui n'est pas de moi.
Je me suis trouvé devant le cas suivant : un composant graphique qui correspondait à ce que je cherchais pour
une application. Malheureusement, il y avait encore des Bogues et il manquait des sécurités. J'ai voulu reprendre
le code pour l'analyser et le corriger. Je me suis trouvé devant un truc inextricable que j'ai commencé à ré
indenter. Mais c'était tellement énorme, que j'ai renoncé. Dommage pour celui qui a écrit le composant et à
qui on dit qu'il a travaillé comme un cochon. Non ?
Bien sur, nous avons tous nos règles et petites habitudes qui nous conviennent. Cependant, nous
devons toujours garder à l'esprit que nos codes seront utilisés par un tiers, soit parce qu'il est libre de
droit, soit par nécessité de modification ou de débogage.
Commençons par corriger l'indentation de cette procédure .
procedure
TBDlisteImage.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer
);
var
n : integer
;
begin
inherited
mousedown(button,shift,x,y);
n := x div
wfixe;
n := n + (colcount * ( y div
hfixe));
if
button = mbLeft then
begin
if
(n<>indexcourant) and
((indexbase+n)<=listephoto.Count-1
) then
setindexcourant(n)
else
if
((indexbase+n)<=listephoto.Count-1
) then
affiche(self
);
end
else
if
(button=mbRight) and
((indexbase+n)<=listephoto.Count-1
) then
begin
imprime_image;
end
;
end
;
C'est tout de même plus lisible, non ?
Voici un autre exemple pour terminer ce préambule.
function
TBDlisteimage.dessinerimage;
var
st:string
;
h,l,r:double
;
h1,l1:integer
;
img:Tpicture;
begin
img:=Tpicture.Create;
st:=listephoto[indexbase+index
];
result:=true
;
try
try
img.LoadFromFile(st);
except
on
EInvalidGraphic do
begin
listephoto.Delete(indexbase+index
);
result:=false
;
exit;
end
;
end
;
h:=img.graphic.Height;
l:=img.graphic.Width;
h1:=hfixe-(marge*2
);
l1:=wfixe-(marge*2
);
try
if
((l/h)<=(l1/h1)) then
begin
r:=l/h*h1;
l1:=trunc(r);
end
else
begin
r:=h/l*l1;
h1:=trunc(r);
end
;
except
begin
listephoto.Delete(indexbase+index
);
result:=false
;
exit;
end
;
end
;
canvas.Brush.color:=self
.color; canvas.Pen.Color:=clwhite;
canvas.Pen.Width:=1
;
canvas.Rectangle( ((index
mod
colcount) * wfixe) + self
.Left + 2
,
((index
div
colcount) * hfixe) + self
.top+2
,
((index
mod
colcount) * wfixe)+wfixe+self
.Left-1
,((index
div
colcount)
* hfixe)+hfixe+self
.top-1
);
canvas.StretchDraw(rect((wfixe-l1) div
2
+ (index
mod
colcount *
wfixe),(hfixe-h1) div
2
+ (index
div
colcount * hfixe),
(wfixe-l1) div
2
+ (index
mod
colcount * wfixe)+l1,(hfixe-h1) div
2
+
(index
div
colcount * hfixe)+h1),img.graphic);
finally
img.free;
end
;
end
;
C'est à se demander comment l'auteur a réussi à se relire. Visiblement pas sensibilisé au fait qu'un
tiers voudra lire son code pour quelque raison que se soit.
2. Base de l'indentation.▲
L'indentation dans l'écriture de code n'a aucun effet sur son exécution. Son intérêt est de le rendre
lisible, d'en faciliter l'analyse et la correction. Il n'y a pas vraiment de règles, mais par expérience je
sais qu'il n'y a pas 36 façons d'indenter correctement du code. Tous les programmeurs confirmés
utilisent presque les mêmes méthodes. Cependant il est clair que par nécessité nous changeons
quelques fois notre façon de faire. En terme simple l'indentation consiste à organiser le texte
représentant le code de façon à le rendre (visuellement) aussi lisible que possible. Cela consiste
principalement à décaler les lignes de texte comme je l'ai montré en préambule.
3. Comment nommer une procédure, une fonction, un objet ?▲
Choisissez des noms clairs et significatifs. Cela évitera souvent des commentaires et vous permettra
de mieux vous souvenir de l'élément (fonction, procédure...) que vous voulez utiliser. Donnez lui le
nom de ce qu'elle est sensée faire.
Exemple : Si c'est une fonction chargée de vérifier si une chaîne de caractères représente un nombre
entier :
Function
ChaineEntierValide(Chn : String
) : Boolean
et non pas :
Function
CEV(S : String
) : Boolean
;
Il est clair que si une fonction dont le nom n'est pas parlant mais documentée, cela ne parait pas
important. Mais si elle s'appelle "ChaineEntierValide" et qu'elle fait partie d'une bibliothèque d'outils,
je m'en souviens parce qu'elle porte le nom de ce qu'elle est sensée faire. C'est une vieille habitude
qui m'est bien profitable. Borland a déclaré la procédure "SetLength" et non pas "SL", c'est la même règle.
Si vous avez besoin de trois tableaux devant contenir l'un des noms, l'autre des valeurs numériques
et le troisième des adresses.
Vous pouvez les déclarer comme ceci :
Tableau1 : Array
Of
String
;
Tableau2 : Array
[0
..200
] Of
Integer
;
Tableau3 : Array
Of
String
;
Alors dès le début, écrivez une documentation pour vous aider.
Faite comme ceci :
TableauNoms,
TableauAdresses : Array
Of
String
;
TableauValeurs : Array
[0
..200
] Of
Integer
;
Encore une fois, cet exemple court ne parait pas pertinent, mais imaginez
ce que cela peut donner dans une application conséquente.
Très important, donnez des noms significatifs aux boutons et autres objets. Ce n'est pas indispensable
si ils sont peu nombreux, mais vous serez vite perdu dans une grosse application.
Procedure
TForm1.BitBtn1Click(Sender : TObject);
Procedure
TForm1.Button1Click(Sender : TObject);
Voila qui facilitera votre travail .
Procedure
TForm1.BtOuvrirClick(Sender : TObject);
Procedure
TForm1.BtCalculClick(Sender : TObject);
C'est la même chose pour les noms des fiches.
Plutôt que Form1, Form2 ... Form10, choisissez des noms clairs. FichePrincipale,
FicheConfiguration, FicheImpression ... Là encore, en écrivant le programme, vous vous souviendrez immédiatement du nom de la fiche que vous voulez appeler.
4. Déclarations de variables types et constantes.▲
Il est courant de voir ceci .
Type
TabInfoTube=Array
[0
..49
] Of
Array
[1
..8
] Of
ShortString;
Const
CheminResultats:String
='c:\resdo'
;
CycleEnCours:Boolean
=False
;
SaisiesValides:Boolean
=False
;
ParametresValides:Boolean
=False
;
NbTubes:Integer
=1
;
SourceValide:Boolean
=False
;
TensionDeBase:Double
=8
;
ReferenceTubeZero:Boolean
=True
;
SELDIRHELP = 1000
;
Var
ErreurCoef:Boolean
;
FichePrincipale:TFichePrincipale;
Densite,PoidsSec:Double
;
TempsEcouleInt:Int64;
Lecture:Integer
;
Abandon:Boolean
;
Debut:TDateTime;
FichierSource: String
;
InfoTube:TabInfoTube;
// Support EXCEL
OleApplication:Variant;
OleWorkBook:Variant;
implementation
Mais ça c'est mieux parce que clair et lisible .
Type
TabInfoTube = Array
[0
..49
] Of
Array
[1
..8
] Of
ShortString;
Const
CheminResultats : String
= 'c:\resdo'
;
CycleEnCours : Boolean
= False
;
SaisiesValides : Boolean
= False
;
ParametresValides : Boolean
= False
;
NbTubes : Integer
= 1
;
SourceValide : Boolean
= False
;
TensionDeBase : Double
= 8
;
ReferenceTubeZero : Boolean
= True
;
SELDIRHELP = 1000
;
Var
ErreurCoef : Boolean
;
FichePrincipale : TFichePrincipale;
Densite, PoidsSec : Double
;
TempsEcouleInt : Int64;
Lecture : Integer
;
Abandon : Boolean
;
Debut : TDateTime;
FichierSource : String
;
InfoTube : TabInfoTube;
// Support EXCEL
OleApplication : Variant;
OleWorkBook : Variant;
implementation
Même si cela parait plus esthétique que nécessaire, ce n'est pas une perte de temps que de réaligner si on change ou ajoute une variable (ce qui n'est pas obligatoire). Je reconnais qu'un alignement parfait n'est pas indispensable. Mais au moins un espace de chaque coté de ":" Valeur : Word; Je préconise cette méthode, car cela me facilite beaucoup mon travail de reprise de code et je vais beaucoup plus vite car c'est beaucoup plus lisible.
5. Indentations de blocs.▲
Le rôle d'un bloc est de cloisonner les parties de code dépendant d'une condition et/ou de regrouper des instructions liées à un même traitement.
Voici les deux façons les plus courantes d'indenter des blocs "begin end".
If
Valeur1 = Valeur2 Then
begin
//Traitement
end
;
Je préfère la seconde, parce que beaucoup plus lisible.
If
Valeur1 = Valeur2 Then
begin
//Traitement
end
;
Un cas particulier, "Repeat Until". Il constituent ensemble un bloc.
Donc :
Repeat
begin
// Traitement
end
;
Until
Fin;
"begin et end" sont inutiles.
Ne décalez pas trop et pas systématiquement les blocs d'instructions. Un décalage trop important dans de longue procédures ou fonctions, va élargir le texte au point de sortir de l'écran. Cela rendra la lecture difficile. Là encore, ce n'est pas une règle mais un conseil.
Pour moi un scrollling latéral est plutôt gênant.
6. Les blocs "begin end" et les sauts de lignes.▲
J'ai l'habitude de considérer que ce qui n'est pas nécessaire est inutile.
Je vais montrer deux exemples simples de l'écriture d'un test conditionnel .
If
Valeur1 = Valeur2 Then
begin
MessageDlg('Réussi'
,mtInformation,[mbOK],0
);
end
;
Pourquoi faire simple quand on peut faire compliqué ? Ici, le bloc "begin end" est parfaitement inutile.
Si ils manquent, et que l'on a besoin d'ajouter des instructions suite au test conditionnel, il est tout de même facile de les rajouter.
If
Valeur1 = Valeur2 Then
MessageDlg('Réussi'
,mtInformation,[mbOK],0
);
Les sauts de lignes entre plusieurs blocs d'instructions.
Pas indispensable mais quelques fois bien commodes.
{--------------------------------------------------------------------- }
procedure
TFichePrincipale.FormActivate(Sender: TObject);
Var
W,Y,C : Integer
;
begin
If
DebutProgramme Then
begin
DebutProgramme := False
;
Image1.Width := 800
;
Image1.Height := 600
;
//
//
With
Image1.Picture.Bitmap Do
begin
Width := 800
;
Height := 600
;
Canvas.Brush.Color := clWhite;
Canvas.Pen.Color := clBlack;
Canvas.Rectangle(0
,0
,799
,599
);
end
;
//
//
W := Image3.Width;
With
Image3.Picture.BitMap Do
begin
Width := Image3.Width;
Height := Image3.Height;
Canvas.Rectangle(0
,0
,Image3.Width,Image3.Height);
end
;
//
//
For
Y := 255
DownTo
0
Do
begin
C := 255
- Y;
Pixel[1
] := C;
Pixel[2
] := C;
Pixel[3
] := C;
Move(Pixel,C,3
);
With
Image3.Picture.BitMap Do
begin
Canvas.Pen.Color := C;
Canvas.MoveTo(0
,Y);
Canvas.LineTo(W,Y);
end
;
end
;
//
//
Image3.Refresh;
Image4.Picture.BitMap := Image3.Picture.BitMap;
TransfertCopiePlan(Image1.Picture.Bitmap);
TransfertBitmap(1
);
If
EvaluerDecoloration Then
RadioButton2.Checked := True
Else
RadioButton1.Checked := True
;
Application.ProcessMessages;
end
;
//
EditCodeBarre.SetFocus;
end
;
7. L'instruction "with", profitez en.▲
L'instruction With peut être traduite en français par : "avec" ou "concernant". Il n'y a
pas d'équivalent en C ou C++. Cette une instruction très commode qui permet d'alléger
le code de façon importante lors de paramétrage de valeurs dans un objet ou une structure.
En effet cette instruction ne s'applique qu'à ces derniers.
Exemple 1 concernant un TStringGrid .
procedure
TFicheSaisies.FormCreate(Sender: TObject);
begin
StringGrid1.Cells[0
,0
] := 'Tube'
;
StringGrid1.Cells[1
,0
] := 'Organisme'
;
StringGrid1.Cells[2
,0
] := 'Milieu'
;
StringGrid1.Cells[3
,0
] := 'Produit'
;
StringGrid1.Cells[4
,0
] := 'Dose'
;
StringGrid1.Cells[5
,0
] := 'Témoins'
;
StringGrid1.Cells[6
,0
] := 'Observations'
;
Coll:=1
;
Lig:=1
;
end
;
Plus simple :
procedure
TFicheSaisies.FormCreate(Sender: TObject);
begin
With
StringGrid1 Do
begin
Cells[0
,0
] := 'Tube'
;
Cells[1
,0
] := 'Organisme'
;
Cells[2
,0
] := 'Milieu'
;
Cells[3
,0
] := 'Produit'
;
Cells[4
,0
] := 'Dose'
;
Cells[5
,0
] := 'Témoins'
;
Cells[6
,0
] := 'Observations'
;
end
;
Coll:=1
;
Lig:=1
;
end
;
Exemple 2 concernant une structure.
Type
TabOrgMil = Record
NomOrganisme : String
[20
];
TypeOrganisme : Integer
;
CodeOrganisme : Word
;
end
;
Var
Organismes : TabOrgMil;
Procedure
Init;
begin
With
Organismes Do
begin
NomOrganisme := 'Botritice'
;
TypeOrganisme := 1
;
CodeOrganisme := 125
;
end
;
end
;
8. Les lignes de séparation, indispensables. ▲
Séparez toutes vos procédures et fonctions par une ligne de commentaire neutre. Je sais
bien que pour beaucoup cela n'est pas nécessaire, mais après de nombreuses années d'expérience,
je peux dire que c'est indispensable.
Procédez comme suit.
Var
Configuration : TConfiguration;
//------------------------------------------------------------
Function
TFicheLecture.Etat : Integer
;
Begin
Result := EtatControle;
End
;
//------------------------------------------------------------
Procedure
TFicheLecture.DemandeAutorisation;
Begin
Clignotant1.Enabled := True
;
BtPret.Enabled := False
;
ComPort1.WriteStr('PORTE'
+ #13
);
BtDemande.Enabled := False
;
End
;
//------------------------------------------------------------
Procedure
TFicheLecture.Fairelecture;
Begin
BtPret.Enabled := False
;
Clignotant1.Enabled := True
;
ComPort1.WriteStr('LECTURE'
+ #13
);
End
;
//------------------------------------------------------------
Procedure
TFicheLecture.ConfigureLePort;
Begin
With
Configuration Do
Bien que plus esthétique que réellement utile, cela facilite beaucoup
la lecture .
9. Les commentaires : Pour quoi faire, comment et où les placer ?▲
Je rassure tout de suite ceux qui pensent qu'ils vont augmenter la taille du fichier une
fois compilé. Cela m'a déjà été donné comme argument pour s'en passer. Les commentaires
ne sont pas intégrés dans le code, et sont ignorés du compilateur.
Un commentaire en terme de programmation a avant tout un sens explicatif. Il peut représenter
une note, un aide mémoire, une courte (mais claire) explication sur ce que fait la fonction
ou la procédure, comment est utilisée une variable et même un petit exemple d'utilisation
de la routine.
Il faut se contenter du nécessaire, et de le décrire de façon claire et aussi simple que
possible, sans en faire trop. On pourrait mettre un commentaire à chaque ligne de code.
Mais comme un exemple vaut mieux qu'un long discours, voici.
Les commentaires en entête de fonctions.
{--------------------------------------------------------}
{ Ajoute un antislash (\) au chemin si il manque }
{--------------------------------------------------------}
Function
CompleteChemin(Chemin : String
) : String
;
Begin
If
Chemin[Length(chemin)] <> '\'
Then
Chemin := Chemin + '\'
;
End
;
{------------------------------------------------------- }
{ Compte le nombre de mots d'une phrase en utilisant }
{ un ou plusieurs caractères séparateurs de champs }
{ Exemple : Mots:=CompteMots(Chaine,[',',';',#9]); }
{ Utilisation de la virgule, du point virgule }
{ et du tabulateur comme séparateur de champs }
{--------------------------------------------------------}
Function
CompteMots(S : String
; WordDelims : EnsembleCarac) : Integer
;
var
I, Count : Integer
;
begin
If
Length(S) = 0
Then
Result := 0
Else
begin
Count := 1
;
For
I:=1
To
Length(S) Do
If
(S[I] in
WordDelims) Then
Inc(Count);
Result := Count;
end
;
end
;
Les commentaires dans le code .
If
M > C Then
begin
C := M;
// Attribuer autant de colonnes que de mots par ligne
// La colonne zéro est réservée pour l'indexage.
If
Grille.ColCount < C + 1
Then
Grille.ColCount := C + 1
;
end
;
Grille.Cells[0
,L] := IntToStr(L);
For
I:=1
To
M Do
Grille.Cells[I,L] := ExtraitMot(I,Chn,Separateur);
Un type particulier de commentaire.
{-------------------------------------------------------------------}
{ Faire le négatif d'une image }
{-------------------------------------------------------------------}
Procedure
Negatif(X1,Y1,X2,Y2 : Integer
);
Var
X,Y : Integer
;
Begin
For
X:=X1 to
X2 Do
For
Y:=Y1 to
Y2 Do
begin
{ Méthode plus rapide }
PlanImage1[Y,X][1
]:=PlanImage1[Y,X][1
] XOR
$FF
;
PlanImage1[Y,X][2
]:=PlanImage1[Y,X][2
] XOR
$FF
;
PlanImage1[Y,X][3
]:=PlanImage1[Y,X][3
] XOR
$FF
;
{
Pixel:=PlanImage1[Y,X];
Pixel[1]:=255 - Pixel[1];
Pixel[2]:=255 - Pixel[2];
Pixel[3]:=255 - Pixel[3];
PlanImage1[Y,X]:=Pixel;
}
end
;
TransfertBitMap(1
);
End
;
Ceci montre que j'ai écrit la partie de code en commentaire en premier.
La jugeant trop lente j'ai cherché un algorithme plus rapide. Je laisse
l'ancien code le considérant comme aide mémoire.
10. Les tests conditionnels booléen : Ne programmez pas comme un débutant.▲
Nous avons tous commencé à écrire un test conditionnel sur une variable booléenne de cette façon :
If
Termine = True
Then
J'ai appris de cette façon jusqu'au jour où j'ai compris que en quelque sorte on vient
d'écrire : "si vérité est vraie alors..."
Le test conditionnel est implicite et ne peut prendre que deux valeurs, vrai ou faux.
Donc écrivez très simplement :
If
Termine Then
Ou bien :
If
Not
Termine Then
Là non plus, cela paraît pas très pertinent et de toute façon n'est pas obligatoire.
Simple habitude d'une écriture plus simple.
Un autre exemple :
If
testVitesse = True
AND
testVolumeB1 = True
AND
testVolumeB2 = False
AND
testVolumeB3 = True
AND
testSommeVolumes = True
AND
testFlacon = False
AND
TestFichierPara = False
AND
testNbflacon = True
Then
ValidationPara := true
else
ValidationPara := false
;
Ouf !
Pourquoi pas comme ceci ?
If
testVitesse AND
testVolumeB1 AND
(Not
testVolumeB2) AND
testVolumeB3 AND
testSommeVolumes AND
testFlacon AND
(Not
TestFichierPara) AND
testNbflacon Then
ValidationPara := true
Else
ValidationPara := false
;
Et même comme cela !
ValidationPara := testVitesse AND
testVolumeB1 AND
(Not
testVolumeB2) AND
testVolumeB3 AND
testSommeVolumes AND
testFlacon AND
(Not
TestFichierPara) AND
testNbflacon;
A vous de choisir.
11. Quand et où faut il déclarer une variable, globale, locale... ?▲
Comme je le disais plus haut, tout ce qui n'est pas nécessaire est inutile.
Le langage PASCAL présente un très gros avantage sur le C, c'est de rassembler dans la même unité,
l'interface et l'implémentation. Pour ceux qui ne connaissent pas le langage C, l'équivalent de la
partie interface en PASCAL est placé dans un autre fichier portant l'extension H.
Déclarez les types, variables et constantes globales à l'unité dans la partie "Implementation".
Préférez déclarer dans la partie "interface", les types, variables et constantes, seulement ceux et
celles dont d'autres unités auront besoin.
Utilisez les variables locales au maximum, pourquoi ?
Quand j'ai commencé à programmer en TURBO-PASCAL , je l'ai appris avec un autodidacte (comme beaucoup
à l'époque), qui avait l'habitude de rassembler toutes les variables dans une même unité appelée UVar.
Cela semblait pratique. Jusqu'au jour où nous nous sommes lancé dans la conception d'un robot d'analyse
et de recherche de traces (dans un laboratoire de chimie.). Cette machine utilisait six
ordinateurs dont un maître qui devait gérer l'ensemble, avec tous les
échanges de données par liaison RS232. Nous-nous sommes trouvé devant des centaines de pages de code
et une gigantesque unité UVar.
Très vite nous avons été dépassé par les confusions et les interactions de variables. J'ai vite compris
que notre façon de faire était à revoir complètement. Je me suis imposé une règle, proscrire toute unité
rassemblant des type de données et variables communes à l'ensemble de l'application, sauf absolue nécessité
de rendre communs certains types, variables et constantes.
Si dans une procédure ou une fonction vous devez utiliser des variables uniquement dans cette fonction,
déclarez les de façon local.
Vous éviterez ainsi de nombreuses confusions et risque de confondre des données dans d'autres fonctions
(ou procédures).
Et comme un exemple vaut mieux qu'un long discours…
unit
Fiche1;
interface
uses
Windows,SysUtils, Messages, Classes, Graphics, Controls,
Forms, Dialogs, Menus;
type
TFichePrincipale = class
(TForm)
Label1: TLabel;
Image1: TImage;
Image2: TImage;
procedure
Quitter1Click(Sender: TObject);
private
{ Déclarations private }
public
{ Déclarations public }
Function
ChargeDonneesEXCEL : Boolean
;
end
;
// Les types, constantes et variables déclarés dans cette partie
// Interface, sont de genre "global". C'est à dire reconnus
// par toutes les unités faisant appel à celle ci, et par toutes
// les fonctions et procédures de cette unité.
Type
TabInfoTube = Array
[0
..49
] OfArray[1
..8
] Of
ShortString;
Const
CheminResultats : String
= 'c:\resdo'
;
CycleEnCours : Boolean
= False
;
SaisiesValides : Boolean
= False
;
ParametresValides : Boolean
= False
;
var
FichePrincipale : TFichePrincipale;
ErreurCoef : Boolean
;
Densite, PoidsSec : Double
;
TempsEcouleInt : Int64;
Lecture : Integer
;
Abandon : Boolean
;
Debut : TDateTime;
FichierSource : String
;
InfoTube : TabInfoTube;
implementation
{$R *.DFM}
// Les types, constantes et variables déclarés dans cette partie
// Implementation, sont de genre à la fois "global" et "local".
// C'est à dire "local" à l'unité, mais "global" pour toutes les
// fonctions et procédure déclarées dans la partie Implementation.
Type
TabCoef = Array
[1
..7
] Of
Double
;
TabCorrecteur = Array
[1
..2
] Of
Double
;
Const
Chercher : Boolean
= False
;
Tube1Trouve : Boolean
= False
;
LectureEnCours : Boolean
= False
;
Var
TC : TabCorrecteur;
TableCoef : TabCoef;
LecturesReste,
Vite,
TopFiche , LeftFiche : Integer
;
CheminCoefDO : String
;
NumTube : Byte
;
//----------------------------------------------------
//-- Vérifier la validité d'une chaîne de caractères
//----------------------------------------------------
Function
ChaineValide(S : String
) : Boolean
;
Var
I : Integer
;
// La variable "I" est strictement locale à la fonction.
// Je n'ai pas donné de nom explicite à cette variable,
// car le code est suffisamment court et compréhensible.
Begin
Result := False
;
If
Length(S) = 0
Then
Exit;
For
I := 1
To
Length(S) Do
begin
If
Ord(S[I]) > 32
Then
begin
Result := True
;
Break;
end
;
end
;
End
;
//----------------------------------------------------
//-- Sauvegarder les valeurs de calcul
//----------------------------------------------------
Procedure
SauveCoefPoidsSec;
Var
Fichier : File
Of
TabCoef;
Erreur : Integer
;
// Les deux variables "Fichier" et "Erreur" sont strictement
// locales à la procédure. Aucune autre fonction ou procédure
// de l'application ne peut y avoir accès.
// De plus, j'ai devant les yeux les noms des variables, ce
// qui me facilite la tâche.
Begin
TableCoef[5
] := TC[1
];
TableCoef[6
] := TC[2
];
If
FileExists(CheminCoefDO) Then
DeleteFile(CheminCoefDO);
AssignFile(Fichier,CheminCoefDO);
ReWrite(Fichier);
Erreur:=IOresult;
If
Erreur = 0
Then
Write
(Fichier,TableCoef);
Erreur:=IOresult;
End
;
end
.
12. Notation hongroise (lien)▲
Notation hongroise
WikipediA - Hungarian notation.
13. Outils de reformatage et autres liens▲
Les meilleurs composants VCL et outils pour Delphi et C++Builder
Sélectionnés par DEVELOPPEZ.COM
Jedi Code Format Pour DELPHI.
DelForExp Pour DELPHI et KYLIX.