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
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, ...).
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).
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>)
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.
É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
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
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 |
... | ... |
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)
MoiMême..MasqueSaisie = maskMajus
nCurseur est un entier = MoiMême..Curseur
MoiMême = Majuscule(MoiMême)
MoiMême..Curseur = nCurseur
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
Et dans le code de sortie 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
// 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
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"))
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.
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.
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, ...