← Retourner à la page principale



Conseils et recommandations générales en WLangage® *

* Les marques "PC SOFT®" et "WINDEV®" sont déposées par la société PC SOFT®.

Charte de programmation
Eléments de projet
Procédures
Variables
Instructions
Fonctions WLangage®
Réduire le code source à maintenir
Respecter l'ordre des instructions
Etre rigoureux
Autres informations
La charge mentale


Charte de programmation

Privilégier la charte de programmation livrée en standard par PCSOFT®. Elle est acceptée et utilisée par la majorité des développeurs en WLangage®.
La convention de nommage et le préfixage permet de connaître rapidement le type d'éléments, ainsi que le type de variable et sa portée.

// Quelques exemples : 
sNom // Le préfixe s correspond à une variable de type chaîne 
nAge // Le préfixe n correspond à une variable de type entier 
rTVA // Le préfixe r correspond à une variable de type réel 
dNaissance // Le préfixe d correspond à une variable de type date 
FEN_TABLE_SOCIETE // Le préfixe FEN_ correspond à un élément de type fenêtre 
gtaPersonnel // Le préfixe gta correspond à une variable de type tableau associatif avec une portée globale 
gm_sCheminFicherDll // Le préfixe gm_s correspond à un membre d'une classe de type chaîne avec une portée globale 

Pour consulter la charte de programmation :

  1. aller dans la description du projet
  2. cliquer sur l'onglet "Options"
  3. dans le chapitre "Charte de programmation"
  4. cliquer sur le bouton "Editer la charte"


Eléments de projet

Nommer les éléments de projet de manière simple et explicite dans l'"esprit" de la nomenclature PCSOFT®.
Si la langue du code est en français alors utiliser des noms en français pour tous les éléments du projet (fenêtres, états, champs, variables, procédures, classes, ...).



Procédures

Typer les valeurs de retour de toutes les procédures.

Privilégier les procédures internes si leur exécution n'est faite que depuis un seul code appelant.

Préfixer les appels aux procédures globales par le nom de la collection de procédures.

Rédiger le nom des fonctions avec un verbe à l'infinitif. L'objectif est que le nom de la fonction puisse donner suffisamment d'informations pour éviter d'aller lire le code.
Une fonction doit faire une seule chose.
Son code idéal doit être séquentiel, lisible de haut en bas.
Le nombre de ses paramètres doit être réduit (moins de 4).


Paramètres de procédures

Utiliser les types de variables énumérations et combinaisons dans les paramètres de procédures. Ceci afin d'éviter des erreurs et de clarifier le code, de fiabiliser l'appel aux procédures et de faciliter la maintenance.

Nom de fenêtre dans l'appel d'une procédure :

UneProcédure("NomFenêtre")

Doit s’écrire :

UneProcédure(NomFenêtre..Nom)

S'il y a un renommage du nom de la fenêtre, l'éditeur changera automatiquement le nom dans l’appel de la procédure alors que dans le premier code, le développeur doit penser à modifier le nom de la fenêtre entre guillemets.

Ne pas oublier l'attributs d'extension dans la déclaration de la procédure. Ceci afin de faciliter l'appel à la procédure :

PROCÉDURE UneProcédure(LOCALE sNomFenêtre est une chaîne <nom de fenêtre>)
PROCÉDURE UneProcédure(LOCALE sNomEtat est une chaîne <nom d'état>)


Variables

Typer toutes les variables selon leur contenu. Ne pas oublier également les paramètres des procédures.

Eviter la négation dans le nom d'une variable de type booléen.

Limiter le nombre de variables globales.

Nommer les constantes en majuscules.

Préfixer les utilisations des variables globales par le nom de la collection de procédures.

Une variable doit avoir un et un seul rôle dans le code, il faut proscrire les variables qui servent à stocker différentes données.



Instructions

Instruction SORTIR

Éviter d'utiliser l'instruction SORTIR dans les boucles. Ceci afin d'améliorer la lisibilité du code et visualiser rapidement toutes les conditions de sortie de la boucle.

Remplacer un couple (POUR , SORTIR) par une boucle TANTQUE.
A titre d'exemple, le premier code ci-dessous peut être remplacé par le deuxième code :

tabTP est un tableau de TâcheParallèle
bSortir est un booléen = Faux
TANTQUE PAS bSortir
    bSortir = Vrai
    POUR i = tabTP..Occurrence _À_ 1 _PAS_ -1
        SI PAS tabTP[i]..Terminée ALORS
            bSortir = Faux
            Temporisation(25, tempoSourisEtClavier)
            SORTIR
        FIN
    FIN
FIN
tabTP est un tableau de TâcheParallèle
nIndice est un entier = 1
TANTQUE (nIndice = 1 À tabTP..Occurrence)
    SI tabTP[nIndice]..Terminée ALORS
        nIndice++
    SINON
        Temporisation(25, tempoSourisEtClavier)
    FIN
FIN

Instruction SELON CAS

Dans une instruction SELON, toujours ajouter le mot-clé AUTRE CAS à la fin.
Et si vous êtes sûr qu'il n'y aura aucun passage dans ce traitement alors y ajouter un point d'arrêt par programmation avec le mot-réservé STOP .
Cela permet de s'arrêter lors du débogage du projet et pourquoi pas d'ajuster l'instruction SELON en conséquence.

SELON nAge
 	CAS 0 À 18 : Trace("Mineur") 
 	CAS 19 À 150 : Trace("Majeur") 
 	AUTRE CAS : 
 		STOP // Ne devrait jamais s'arrêter ici
FIN


Fonctions WLangage®

En WLangage®, il existe plusieurs fonctions qui renvoient un résultat identique. N'utiliser qu'une seule et uniquement qu'une seule de ces fonctions.

Le résultat de ces fonctions sont identiques mais une recherche dans le code source obligerait et pénaliserait les développeurs à effectuer plusieurs recherches plutôt qu'une seule.
Voici une liste d'exemples :

Utiliser ces fonctions Ne pas utiliser
DateSys() DateDuJour()
HeureSys() Maintenant()
DateVersJourDeLaSemaine() DateVersJour()
API() Appel32()
FenRepeint() MultitâcheRepeint()
Ferme(<NomFenêtre>) FenEtat(<NomFenêtre>, Inexistant)
DonneFocusEtRetourUtilisateur() RepriseSaisie()
gValeurMémorisée() gLien()
ChaîneVersNumérique() Val()
fRepExiste() fRépertoireExiste()
fRepTemp() fRépertoireTemp()
PROCÉDURE FONCTION
... ...



Réduire le code source à maintenir

S'il y a moins de code alors il y aura moins de bugs. Le code source sera moins long à comprendre et plus facile à lire et à maintenir.
C'est un fait reconnu que le code est lu beaucoup plus souvent qu'il n'est écrit. C'est pourquoi sa lisibilité est essentielle.
Cependant réduire et optimiser la taille du code ne signifie pas nécessairement que le code sera plus rapide.

A titre d'exemple, le premier code ci-dessous peut être réduit par le deuxième :

bEstFichierTexte est un booléen
SI (fFichierExiste(sUnFichier) = Vrai) ALORS
    SI (fExtraitChemin(sUnFichier, fExtension) = ".txt") ALORS
        bEstFichierTexte = Vrai
    SINON
        bEstFichierTexte = Faux
    FIN
SINON
    bEstFichierTexte = Faux
FIN

ST_Rectangle est une Structure
    nX est un entier
    nY est un entier
    nLargeur est un entier
    nHauteur est un entier
FIN
stUnRectangle est un ST_Rectangle
stUnRectangle.nX = 0
stUnRectangle.nY = 0
stUnRectangle.nLargeur = 0
stUnRectangle.nHauteur = 0

ST_Point est une Structure
    nX est un entier
    nY est un entier
FIN
stUnPoint est un ST_Point
stUnPoint.nX = 0
stUnPoint.nY = 0

tabEntier est un tableau de entier = [1, 2, 3, 4, 5]
nSomme est un entier
POUR i = 1 _À_ tabEntier..Occurrence
    nSomme += tabEntier[i]
FIN
bEstFichierTexte est un booléen
bEstFichierTexte = (fFichierExiste(sUnFichier) _ET_ (fExtraitChemin(sUnFichier, fExtension) = ".txt"))

UnRectangle est un Rectangle
VariableRAZ(UnRectangle)

UnPoint est un Point
VariableRAZ(UnPoint)

tabEntier est un tableau de entier = [1, 2, 3, 4, 5]
nSomme est un entier = Somme(tabEntier)


Réduire le code source à maintenir (bis)

Il existe différentes méthodes pour forcer un champ de saisie de type "Texte" à être en majuscule :

-Méthode n°1 : par la fenêtre des 7 onglets, dans "Masque de saisie" :
choisir "Majuscules" ou "TOUT EN MAJUSCULES"

-Méthode n°2 : par programmation, dans le code d'intialisation du champ :
MoiMême..MasqueSaisie = maskMajus

-Méthode n°3 : par programmation, à chaque modification du champ :
nCurseur est un entier = MoiMême..Curseur
MoiMême = Majuscule(MoiMême)
MoiMême..Curseur = nCurseur

-Méthode n°4 : par programmation, à chaque modification du champ :
nCurseur est un entier = MoiMême..Curseur
sEnMajuscule est une chaîne 
POUR i = 1 _À_ Taille(MoiMême)
    bSortir est un booléen
    POUR j = 97 _À_ 122
        SI (MoiMême[[i]] = Caract(j)) ALORS
            bSortir = Vrai
            sEnMajuscule += Caract(j-32)
        FIN
    FIN
    SI PAS bSortir ALORS
        POUR j = 224 _À_ 253
            SI (MoiMême[[i]] = Caract(j)) ALORS
                bSortir = Vrai
                sEnMajuscule += Caract(j-32)
            FIN
        FIN
    FIN
    SI PAS bSortir ALORS
        sEnMajuscule += MoiMême[[i]]
    FIN
FIN
MoiMême = sEnMajuscule
MoiMême..Curseur = nCurseur

-Méthode n°5 : par programmation, dans le code d'entrée du champ :
// Forcer la majuscule du clavier si celle-ci n'est pas déjà en majuscule
SI PAS API("USER32", "GetKeyState", 20) ALORS // 20 = VK_CAPITAL
    AppelDLL32("USER32.dll", "keybd_event", 20, 0, 0, 0)
    AppelDLL32("USER32.dll", "keybd_event", 20, 0, 2, 0)
FIN
Et dans le code de sortie du champ :
// Forcer la minuscule du clavier si celle-ci n'est pas déjà en minuscule
SI API("USER32", "GetKeyState", 20) ALORS // 20 = VK_CAPITAL
    AppelDLL32("USER32.dll", "keybd_event", 20, 0, 0, 0)
    AppelDLL32("USER32.dll", "keybd_event", 20, 0, 2, 0)
FIN

Tout ça pour insister sur le fait qu'il existe différentes méthodes pour arriver au même résultat.
Et que certains méthodes sont bien meilleures que d'autres.
Pour ma part, je conseille l'utilisation des 2 premières méthodes car les autres présentes certains inconvénients.



Respecter l'ordre des instructions

Dans le code ci-dessous la trace affichera "30/04/2019" au lieu de "31/04/2019" souhaité.

dTemp est une Date = "20120923"
dTemp..Jour = 31 // Cette ligne est à déplacer avant la fonction Trace()
dTemp..Mois = 4
Trace(DateVersChaîne(dTemp, "JJ/MM/AAAA"))


Etre rigoureux

L'exécutation du code ci-dessous est correcte, c'est-à-dire il donne le bon résultat quelque soit la réponse de l'utilisateur :

SI (OuiNon("Etes-vous un humain ?") = Vrai) ALORS
    Info("L'utilisateur a dit Oui.")
SINON
    Info("L'utilisateur a dit Non.")
FIN

Cependant la documentation précise que le résultat de la fonction OuiNon() est une des deux constantes Oui ou Non.
Alors avec ce code rien de trop problématique mais avec le code ci-dessous, le résultat n'est pas celui attendu. Le traitement est bloqué dans une boucle infinie. Mais pourquoi ?

nChiffreDeux est un entier

PROCÉDURE INTERNE piInit()
    ThreadPause(100)
    nChiffreDeux = 2
FIN

ThreadExécute("piInit", threadNormal, piInit)
TANTQUE (ThreadEtat("piInit") <> Inexistant)
    Temporisation(25, tempoSourisEtClavier)
FIN
Trace( nChiffreDeux )

Pour revenir dans un état cohérent, remplacer Inexistant par threadInexistant.



Autres informations

Il faut garder à l'esprit que coder en langage WL5® ne signifie pas que le développeur ne doit pas prendre en compte les problématiques mémoire lorsqu'il programme. En effet, une vraie prise en compte est nécessaire même si le raisonnement est différent de ce qu'il peut-être dans d'autres langages.
Les outils de PCSOFT® vous permettent donc de pratiquement tout faire. Pour certains, il est tentant de considérer qu'ils sont suffisants et qu'il ne faille pas aller voir ailleurs de temps à autre. C'est une grave erreur ! En effet, bien que ces outils permettent de tout faire, cela ne signifie pas qu'ils soient la meilleure solution dans tous les cas. Ainsi chaque langage de programmation présente des avantages et des inconvénients en fonction du type d'application à implémenter et du domaine cible.
Avec moins de lignes de code, les développeurs ont plus de temps à consacrer au besoin même du métier. Le développeur peut se concentrer sur les besoins utilisateurs à forte valeur ajoutée.
L'une des forces du WLangage® est sa simplicité. Cependant comme n'importe quel langage de programmation, WLangage® réserve aussi sa part de subtilités que l'on saisit avec l'expérience.



La charge mentale

Un développeur a 2 choses en main : le problème qu'on lui demande de résoudre et la technique qui lui permet de le résoudre.
On cherche à avoir la technique la plus efficace afin de se concentrer sur le problème.
L'objectif : c'est le problème. La technique n'est qu'un moyen.
Donc il existe des outils pour simplifier la vie des développeurs, pour rendre la partie technique plus efficace. C'est tout naturel.
Seulement ces outils censés simplifier la vie ajoutent en réalité une "charge mentale" aux développeurs.
Cette charge mentale est la connaissance/maitrise de ces outils tels que GIT, Docker, Kubernetes, les différents frameworks, ...