PC SOFT

GRUPOS DE DISCUSSÃO PROFISSIONAL
WINDEVWEBDEV e WINDEV Mobile

Inicio → WINDEV 2024 → Méthode discutable
Méthode discutable
Iniciado por Jean-Michel, ago., 14 2017 9:12 AM - 21 respostas
Membro registado
834 mensagems
Popularité : +13 (13 votes)
Publicado em agosto, 14 2017 - 9:12 AM
Bonjour,
2 personnes ne sont pas d’accord sur une façon de programmer, plus exactement la façon d’écrire ou de modifier un enregistrement dans un fichier.
Afin de les mettre d’accord, j’ai eu l’idée de poster les deux différentes méthodes sur ce forum.
Si vous avez le temps, merci de dire ce que vous en pensez.
Méthode A ou Méthode B et pourquoi ?

Énoncè :
L’écran de création/Modification client reçoit un paramètre.
Il reçoit l’ID du client si c’est une modification ou zéro si c’est une création.
Le paramètre est P_IDclient.
A la validation de la fiche client :

Méthode A
HLitRecherche(Client,IDClient,P_IDclient,hIdentique)
Client.Nom = sai_nom
Client.prenom = sai_prénom
Client.pays = sai_pays
(OU EcranVersFichier(FEN_client,Client)) SI zones rattachées

SI P_IDclient = 0 ALORS
HAjoute(Client)
SINON
HModifie(Client)
FIN


Méthode B
HLitRecherche(Client,IDClient,P_IDclient,hIdentique)
SI P_IDclient = 0 ALORS
Client.Nom = sai_nom
Client.prenom = sai_prénom
Client.pays = sai_pays
(OU EcranVersFichier(FEN_client,Client)) SI zones rattachées

HAjoute(Client)
SINON
Client.Nom = sai_nom
Client.prenom = sai_prénom
Client.pays = sai_pays
(OU EcranVersFichier(FEN_client,Client)) SI zones rattachées

HModifie(Client)
FIN


Merci pour vos commentaires.
J.Michel

--
Synchronize Systems International LTD
Développement d'outils de gestion

Environnements AS400 – Windows
Langages GAP III – CL – Visual Basic - Visual Adélia - Adélia - Windev
http://www.cashpower.fr/

Bangkok / Pattaya
Membro registado
939 mensagems
Popularité : +66 (68 votes)
Publicado em agosto, 14 2017 - 9:22 AM
bonjour,

perso je ferais plutôt :

SI P_IDClient=0 ALORS
HRAZ(client)
SINON
HLitRecherche(Client,IDClient,P_IDclient,hIdentique)
// Contrôle d'accès sur l'enreg à rajouter ainsi que gestion verrou
// si HDejaBloque() ou pas htrouve() alors
// // Message d'info...
// fin
FIN
Client.Nom = sai_nom
Client.prenom = sai_prénom
Client.pays = sai_pays
(OU EcranVersFichier(FEN_client,Client)) SI zones rattachées

HEnregistre(Client)
Publicado em agosto, 14 2017 - 9:41 AM
Pour moi clairement pas la méthode B, à cause de la redondance de code.
Mais sur la méthode A, un htrouve serait plus relevant qu'un P_IDClient=0
Membro registado
1.923 mensagems
Popularité : +53 (65 votes)
Publicado em agosto, 14 2017 - 9:53 AM
Bravo Christophe !
Match nul.

--
Bon dev,
Jean-Pierre
Membro registado
281 mensagems
Popularité : +24 (26 votes)
Publicado em agosto, 14 2017 - 1:49 PM
Bonjour,

Pour mon cas, aucune des deux méthodes ne me conviennent :)

C'est pour moi une hérésie de faire appel à des fonctions comme HLitRecherche() qui font des requêtes à la base complètement inutiles alors que l'ont peux faire bien plus propre et moins gourmand en ressources en exécutant soit meme du code SQL.
Publicado em agosto, 14 2017 - 1:58 PM
Je trouve le HEnregistre un peu cavalier aussi. Ne pas maîtriser s'il faut ajouter ou modifier un enregistrement me paraît quelque peu hasardeux...
Membro registado
2.566 mensagems
Popularité : +222 (260 votes)
Publicado em agosto, 14 2017 - 2:59 PM
Bonjour,

Perso je ferai ça:
SI PAS HLitRecherche(Client,IDClient,P_IDclient,hIdentique) ALORS HRAZ(Client)
Client.Nom = sai_nom
Client.prenom = sai_prénom
Client.Pays = sai_pays
(OU EcranVersFichier(FEN_client,Client)) SI zones rattachées
HEnregistre(Client)


Quant à l'écriture de sql, sans méchanceté aucune Damien, pour ce petit bout de code le temps gagné est tellement infinitésimal qu'il me semble être une perte de temps.

--
Cordialement,

Philippe SAINT-BERTIN
Géode Informatique
Membro registado
281 mensagems
Popularité : +24 (26 votes)
Publicado em agosto, 14 2017 - 4:49 PM
Philippe SB a écrit :
Bonjour,

Perso je ferai ça:
SI PAS HLitRecherche(Client,IDClient,P_IDclient,hIdentique) ALORS HRAZ(Client)
Client.Nom = sai_nom
Client.prenom = sai_prénom
Client.Pays = sai_pays
(OU EcranVersFichier(FEN_client,Client)) SI zones rattachées
HEnregistre(Client)


Quant à l'écriture de sql, sans méchanceté aucune Damien, pour ce petit bout de code le temps gagné est tellement infinitésimal qu'il me semble être une perte de temps.

--
Cordialement,

Philippe SAINT-BERTIN
Géode Informatique


Dites cela à un de mes clients qui à des sites à travers le monde et des connexions avec de grosses latence ;) La moindre économie d'aller/retour est importante et il y a aussi le fait de maitriser ce que l'ont fait !
Membro registado
2.566 mensagems
Popularité : +222 (260 votes)
Publicado em agosto, 14 2017 - 6:59 PM
Il y a toujours des cas particuliers mais il ne faut pas faire d'une exception une généralité. Dans 95% des cas, mon code est plus court et suffisamment efficace.

--
Cordialement,

Philippe SAINT-BERTIN
Géode Informatique
Membro registado
190 mensagems
Popularité : +21 (23 votes)
Publicado em agosto, 14 2017 - 8:33 PM
Bonjour

Il y a différentes méthodes avec des avantages/inconvénients,
Idéalement il faut que ce soit concis, facile à lire, rapide d'accès, évolutif.

Pour faire simple, nous avons opté pour 2 paramètres dans la fenêtre de consultation d'une fiche.
Un paramètre d'action : Visualisation / Modification/ Création/ et même copie d'enregistrement / Suppression
Et un paramètre ID fiche.
Avoir uniquement un ID (Création si ID=0, modif sinon) ne nous suffisait pas pour ce qu'on voulait faire.

A l'initialisation de la fenêtre on lit la fiche si on a un ID, (sinon HRAZ)
Selon l'action on active le menu adéquat
A la validation (ou abandon) de la fenêtre, selon l'action, on réalise le traitement.
De plus, ça nous permet en fonction du type d'utilisateur, d'autoriser ou non l'action grâce à une table des droits.

C'est bien d'échanger sur différentes méthodes de saisie.
Après ça dépend les cas métiers rencontrés.
Membro registado
30 mensagems
Popularité : +3 (3 votes)
Publicado em agosto, 15 2017 - 6:16 PM
Bonjour

déjà quand une recherche échoue et que l'on doit faire un ajout, je fais toujours un hraz(dufichier)

SI PAS HLitRecherche(Client,IDClient,P_IDclient,hIdentique) ALORS
HRAZ(Client)
FIN
Client.Nom = sai_nom
Client.prenom = sai_prénom
Client.pays = sai_pays
(OU EcranVersFichier(FEN_client,Client)) SI zones rattachées

SI Client..NouvelEnregistrement ALORS
HAjoute(Client)
SINON
HModifie(Client)
FIN


Je ferme aussi toujours un SI par un FIN car j'ai eu des galères sans nom avec l'indentation et les SI condition ALORS action sur la même ligne.

Même si je trouve le HEnregistre très séduisant, je préfère maitriser l'opération d'accès au fichier lors du HAjoute et HModifie.

Après je suis plutôt d'accord avec Damien, il est préférable de passer par des requêtes SQL mais ce n'est pas le propos de ce topic.


Thierry
Publicado em agosto, 16 2017 - 11:03 AM
Philippe SB a présenté l'énoncé suivant :
Bonjour,

Perso je ferai ça:
SI PAS HLitRecherche(Client,IDClient,P_IDclient,hIdentique) ALORS
HRAZ(Client)
Client.Nom = sai_nom
Client.prenom = sai_prénom
Client.Pays = sai_pays
(OU EcranVersFichier(FEN_client,Client)) SI zones rattachées
HEnregistre(Client)


Quant à l'écriture de sql, sans méchanceté aucune Damien, pour ce petit bout
de code le temps gagné est tellement infinitésimal qu'il me semble être une
perte de temps.


+1
Pour une lecture, H... pour un ensemble SQL....

a plus

--
-------------------------------------------------------------
www.ctc-soft.com
Gestion biblo-documentaire (free-share)
Comptabilité shareware
Logiciels de Gestion de saisie terrain
Spécialisé Tournées de boulangers
-------------------------------------------------------------
Membro registado
96 mensagems
Popularité : +18 (20 votes)
Publicado em agosto, 16 2017 - 3:34 PM
Bonjour,

Aucune des deux méthodes ne me parait correct, mais si je devais en choisir une, ce serait la première, car comme déjà dit précédemment, il y a une redondance de code.

Lorsqu'on effectue le HLitRecherche (j'ai une préférence pour le HLitRecherchePremier plutôt que d'utiliser hIdentique), il faut vérifier si l'on trouve l'enregistrement. Si on ne le trouve pas, il faut gérer l'erreur.
Idem lorsqu'on enregistre, il faut gérer l'erreur si l'enregistrement échoue.

Si on mélange la création et la modification dans le même code, je trouve que le HEnregistre permet de diminuer la quantité de code. Si on distingue les deux cas (deux procédures distinctes par exemple), il faut utiliser HAjoute dans le cas d'un ajout et HModifie dans le cas d'une modification. Cela protège le code car on ne peut pas faire d'ajout avec un HModifie (Identifiant nul) et une modification avec le HAjoute (erreur de doublon).

NouvelEnregistrement est un booléen
EnregistrementTrouvé est un booléen

NouvelEnregistrement = (P_IDclient = 0) // Utiliser une variable est plus parlant qu'une comparaison
SI NouvelEnregistrement ALORS
HRAZ(Client)
SINON
EnregistrementTrouvé = HLitRecherche(Client, IDClient, P_IDclient, hIdentique)
SI PAS EnregistrementTrouvé ALORS
// Gestion de l'erreur
// Il faut prévenir l'utilisateur et gérer l'erreur car on se trouve dans un cas interdit. L'enregistrement a disparu ! Ce n'est pas anodin
// Dans tous les cas, le traitement doit s'arrêter ici
RENVOYER Faux OU RETOUR
FIN
FIN

EcranVersFichier(...) // Ou assignation des champs manuellement

SI PAS HEnregistre(Client) ALORS
// Gestion de l'erreur
// En cas d'erreur, il faut prévenir l'utilisateur et gérer l'erreur. Au pire des cas, on logge l'erreur.
FIN


En règle général, je place ce genre de code dans une procédure globale. Je gère les erreurs par des exceptions (ou dernièrement avec des retours de valeurs multiples avec le message d'erreur en deuxième paramètre). L'alimentation des rubriques du fichier se fait par plusieurs paramètres ou par une structure passée en paramètre (La nouvelle syntaxe des paramètres nommés de procédure est très pratique pour cela aussi).
En procédant ainsi, je peux utiliser ma procédure dans les fenêtres mais aussi dans des traitements automatisés.

Ce qui donnerait ceci :

Procedure ClientEnregistrer(pIdClient est un entier, pNom est chaîne, pPrénom est chaîne, pPays est chaîne, ...)

NouvelEnregistrement est un booléen
EnregistrementTrouvé est un booléen

NouvelEnregistrement = (pIdClient = 0) // Utiliser une variable est plus parlant qu'une comparaison
SI NouvelEnregistrement ALORS
HRAZ(Client)
SINON
EnregistrementTrouvé = HLitRecherche(Client, IDClient, pIdClient, hIdentique)
SI PAS EnregistrementTrouvé ALORS
RENVOYER (Faux, "Le client n'existe pas. Impossible de le modifier.")
FIN
FIN

Client.Nom = pNom
Client.prenom = pPrénom
Client.pays = pPays

Client.Adresse = pAdresseClient
...

EnregistrementEffectué est un booléen = HEnregistre(Client)
SI EnregistrementEffectué ALORS
RENVOYER (Vrai, "")
SINON
RENVOYER (Faux, HErreurInfo())
FIN


// Et lorsque j'appelle mon code
EnregistrementEffectué est un booléen
MsgErreur est une chaîne
(EnregistrementEffectué, MsgErreur) = ClientEnregistrer(P_IDclient, sai_nom, sai_prénom, sai_pays)
SI PAS EnregistrementEffectué ALORS
Erreur("Erreur lors de l'enregistrement de la fiche client.", MsgErreur)
FIN


J'espère que cela donnera l'inspiration à tes collègues.

Bon code !

--
Johjo aka Jonathan Laurent

Mon blog : http://blog.ytreza.org
Twitter : @Johjo07
Mensagem modificada, agosto, 16 2017 - 3:36 PM
Membro registado
834 mensagems
Popularité : +13 (13 votes)
Publicado em agosto, 17 2017 - 5:50 AM
On ne pensait pas recevoir autant de commentaires.
Cela a été un réel plaisir de lire vos commentaires et critiques constructives sur ce petit morceau de code de type école.

A force de les entendre se disputer pour un "si" et un "tantque", j'ai voulu leur démontrer, qu'il n'y a pas qu'une seule façon d'écrire mais plusieurs et qui fonctionnent.
Grace à vous, et à ce forum, pari réussi.

En ce qui me concerne, les 2 codes sont bons avec une légère amélioration.
Du moment que cela fonctionne et que le code est écrit clairement afin qu'un débutant puisse le comprendre, pour la maintenance.......

A moi de jouer :
HLitRecherche(client,IDclient,P_idclient,hIdentique)
TANTQUE HErreurBlocage() = Vrai
HLitRecherche(client,IDclient,P_idclient,hIdentique + hBlocageLectureEcriture)
FIN
SI PAS HTrouve(client) ALORS HRAZ(client)

client.nom = SAI_nom
client.prenom = SAI_prenom
client.Pays = SAI_pays

SI PAS HTrouve(client) ALORS
HAjoute(client)
SINON
HModifie(client)
FIN

HDébloqueNumEnr(client)


Un grand merci à vous tous et Bon Dev..........................

--
Synchronize Systems International LTD
Développement d'outils de gestion

Environnements AS400 – Windows
Langages GAP III – CL – Visual Basic - Visual Adélia - Adélia - Windev
http://www.cashpower.fr/

Bangkok / Pattaya
Membro registado
96 mensagems
Popularité : +18 (20 votes)
Publicado em agosto, 17 2017 - 8:29 AM
Je pense qu'il faudrait rajouter une temporisation (multitache par exemple) dans le tantque. Si l'enregistrement est bloqué par un autre poste, le programme va partir dans une boucle infinie qui prendra tout le processeur.

--
Johjo aka Jonathan Laurent

Mon blog : http://blog.ytreza.org
Twitter : @Johjo07
Membro registado
834 mensagems
Popularité : +13 (13 votes)
Publicado em agosto, 17 2017 - 2:19 PM
Surtout pas Johjo et cela ralentirait le process inutilement. Les enregistrements sont toujours débloqués à la fin de la procédure.
On utilise ce procédé dans la mise à jour des stock. Il arrive très souvent que plusieurs postes fassent une vente du même article au même moment, la procédure lit l'enregistrement du stock en bloquant, fais un négatif, écrit le nouveau stock et libère l'enregistrement. Grace à cette boucle, il attend que le 1er finisse pour continuer. Cela ne dure que quelques millisecondes. De plus, des mouvements et des approvisionnements de stocks sont également fait en même temps par le stock central.
Plus de 4.000 transactions toutes les nuits.
J'ai fait un test en mettant 2 pc en réseau qui vendent le même article toutes les 0,x secondes pour l'un et 0,x1 seconde pour l'autre. Au bout de peu de temps il y a de multiples accès concurrentiel. En mettant un "trace" j'ai pu suivre et c'est parfait.

--
Synchronize Systems International LTD
Développement d'outils de gestion

Environnements AS400 – Windows
Langages GAP III – CL – Visual Basic - Visual Adélia - Adélia - Windev
http://www.cashpower.fr/

Bangkok / Pattaya
Membro registado
96 mensagems
Popularité : +18 (20 votes)
Publicado em agosto, 17 2017 - 8:37 PM
Tout dépend du contexte dans lequel on se trouve.

Tout d'abord, je me méfie toujours d'une boucle sur lequel je ne maîtrise pas la sortie. Je met toujours en place une option de sortie avec gestion de l'erreur. Dans un monde parfait, on est sûr de sortir de la boucle. Si ne je ne suis pas sûr à 100%, j'envisage une autre sortie. Dans le cas présent, s'il y a un blocage sur l'enregistrement qui se fait en dehors de cette procédure et pour une raison quelconque, le blocage ne se défait pas (on n'est jamais à l'abri d'un bug), la boucle ne se terminera jamais.

Dans le cas présent, si l'on part en boucle infinie, un des cœurs du processeur sera mis à genou. Si en plus on est sur du HF Client / Serveur, lui faire un HLitRecherche sans temporiser risque de le chatouiller un peu.

Deuxième chose, on est dans le cas d'une fiche de saisie d'un client. En règle générale, on bloque d'une manière ou d'une autre l'enregistrement lié au client lorsqu'on rentre en saisie sur sa fiche. On a tout intérêt à faire cela pour éviter que la fiche soit modifiée par deux personnes. Le blocage de l'enregistrement peut être une des méthodes utilisées.

Dans le cas présent, soit le blocage n'est pas nécessaire car déjà fait au préalable car on a ouvert la fiche client, soit on est dans un traitement automatique (avec des champs de saisie, peu probable), et dans ce cas, la fiche client peut avoir été laissée ouverte sur un autre poste.

Dans le contexte de mise à jour de vos ventes, vous êtes dans un processus automatique (pas de bug due à l'interface chaise / clavier) et vous avez fait en sorte d'avoir un process qui ne génère pas d'erreur (ou bien vous débloquez les enregistrements en cas d'erreur). Il est normal que ça marche car vous semblez tout contrôler dans votre environnement (et ça, c'est une bonne chose).

Petit détail pour compléter votre exemple, je mettrai aussi le blocage dans la première lecture car s'il n'y a pas d'erreur de blocage, l'enregistrement ne sera pas bloqué.

Bon dev à vous aussi !

--
Johjo aka Jonathan Laurent

Mon blog : http://blog.ytreza.org
Twitter : @Johjo07
Membro registado
834 mensagems
Popularité : +13 (13 votes)
Publicado em agosto, 18 2017 - 7:24 AM
Joho,
Concernant la fiche de saisie d'un client, je vous donne raison, j'ai mis ce code de blocage un peu inutilement par réflexe.
Par contre, dans l'exemple de mon batch, je ne vois comment procéder autrement, ce n'est pas plus bête que ça.
Si vous avez un exemple, je suis preneur car il faut bien qu'il soit mis en attente avant de traiter......
Concernant le petit détail, le blocage est également dans la 1ere lecture, mais n'apparait pas dans mon exemple, oups......

--
Synchronize Systems International LTD
Développement d'outils de gestion

Environnements AS400 – Windows
Langages GAP III – CL – Visual Basic - Visual Adélia - Adélia - Windev
http://www.cashpower.fr/

Bangkok / Pattaya
Membro registado
96 mensagems
Popularité : +18 (20 votes)
Publicado em agosto, 18 2017 - 9:58 AM
Pour votre batch, je pense que votre méthode est bonne.

Quand je vous propose une temporisation et une option de sortie (basé sur le nombre d'itération ou sur une certaine durée), c'est plus de la prévention qu'autre chose. En temps normal, il y a de forte chance qu'on n'y rentre même pas ou qu'on en sorte dès la première itération.

Les accès concurrents sont vraiment compliqués à gérer. Avec un blocage sur le fichier, ce sera extrêmement rare, mais on peut tomber sur un processus qui souhaite bloquer le fichier, mais il y aura toujours un autre processus pour le bloquer avant lui. L'idéal, ce serait d'avoir une file (premier entré, premier traité) pour gérer les blocages et l'idéal pour cela, c'est l'utilisation des sémaphores associée au blocage Hyperfile.

Mais lorsque le HModifie s'effectue sur plusieurs postes différents, on ne peut pas utiliser les sémaphores. Il ne reste donc que le blocage Hyperfile.

On pourrait avoir une application serveur qui s'occupe de faire les modifications, et dans ce cas, on peut utiliser les sémaphores avec le blocage mais cela revient à casser toute l'architecture d'une application qui tourne correctement.

Donc, à mon avis, votre méthode est la bonne.

--
Johjo aka Jonathan Laurent

Mon blog : http://blog.ytreza.org
Twitter : @Johjo07
Membro registado
834 mensagems
Popularité : +13 (13 votes)
Publicado em agosto, 19 2017 - 11:05 AM
Johjo ,
J'ai voulu voir votre Blog mais ça marche pas !!
J'arrive la dessus :




--
Synchronize Systems International LTD
Développement d'outils de gestion

Environnements AS400 – Windows
Langages GAP III – CL – Visual Basic - Visual Adélia - Adélia - Windev
http://www.cashpower.fr/

Bangkok / Pattaya
Membro registado
96 mensagems
Popularité : +18 (20 votes)
Publicado em agosto, 20 2017 - 7:47 PM
Bonjour,

merci pour cette info, mon serveur personnel semble être tombé. Dès que je rentre de weekend, je répare ça !

--
Johjo aka Jonathan Laurent

Mon blog : http://blog.ytreza.org
Twitter : @Johjo07
Membro registado
1.623 mensagems
Popularité : +100 (114 votes)
Publicado em agosto, 21 2017 - 3:42 PM
SI P_IDCLIENT = 0 ALORS
HRAZ(Clients)
AffectationValeurs
SI PAS HAjoute(Clients) ALORS
Erreur("Erreur lors de l'ajout du client")
SINON
P_IDCLIENT = Clients.Idclient // La fenetre passe du coup en mode edition apres la création
FIN
SINON
HLitRecherchePremier(Cients,IDclient,P_IDclient)
SI HTrouve(clients) ALORS
AffectationValeurs
SI PAS HModifie(Clients) ALORS
Erreur("Un erreur est survenue de la modification du client.")
FIN
SINON
Erreur("Une erreur est survenue de la modification du client.. Client non trouve")
FIN
FIN

PROCEDURE INTERNE AffectationValeurs
clients.nom = SAI_Nom //etc...
FIN
Mensagem modificada, agosto, 21 2017 - 3:44 PM