8723 sujets

Développement web côté serveur, CMS

Bonsoir,

Dans l'idéal je voudrais recueillir quelques avis pour savoir si je suis de bonnes pratiques car, dans mon périple de programmation from scratch pour un backend, en tant qu'amateur dans mon coin, parfois je me sens vraiment comme un navigateur en solitaire...

Il s'agit ici d'une optimisation pour une base de donnée sous PostgreSQL, plus spécifiquement il s'agit du remplissage automatique des colonnes en lien avec une date de révision :
CREATE TABLE __account (
  _id INT GENERATED BY DEFAULT AS IDENTITY,
  [...]
  _date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- date de création
  _date_modified TIMESTAMP NULL, -- date de révision
  [...]
  PRIMARY KEY (_id),
  FOREIGN KEY (_author_id) REFERENCES __person(_id) ON DELETE SET NULL    -- CONSTRAINT __post__person_fkey
);

Dans un premier temps j'ai pensé remplir le champ "_date_modified" par une requête SQL à partir de l'application, par exemple, sur un point de terminaison :
UPDATE __account SET _date_modified = CURRENT_TIMESTAMP, _role_name = $2, _language = $3, _media_id = $4 WHERE _id = $1

J'ai eu un petit soucis de formatage de la date, mais avant de corriger le bug et d'avancer plus avant, je me suis dit :
a écrit :
Si ça se trouve, puisque j'arrive à remplir automatiquement la colonne "_date_created" sans passer par l'application, il doit bien y avoir un moyen de faire la même chose pour compléter "_date_modified" seulement sur un UPDATE"...

Bingo, avec un trigger :
CREATE OR REPLACE FUNCTION update_date_modified()
RETURNS TRIGGER AS $$
BEGIN
  NEW._date_modified = CURRENT_TIMESTAMP; -- Mettre à jour _date_modified avec le timestamp actuel
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Et comme la table "__account" n'est pas la seule concernée par ce type de colonne (que, heureusement, par esprit maniaque j'ai dénommé de la même manière partout) je peux appeler la fonction pour tout le monde, bien que cela soit un peu répétitif :
CREATE TRIGGER update_date_modified_trigger__account
BEFORE UPDATE ON __account
FOR EACH ROW
EXECUTE FUNCTION update_date_modified();

CREATE TRIGGER update_date_modified_trigger__post
BEFORE UPDATE ON __post
FOR EACH ROW
EXECUTE FUNCTION update_date_modified();

CREATE TRIGGER update_date_modified_trigger__media
BEFORE UPDATE ON __media
FOR EACH ROW
EXECUTE FUNCTION update_date_modified();

CREATE TRIGGER update_date_modified_trigger__comment
BEFORE UPDATE ON __comment
FOR EACH ROW
EXECUTE FUNCTION update_date_modified();

Pour revenir sur la question initiale : y-a-t-il de meilleures manières de procéder ou c'est OK ? Puis-je faire encore des optimisations de code sur cette fonctionnalité ?
Modérateur
Bonjour,
Olivier C a écrit :
Puis-je faire encore des optimisations de code sur cette fonctionnalité ?
Une seule requête devrait suffire (ou plus exactement faire une boucle pour ne pas réécrire x fois le même code).

Amicalement,
Modifié par parsimonhi (10 Mar 2024 - 04:32)
parsimonhi a écrit :
Une seule requête devrait suffire (ou plus exactement faire une boucle pour ne pas réécrire x fois le même code).

Ah oui j'ai vu ça :
DO $$
DECLARE
  tables TEXT[] := ARRAY['__account', '__post', '__media', '__comment'];
BEGIN
  FOR i IN 1..array_length(tables, 1) LOOP
    EXECUTE format('CREATE TRIGGER update_date_modified_trigger_%I
                    BEFORE UPDATE ON %I
                    FOR EACH ROW
                    EXECUTE FUNCTION update_date_modified()', tables[i], tables[i]);
  END LOOP;
END $$;

Je m'étais défilé car je ne suis pas très à l'aise en SQL et je m'étais dit que pour une relecture ultérieure... non mais en fait ça va.

Si vous avez d'autres suggestions, des considérations sur les perfs ou je ne sais quoi d'autres encore, n'hésitez pas.
Salut Olivier,

Tu as l'intention d'utiliser un système de migrations pour ta BDD ? C'est une bonne pratique sous estimée à mon humble avis. Je t'invite à te renseigner à ce sujet si tu ne connais pas déjà.

Have fun Smiley smile
Merci Anymah,

Oui j'ai l'intention de convertir une table "wp_post" WordPress en table "__post" pour PostgreSQL. Le plus pénible, je pense, sera la conversion des dates. J'aurais voulu aussi récupérer les mots clefs, mais c'est peut-être un peu ambitieux pour moi (au pire ce n'est pas si grave, ça me permettrait de faire le ménage dans les mots clefs au passage, en passant un peu tout en revu).

Sur le web j'ai trouvé une ou deux solutions, plus ou moins bien maintenues et pas forcément simples à installer/configurer (ex : pgloader). Du coup je me dis qu'il serait tout aussi simple d'écrire un petit script personnalisé que je pourrais lancer sur la sauvegarde. Je n'ai pas encore réfléchi à la manière de procéder :
- les colonnes de la table que je garde ou non,
- sous quel environnement j'écris le script (plutôt node.js, python au pire),
- et puis d'abord je passe par un dump SQL ou via un fichier CSV ?
Etc.
Modifié par Olivier C (10 Mar 2024 - 13:39)
Hello !

Je pensais pas à une migration entière de BDD vers une autre. Je pensais aux outils qui permettent de faire du versioning. En gros, l’évolution du modèle de ta BDD est inclus dans ton code source sous la forme de succession de migrations exécutées les unes après les autres. Globalement ça permet d’avoir un meilleur contrôle sur l’état de ta BDD. Ça facilite et sécurise grandement les mises à jours du modèle sur la BDD, aussi bien en développement que pour une mise en production.

Si tu fais du PHP j’ai trouvé Phinx en recherchant rapidement.

Voilà voilà Smiley biggrin
Modifié par Anymah (10 Mar 2024 - 20:21)
En tous les cas, pour ce qui concerne la migration de base de données à base de données (WordPress > PostgreSQL) : vous croyez que j'ai utilisé des scripts hypers compliqués ? Un logiciel spécialisé ? Que dalle : hier soir j'ai fait une grosse séance de copier remplacer dans... Visual Studio Code !

En même temps j'ai été petit joueur : je n'ai gardé que les mots clés et les articles, même pas la relation many to many entre les deux.

Bien sûr, il n'y a pas des millions d'entrées, il y a un peu plus de 1030 articles (toutefois certains d'entre eux sont très volumineux).

Au final je n'ai gardé que quelques colonnes. Je n'avais jamais fait attention mais dans la table des "posts" il y a une colonne pour les redirections 301 qui prend beaucoup de place. Je vois l'utilité, mais je ne garderai pas le principe de cette fonctionnalité pour mon site, même si j'en vois l'intérêt, ça fait vraiment très sale dans la base de données et pour les perfs de toute façon, les redirections... Tant pis pour les redirections 301.

Reste le problème des liens des images et ressources, étant donné que je vais complètement modifier mon système d'upload par rapport à WordPress (bien que je vais m'en inspirer beaucoup).
Modifié par Olivier C (11 Mar 2024 - 08:57)
Salut,

Je vais parler juste de ce point la :
a écrit :
Pour revenir sur la question initiale : y-a-t-il de meilleures manières de procéder ou c'est OK ? Puis-je faire encore des optimisations de code sur cette fonctionnalité ?


Je dirais que c'est à toi de choisir où tu mets "l'intelligence" de ton application.
Tu peux faire énormément de chose en BDD tout comme tu peux en faire autant dans ton code ou repartir entre les 2 (voir même faire "doublon" pour certains trucs en mode ceinture/bretelles).

J'ai l'impression que la "mode" actuellement est plutôt de tout faire dans le code et de ne pas tellement se soucier de ce que fais la BDD (coucou les ORM)

Il y a des avantages et des inconvénients aux différentes approches, du coup je ne sais pas dire si il y en a de meilleurs..
- ORM : on ne se soucis pas de la BDD sous jacente, on comprends globalement ce qui se passe en lisant uniquement le code. Mais on a un mini boite noire au niveau de la bdd, ce qui peut poser des problèmes de perfs difficiles à résoudre.
- BDD : On peut automatiser pas mal de petits détails via des triggers pl/sql et faire des requêtes aux petits oignons pour résoudre les éventuels problèmes de performances sur certains traitements. L’inconvénient c'est qu'en lisant uniquement le code (php ou autre) on ne voit pas toutes les automatisation faites en bdd, ce qui peut produire des comportements improbables et ultra pénible à résoudre quand ça se ne produit que dans certains cas à la marge (souvenirs Smiley bawling )


Et pour la fonctionnalité en elle même, j'ai vu quelques applis que j'ai trouvais plus utile en mettant en place des genre de systèmes "d'historique".
"Plus utile" parce qu'en gros juste savoir que quelque chose à changer à telle date, assez souvent au final on s'en fou un peu Smiley sweatdrop
Alors qu'avoir un historique en mode "à cette date, cette personne à mis cette valeur dans ce champs" stocker dans une table à plus de valeur à mon gout (après ça a un coût en terme d'espace de stockage)
Bonjour Mathieuu,

Effectivement je suis anti-ORM, la raison principale étant que j'avais lu un bouquin entier sur le SQL dans une vie antérieure (coucou Le Site du Zéro) et je ne me voyais pas "rétrograder" sur un truc moins performant et pas forcément moins compliqué au final. Aujourd'hui les app' se veulent sans opinions quand aux BDD, mais moi je veux rester sous PostgreSQL "quoi qu'il en coûte" ! (non, vraiment, je kiffe cette base de données). A la limite, le framework js du moment je m'en moque un peu et même le langage même si, en réalité, je ne me vois pas switcher en raison de l'écosystème que je connais bien maintenant.

Cependant la BDD je ne veux lui faire faire que des choses simples, notamment pour des raisons de performance (ne pas saturer les ressources de la BDD), mais pour l'incrémentation d'une date je trouve ça cool que l'on n'ait pas à s'en occuper pour le moindre truc (sans compter que l'on pourrait oublier), et puis ça évite le risque de ne pas INSERT l'entrée de la même manière partout (même si coucou CONSTRAINT).

Les mises à jour de date, c'est une information qui restera toujours utile à l'utilisateur pour certaines entités (comme un article par exemple). Par contre, pour l'historique, c'est non : pas tellement le problème technique (qui en soit est un défit pour moi), mais plutôt la place que ça prendrait en BDD, effectivement (ou alors un système d'historique sur un nombre d'actions max).

Merci pour ton retour.
Modifié par Olivier C (12 Mar 2024 - 13:06)
A priori ce n'est pas très compliqué techniquement, au lieu de faire un update tu fais un nouvel insert et au lieu d'avoir seulement un id d'article comme clé primaire tu rajoutes un champs numéro de version que tu incrémentes à chaque fois.
( Et sinon tu peux avoir une table supplémentaire qui ne sert que pour l'historique).
De sans doute un peu plus coton (encore que je sais pas comment c'était fait en bdd) c'est de faire une espèce de gestion à la git où tu permet de voir l'historique un peu comme pour git avec les ajouts / suppressions en différentes couleurs.


Ensuite pour limiter la place en bdd tu peux rajouter un trigger on insert qui va supprimer les trop vieilles (genre tu gardes juste les 10 dernières versions).
Sur certains trucs de petites tailles (genre des paramètres de config) tu peux même en garder plus que ça ( et pour le coup c'est pas mal quand on te dit qu'un certains trucs ne fonctionnent plus, que tu as une erreur bizarre dans les logs qui ne sort de nul part et que tu vois que c'est un des autres admins qui à traficoter des options sans rien dire Smiley fache )
Merci Mathieuu.
C'est vrai que ça fait envie d'essayer.
Je fais d'abord une première version complète pour un site et j'itérerais ensuite cette idée sur une version ultérieure.