Indentation et conseils d'écriture en pascal.

Philippe GORMAND

DELPHI = PASCAL.

Petit rappel : DELPHI est un outil de développement pour le langage PASCAL pour WINDOWS. Son origine est le TURBO-PASCAL développé par le français Philippe KHAN.

Quand vous développez un programme vous devez toujours garder à l'esprit qu'un tiers, pourra être amener à le modifier ou à le compléter. Un des objectifs des préconisations d'écriture est de faciliter la compréhension d'un code source. La maintenance corrective et évolutive sera ainsi réduite en évitant de fastidieuses phases de reprise de code. En résumé, facilitez la compréhension de ce que fait le code plutôt que comment il le fait. Je montre ici, simplement ma façon de faire, je ne peux que conseiller (en particulier les débutants) de s'en inspirer.

Je tiens à remercier l'équipe DELPHI de Developpez.com, et en particulier Laurent Dardenne pour son aide et pour ses conseils.

- Titre : Indentation et conseils d'écriture en pascal.

- Auteur : Philippe GORMAND

- Parution : 18 mai 2006

- Mise à jour : 12 mai 2006

- Licence : Copyright ® 2006 Philippe GORMAND. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- 1.   Préambule.

- 2.   Base de l'indentation.

- 3.   Comment nommer une procédure, une fonction, un objet ?

- 4.   Déclarations de variables types et constantes.

- 5.   Indentations de blocs.

- 6.   Les blocs "begin end" et les sauts de lignes.

- 7.   L'instruction "with", profitez en.

- 8.   Les lignes de séparation, indispensables.

- 9.   Les commentaires : Pour quoi faire, comment et où les placer ?

- 10. Les tests conditionnels booléen : Ne programmez pas comme un débutant.

- 11. Quand et où faut il déclarer une variable, globale, locale... ?

- 12. Notation hongroise (lien)

- 13. Outils de reformatage et autres liens

- 14. L'article au format PDF

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.

14 - L'article au format PDF

L'article au format PDF.