IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Décisions SGBD Discussion :

BDD jeu en ligne - conception et migration des données


Sujet :

Décisions SGBD

  1. #1
    Candidat au Club
    Homme Profil pro
    Président des Etats-Unis d'Amérique
    Inscrit en
    Septembre 2017
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Président des Etats-Unis d'Amérique
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2017
    Messages : 7
    Points : 2
    Points
    2
    Par défaut BDD jeu en ligne - conception et migration des données
    Bonjour à tous.

    Je suis actuellement en train de développer un jeu en ligne textuel en me basant sur un projet open-source codé en Python (version 3.x). Le projet est dans un état avancé et comprend de nombreuses classes et un code source assez conséquent.

    Actuellement, les données de l'univers (les infos des joueurs, des bots, des objets, etc.) sont stockés à l'aide de Pickle. Une simple boucle parcourt tous les objets du jeu stockés en mémoire et les sauvegarde dans un fichier. Le chargement, quant à lui, consiste simplement à dépickler tous les objets du fichier. Cette méthode est simple mais nous posera, sur le long terme, des problèmes de performance et complique la consultation et l'analyse des données.

    Par conséquent, j'aimerais changer de système et partir sur une base de données relationnelle. Je dois avouer que j'ai du mal à me projeter dans la tâche et que la conversion me parait complexe. C'est pourquoi je vous consulte aujourd'hui en quête de conseils.

    Voici un exemple particulier basé sur trois classes.

    Une classe "PNJ" hérite d'une classe "Personnage".
    Une classe "Joueur" hérite d'une classe "Personnage."

    Voici un code très simplifié des trois classes. J'ai bien entendu enlevé la grande majorité des attributs ainsi que l'intégralité des méthodes. C'est juste pour l'exemple.

    La classe "Personnage" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Personnage(Base_objet):
     
        def __init__(self):
     
            Base_objet.__init__(self)
            self.nom = ""
            self.salle = None
            self.stats = Stats(self)
            self.race = None
    	self.sorts = {}
    La classe "Joueur" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Joueur(Personnage):
     
        def __init__(self):
            Personnage.__init__(self)
            self.compte = None
            self.niveau = 1
            self.classe = None
    La classe "Personnage" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class PNJ(Personnage):
     
        def __init__(self, prototype, salle=None):
            Personnage.__init__(self)
            self._nom = ""
            self.prototype = prototype
            self.salle = salle
    Personnage contient plusieurs instances d'autres classes. Exemple : la race qui y est stockée est un objet issu de la classe "Race". Le dictionnaire "sorts" contient également des objets "Sort". La classe joueur comporte un objet "Classe" et un objet "Compte". Quant à la classe "PNJ", elle comporte un objet "Prototype" ainsi qu'un objet "Salle".

    Je vois deux méthodes possibles pour stocker toutes ces infos dans une base de données.

    Méthode 1 : utilisation de requêtes SQL brutes

    J'ajoute des méthodes "save" et "load" à chacune des classes du projet. Ces méthodes se chargent de faire des requêtes SQL pour récupérer les infos de la base et les mettre à jour tout au long de l’exécution du programme. Le problème, c'est que j'ai peur de la complexité d'une telle méthode. Chaque classe ayant des liens avec les autres, comment écrire des requêtes SQL propres et facilement maintenables ? J'ai l'impression de devoir inévitablement partir sur une usine à gaz. Pour charger un Personnage, il faut commencer par charger tous les sorts qui y sont stockés, dans le dictionnaire "sorts". Pour charger un Joueur, il faut que tous les comptes soient déjà chargés, etc. Une salle contient une référence de tous les joueurs qui s'y trouvent... et chaque joueur possède une référence de la salle dans laquelle il se trouve... bref, il y a de très nombreux liens entre toutes les classes du projet et je peine à déterminer comment et dans quel ordre je dois traiter tout ça pour stocker/charger le tout dans/de la base de données. Surtout que chaque liste et chaque dictionnaire Python se traduira obligatoirement dans la base de données par une classe d'association... bref, je vais me retrouver avec une centaine de tables pour modéliser le tout.

    Méthode 2 : utilisation d'un ORM

    J'utilise un ORM, comme SQLAlchemy qui est censé faciliter le mapping objet-relationnel. Mais que pensez-vous d'une telle méthode ? Est-ce aisé de convertir un projet déjà mature à SQLAlchemy ? Et quid de la base de données générée par SQLAlchemy ? J'aimerais garder une base propre et facilement consultable/modifiable à l'aide de SQL. J'ai peur qu'SQLAlchemy me génère un peu tout et n'importe quoi.

    Bref, je suis un peu perdu et j'ai du mal à voir par quel bout je peux commencer cette conversion. Si quelqu'un a des conseils, des retours d'expérience, des remarques, je prends.

    Merci à vous !

  2. #2
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Quel dommage de ne pas avoir commencé le projet en modélisant les données !

    Le boulot n'est en effet pas mince pour transformer ce gloubi-boulga en base de données relationnelle !

    Je m'attarderai sur un point de votre message pour essayer de comprendre :
    Une classe "Joueur" hérite d'une classe "Personnage."
    Si je me mets dans l'univers du discours de la base de données, cette phrase voudrait dire qu'un joueur est une spécialisation d'un personnage. J'ai plutôt l'impression que dans votre univers, ce serait plutôt le contraire et qu'un joueur peut avoir plusieurs personnages et qu'un personnage appartient à un seul joueur, non ?

    Si je fais une comparaison, en me plaçant encore dans le monde des BDD, voici le genre d'héritages qu'on peut avoir...
    Commençons par écrire les règles de gestion des données :
    R1) Une personne physique est une personne et une personne peut être une personne physique.
    R2) Une personne morale est une personne et une personne peut être une personne morale.

    => On comprend avec ces deux règles qu'une personne est soit personne physique (vous, moi, un joueur...) et/ou une personne morale (une association, une entreprise, un organisme public, un micro-entrepreneur qui est personne morale sous son propre nom de personne physique).

    On modélise ainsi, selon le Modèle Conceptuel de Données de la méthode Merise (ici en version texte mais je vous conseille d'utiliser un logiciel de conception tel que, par exemple, JMerise) :
    personne_physique -(1,1)----être----0,1- personne
    personne_morale -(1,1)----être----0,1-----------|

    Ce qui pourra nous donner ce genre de tables dans la base de données :
    te_personne_prs (prs_id, prs_nom_usuel... [autres colonnes communes à toutes les personnes])
    th_personne_physique_pph (pph_id_personne, pph_nom_naissance, pph_prenom, pph_date_naissance... [autres colonnes spécifiques aux personnes physiques])
    th_personne_morale_pmr (pmr_id_personne_physique, pmr_raison_sociale, pmr_siret... [autres colonnes spécifiques aux personnes morales])

    On voit ci-dessus que pph_id_personne et pmr_id_personne sont des identifiants hérités de te_personne_prs.prs_id que ces colonnes sont donc à la fois des clés primaires et des clés étrangères de leur table respective.

    Ensuite, pour reconstituer les personnes physiques à partir des informations réparties dans la BDD, on crée une vue :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CREATE VUE v_personne_physique AS
    SELECT prs.prs_id AS pphId,
    	prs.prs_nom_usuel AS pphNomUsuel,
    	/* autres colonnes éventuelles communes à toutes les personnes */
    	pph.pph_nom_naissance AS pphNomNaissance,
    	pph.pph_date_naissance AS pphDateNaissance 
    FROM te_personne_prs prs 
    INNER JOIN th_personne_physique_pph pph ON pph.pph_id_personne = prs.prs_id

    Et l'aplication peut ensuite directement interroger la vue :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT pphId, pphPrenom, pphDateNaissance
    FROM v_personne_physique
    WHERE pphNomUsuel = 'Leménager'

    Voilà en gros le principe de ce qui peut être fait. En résumé :
    1) Modéliser correctement les données en faisant abstraction de l'application qui les utilisera.
    2) Créer les vues qui vont correspondre aux classes métier de l'application.
    3) Créer les fonctions d'interrogation dans les classes métier qui vont directement interroger les vues.

    Selon le SGBDR que vous utiliserez et selon vos vues, vous ne pourrez pas directement enregistrer de nouvelles données ou en modifier des existantes directement via les vues. Il est alors conseillé de programmer des procédures SQL qui seront utilisées par les classes métier de l'application. En effet, pour reprendre mon exemple ci-dessus, pour enregistrer une nouvelle personne physique, il faut d'abord enregistrer une personne et récupérer l'identifiant de la personne créée pour l'utiliser en tant qu'identifiant de la personne physique.

    Bon courage ! On peut vous aider dans le forum Schéma pour la première étape.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  3. #3
    Candidat au Club
    Homme Profil pro
    Président des Etats-Unis d'Amérique
    Inscrit en
    Septembre 2017
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Président des Etats-Unis d'Amérique
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2017
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Merci CinePhil pour cette belle réponse instructive et détaillée !

    Si je me mets dans l'univers du discours de la base de données, cette phrase voudrait dire qu'un joueur est une spécialisation d'un personnage. J'ai plutôt l'impression que dans votre univers, ce serait plutôt le contraire et qu'un joueur peut avoir plusieurs personnages et qu'un personnage appartient à un seul joueur, non ?
    En effet, j'aurais dû expliciter un peu plus le concept. En réalité, la classe "Personnage" est bien une classe dont héritent les classes "Joueur" et "PNJ". Certains attributs sont en effet communs à ces deux classes. C'est par exemple le cas pour la barre de vie et de mana qui correspondent aussi bien à un joueur qu'à un PNJ et qui sont donc stocké au niveau de "Personnage". Mais ne vous ayant pas donné d'explication, votre interprétation était tout à fait logique.

    Je n'avais pas du tout pensé à utiliser des Vues pour faciliter la transmission des informations entre la BDD et le programme. L'idée me plait, je vais creuser ça ! Je vois encore quelques zones d'ombres mais j'imagine qu'en mettant les mains dans le cambouis, celles-ci s'eclairciront d'elles-mêmes.

    En tout cas, je pense que je suis parti pour suivre la méthode numéro 1 consistant à concevoir moi-même la BDD ainsi que toutes les requêtes SQL du programme. Je préfère ne pas m'en remettre à un ORM.

    Encore merci.

  4. #4
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Je préfère ne pas m'en remettre à un ORM.
    J'approuve ! J'ai de mauvais souvenirs de ma tentative d'utilisation de ces Outils Réellement Merdiques !
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  5. #5
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 147
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    Si je puis me permettre, afin de simplifier au maximum le code de votre jeu, n'utilisez pas directement de requêtes dedans.

    Préférez utiliser des procédures stockées et fonctions et vues pour mettre à jour les données et les charger.

    En effet, il y a de grandes chances pour que la structure des données évolue dans le temps (par exemple, en plus de vie et mana, ajouté "rage" ou "endurance", qui permettent d'utiliser certains nouvelles capacités, ou un nouveau type de personnage "pet", qui obligerait à revoir un profondeur les tables de bases que son "personnage", "joueur" et "pnj" et donc réécrire tout le code.
    => Avec une procédure stockée "JetteUnSorsCible(@idpersonnage, @idcible, @idsort)" aura toujours la même signature, que ce soit un pet, un pnj ou un joueur qui lance ou reçoive le sors. Et si ce sort nécessite que la rage ou l'endurance soit au dessus un certain seuil, ou augmente ses effets si l'endurance du maître du pet est inférieur à un seuil, alors il n'y aura pas une ligne de code à changer dans le programme, uniquement cette fonction.
    On ne jouit bien que de ce qu’on partage.

  6. #6
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 360
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 360
    Points : 20 377
    Points
    20 377
    Par défaut
    Citation Envoyé par CinePhil Voir le message
    Quel dommage de ne pas avoir commencé le projet en modélisant les données !
    Le boulot n'est en effet pas mince pour transformer ce gloubi-boulga en base de données relationnelle !
    évidemment j'approuve +1000
    Je me permets un aparté c'est que lorsqu'on apprend la programmation et l'informatique on apprend d'abord à faire du code et la conceptualisation après
    Alors que ça devrait être rigoureusement l'inverse..
    avec une conceptualisation bancale et une modélisation du système de données on ne peut que finir avec un projet bancal...

  7. #7
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 147
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Mat.M Voir le message
    c'est que lorsqu'on apprend la programmation et l'informatique on apprend d'abord à faire du code et la conceptualisation après
    J'ai la chance de faire partie de l'infime exception alors

    Je me souvient avoir bouffé du MERISE pendant 6 mois avant de voir une ligne de SQL, et commencé à "coder" au papier et crayon des "arbres programmaticaux" (algo sous forme graphique) avant d'apprendre le moindre langage de programmation.
    On ne jouit bien que de ce qu’on partage.

  8. #8
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 080
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 080
    Points : 30 786
    Points
    30 786
    Par défaut
    Cela dépend si tu es passé par une formation de concepteur ou de pisseur de code.
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  9. #9
    Candidat au Club
    Homme Profil pro
    Président des Etats-Unis d'Amérique
    Inscrit en
    Septembre 2017
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Président des Etats-Unis d'Amérique
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2017
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Merci pour vos réponses. C'est très interessant :-)

    Si je puis me permettre, afin de simplifier au maximum le code de votre jeu, n'utilisez pas directement de requêtes dedans.

    Préférez utiliser des procédures stockées et fonctions et vues pour mettre à jour les données et les charger.

    En effet, il y a de grandes chances pour que la structure des données évolue dans le temps (par exemple, en plus de vie et mana, ajouté "rage" ou "endurance", qui permettent d'utiliser certains nouvelles capacités, ou un nouveau type de personnage "pet", qui obligerait à revoir un profondeur les tables de bases que son "personnage", "joueur" et "pnj" et donc réécrire tout le code.
    => Avec une procédure stockée "JetteUnSorsCible(@idpersonnage, @idcible, @idsort)" aura toujours la même signature, que ce soit un pet, un pnj ou un joueur qui lance ou reçoive le sors. Et si ce sort nécessite que la rage ou l'endurance soit au dessus un certain seuil, ou augmente ses effets si l'endurance du maître du pet est inférieur à un seuil, alors il n'y aura pas une ligne de code à changer dans le programme, uniquement cette fonction.
    Je dois avouer être réticent (peut-être à tort) à l'idée d'écrire des procédures SQL hébergeant la logique même de mon programme. Est-ce que ce n'est pas me rendre totalement dépendant du SGBD que j'utiliserai ? Est-ce que ce n'est pas finalement complexifier l'ensemble ?

    Ce que j'aime bien avec l'idée que les requêtes soient incluses dans le code, c'est que je peux tout à fait imaginer un système où le vieux code Pickle reprendrait le relais en cas de défaillance du SGBD. Il serait possible, par exemple, de faire en sorte que Pickle fasse une sauvegarde complète du jeu toutes les nuits. Bref, le jeu serait indépendant du système de sauvegarde et se suffirait à lui-même. Les Vues, quant à elles, n'auraient pour rôle que d'interfacer le jeu avec la BDD.

    De plus, un langage objet tel que Python permet déjà de faire ce que vous décrivez. Pour reprendre l'exemple des classes Personnage, Joueur et PNJ, les méthodes du type "JetteUnSorsCible" prennent déjà en paramètre des "Personnage", et non des "Joueur" et des "PNJ". Et si je rajoute une classe "Pet", elle n'aura qu'à hériter de "Personnage" pour avoir une barre de vie, une barre de mana et donc être utilisable via "JetteUnSortsCible".

    Qu'en pensez-vous ?

    Quel dommage de ne pas avoir commencé le projet en modélisant les données !
    Oui, c'est très étonnant d'ailleurs parce que le reste du projet est bien conçu. Mais son créateur est parti dès le début du projet sur Pickle et s'est rendu compte de ses limites que bien longtemps après. Mais Pickle, c'est impossible pour moi... j'ai besoin de pouvoir visualiser mes données dans de bonnes conditions. Et dans le cas d'un jeu en ligne, ça me parait absolument obligatoire de pouvoir faire des analyses, des reportings, etc.

  10. #10
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour,
    Citation Envoyé par Daily45 Voir le message
    Est-ce que ce n'est pas me rendre totalement dépendant du SGBD que j'utiliserai ?
    dépendant, oui, totalement, non.
    Le langage SQL étant normalisé, la migration ver un autre SGBDR en est facilitée. Il y aura fatalement du code à adapter, mais il est par ailleurs assez rare de changer de SGBD.

    En revanche, vous deviendrez moins dépendant du langage client qui n'aura plus qu'un rôle d'interface avec la BDD, avec un minimum de logique métier. De fait, si vous voulez par exemple créer un client lourd en plus de la version en ligne, le développement en sera plus facile et plus rapide. Cela évitera aussi d'avoir une même logique métier codée à plusieurs endroit différents, donc moins de code, donc moins de bogues...

    En plus de cela, vous gagnerez en performances, notamment pour toutes les actions qui requièrent des transaction explicites : elle seront gérées directement au sein de la BDD, évitant ainsi les aller/retour BDD/client. Et des transactions plus courtes, ça signifie des verrous posés moins longtemps, donc une concurrence d’accès améliorée et donc une meilleur montée en charge.

  11. #11
    Candidat au Club
    Homme Profil pro
    Président des Etats-Unis d'Amérique
    Inscrit en
    Septembre 2017
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Président des Etats-Unis d'Amérique
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2017
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    En faisant des recherches, je constate qu'il y a un véritable débat sur la question. Certains mettent toute la logique du programme côté BDD, d'autres considèrent qu'il ne s'agit là que d'un endroit où stocker de la donnée et d'autres partent sur un savant mélange des deux.

    En ce qui me concerne, il m'est impossible de faire un programme full BDD. Cela reviendrait à réécrire tout le projet.

    En revanche, vous deviendrez moins dépendant du langage client qui n'aura plus qu'un rôle d'interface avec la BDD, avec un minimum de logique métier. De fait, si vous voulez par exemple créer un client lourd en plus de la version en ligne, le développement en sera plus facile et plus rapide. Cela évitera aussi d'avoir une même logique métier codée à plusieurs endroit différents, donc moins de code, donc moins de bogues...
    J'ai l'impression que ces arguments ne s'appliquent pas réellement à mon cas. Mon jeu en ligne textuel repose sur un simple programme serveur. Les joueurs s'y connectent via des clients sur lesquelles je n'ai pas la main (on appelle ça des clients MUD). Si vous voulez en savoir plus, voici la page wikipédia des Multi-User Dungeon.

    Les joueurs intéragissent avec le serveur via un client MUD. Le serveur reçoit une chaine de caractère, la traite, puis la renvoie au client. Par conséquent, toute la logique du programme se situe déjà au même endroit. Si je décide un jour de créer une interface web ou une application Android pour se connecter à mon jeu, il me suffira de les faire communiquer avec le serveur de la même façon.

  12. #12
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 760
    Points : 52 541
    Points
    52 541
    Billets dans le blog
    5
    Par défaut
    Il faut aussi comprendre que l'écriture du code dans la base, non seulement est plus optimale au point de vue performances, charge, ect.. mais en plus est dynamique au changement.
    Si vous devez modifier votre code client, il faudra arrêter l'application. Si vous voulez changer le code d'une procédure il ne faut pas arrêter la base et les utilisateurs continuent de l'utiliser comme si de rien n'étais.
    En revanche ne croyez pas du tout que le langage SQL soit compatible d'un SGBDR à l'autre. Certains sont très pauvres par apport à la norme SQL (MySQmerde en particulier) et d'autres ajoutent des syntaxes spécifique qui les rendent strictement incompatible (oracle en particulier).
    Même une simple requête comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * FROM MaTable ORDER BY UneColonne
    ne donnera pas le même tri sur des SGBDR différents !

    À me lire : http://sqlpro.developpez.com/cours/s...age=partie1#L4

    Donc, la tentative d'avoir des requêtes communes à plusieurs SGBDR est nulle !

    Un autre avantage du code en procédures stockées est que le SGBDR analyse en permanence ses propres performances ce qui permet de diagnostiquer les choses à récrire pour améliorer les performances. Cela n'existe pas dans l'univers des langages client.
    Un petit exemple dans SQL Server :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * FROM sys.dm_exec_procedure_stats
    https://technet.microsoft.com/fr-fr/...=sql.105).aspx

    Au final vous gangerez un temps considérable.


    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  13. #13
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Certains mettent toute la logique du programme côté BDD
    Je n'irais pas jusque là !

    Le programme utilisateur s'occupe de l'interaction avec l'utilisateur et demande au SGBD ce qu'il sait mieux faire que lui :
    - Extraire juste les données nécessaires à satisfaire le besoin de l'utilisateur ;
    - Enregistrer les données et contrôler leur cohérence ;
    - Exécuter des opérations sur des masses de données.

    Exemple trivial...
    Il n'est pas rare, dans nos forums, de voir des morceaux de programmes qui extraient la totalité d'une table pour ensuite simplement en compter les lignes... alors que le SGBD dispose d'une fonction COUNT qui fait ça beaucoup plus rapidement !
    Le programmeur de cette application n'a souvent qu'une maigre connaissance de l'univers des bases de données relationnelles et ne connait même pas cette fonction SQL pourtant basique.

    Et des exemples triviaux de ce genre, il y en a à la pelle !

    Ce que j'ai décrit ci-dessus est peut-être ce que vous appelez "un savant mélange entre les deux" et que SQLPro appelle le "développement en base de données épaisse".
    En résumé, on met dans le SGBDR tout ce qui concerne la gestion des données et dans le programme applicatif tout ce qui concerne l'interaction avec l'utilisateur.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  14. #14
    Candidat au Club
    Homme Profil pro
    Président des Etats-Unis d'Amérique
    Inscrit en
    Septembre 2017
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Président des Etats-Unis d'Amérique
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2017
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Ok, je vais potasser tout ça. De toute façon, je n'y suis pas encore... je viens de constater qu'il y a 163 types d'objets différents à stocker... sachant que derrière, il y a des tables associations pour chaque dictionnaire/liste Python... je crois que mon schéma contiendra plus de 300 tables. J'ai du boulot

    Encore merci à tout le monde pour toutes ces infos.

  15. #15
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 147
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    Dans la limite du raisonnable, il est possible de ne pas stocker tout "dans le détail".

    En effet, le SGBD sert ici avant tout à stocker et restituer de l'information "telle qu'elle".
    Il y aura quelques rapports permettant par exemple de comptabiliser le nombre de jours actifs, le nombre de mobs tués dans la journée, l'état des finances des différentes guildes, etc.

    Mais toutes les données n'auront pas forcément besoin d'être requêtées pour faire des calculs.
    Les types de colonnes "XML" ou "JSON" (voir même VARBINARY si vous souhaitez sérialiser directement en binaire) peuvent vous aider à réduire la quantité de tables et colonnes à créer.

    Mettons par exemple, pour un MUD, chaque arme a un certain nombre de caractéristiques (type d'arme, emplacements possibles, range(s) de dégâts, type(s) de dégâts, combos, nom, description, nodrop, unique, attributs requis, capacités requises, modificateurs attributs, modificateurs capacités, etc. il doit y en avoir à la louche 2 ou 3 dizaines).
    Il y a peut de chances qu'un reporting "quelle est l'épée à deux main qui fait des dégâts de feu utilisable que par les paladins et qui a un bonus de dégâts contre les morts-vivants qui apporte le meilleur modificateur de force ?" soit nécessaire, voir même souhaitable.

    Donc à part le type d'arme, le nom, sont identifiant et éventuellement deux ou trois attributs nécessaires par exemple pour filtrer ce qu'un marchand peu vendre ou non, tous les autres peuvent être agrégés sous forme JSON. Ainsi, le modèle se retrouve simplifié, et si besoin, ces attributs restent toujours utilisables directement dans les requêtes SQL. Le type XML permet la même chose. Un VARBINARY, quant à lui, permettra une sérialisation/désérialisation performante, en revanche il sera complexe d'accéder à un attribut directement en SQL.

    https://docs.microsoft.com/fr-fr/sql...ata-sql-server

    Cependant, attention à ne pas abuser des bonnes choses : ces types sont à la base déconseillés, car implique une dénormalisation du modèle et une incapacité pour le SGBD de valider l'intégrité des données (par exemple, impossible de vérifier dans le contenu JSON que le type de dégât est bien une valeur existante dans la table "type_degat").
    C'est donc à n'utiliser que pour des données qu'on ne souhaite absolument pas manipuler en SQL, uniquement sauvegarder/charger tel quel dans le programme.
    On ne jouit bien que de ce qu’on partage.

  16. #16
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    je viens de constater qu'il y a 163 types d'objets différents à stocker...
    Alors intéressez-vous, peut-être, à la modélisation par métadonnées ou une approche voisine qui ne nécessite que peu de tables...

    Règle de gestion :
    R1 : Un type d'objet est caractérisé par un à plusieurs paramètres et un paramètre peut caractériser plusieurs types d'objets.

    MCD 1 :
    parametre -0,n----caracteriser----1,n- type_objet

    Tables :
    tr_parametre_par (par_id, par_code, par_libelle, ...)
    tr_type_objet_tob (tob_id, tob_code, tob_libelle, ...)
    tj_par_caracteriser_tob_pct (pct_id_parametre, pct_id_type_objet, ...)

    Règle de gestion :
    R2 : Un objet est classé dans un certain type d'objet et un type d'objet peut classer plusieurs objets.

    MCD 2 :
    type_objet -0,n----classer----1,1- objet

    Table supplémentaire :
    te_objet_obj (obj_id, obj_id_type_objet, obj_code, obj_nom, ...)

    Règle de gestion :
    r3 : Un objet est valorisé par les paramètres de son type d'objet (appelées caractéristiques) et un paramètre de type d'objet (appelé caractéristique) peut valoriser plusieurs objets.

    Étape intermédiaire sur le MCD 1, on transforme l'association caractériser en ce que j'appelle une "entité type associative" :
    parametre -0,n----appliquer----(1,1)- caracteristique -(1,1)----concerner----1,n- type_objet

    La table tj_par_caracteriser_tob_pct disparaît au profit de la table :
    tr_caracteristique_car (car_id_parametre, car_id_type_objet, ...)

    On peut alors utiliser cette entité associative pour faire le MCD 3 issu de la règle R3 :
    caracteristique -0,n----valoriser----1,n- objet

    Table supplémentaire :
    tj_car_valoriser_obj_cvo (cvo_id_parametre, cvo_id_type_objet, cvo_id_objet, cvo_valeur, ...)

    Il faut cependant prendre en compte une contrainte exprimée dans la règle de gestion R3 : "les paramètres de son type d'objet"
    On peut dessiner une contrainte sur le MCD exprimant que les paramètres des caractéristiques de l'objet soient bien ceux du type d'objet de l'objet.

    On peut aussi utiliser une astuce en identifiant l'objet relativement à son type dans le MCD 2 :
    type_objet -0,n----classer----(1,1)- objet

    Cette fois, chaque objet est identifié par son type d'objet et par un simple numéro d'arrivée dans le type :
    te_objet_obj (obj_id_type_objet, obj_numero, obj_code, obj_nom, ...)

    Du coup, la table associative tj_car_valoriser_obj_cvo devrait devenir celle-ci, reprenant en clé primaire les clés étrangères référençant les deux tables participant à l'association :
    tj_car_valoriser_obj_cvo (cvo_id_parametre, cvo_id_type_objet, cvo_id_type_objet, cvo_numero, cvo_valeur, ...)

    Et comme il y a deux fois la même clé étrangère cvo_id_type_objet qui doivent avoir la même valeur du fait de la contrainte exprimée dans R3, il suffit de supprimer une de ces deux colonnes pour que la contrainte soit respectée. En gardant les deux clés étrangères, le paramètre de l'objet sera bien celui de son type.
    tj_car_valoriser_obj_cvo (cvo_id_parametre_caracteristique, cvo_id_type_objet, cvo_numero_objet, cvo_valeur, ...)

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ALTER TABLE tj_car_valoriser_obj_cvo
    	CONSTRAINT fk_cvo_objet FOREIGN KEY (cvo_id_type_objet, cvo_numero_objet) REFERNCES te_objet_obj(obj_id_type_objet, obj_numero_objet);
    ALTER TABLE tj_car_valoriser_obj_cvo
    	CONSTRAINT fk_cvo_caracteristique FOREIGN KEY (cvo_id_parametre_caracteristique, cvo_id_type_objet) REFERNCES tr_caracteristique_car (car_id_parametre, car_id_type_objet);

    Soit seulement 5 tables pour caractériser tous les objets, qu'il y en ait 10 types ou 200.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  17. #17
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour,

    je vais me faire l'avocat du diable.

    La modélisation par métadonnée a quand même ses limites, notamment en terme de performances. Elle facilite certes les évolutions car elle ne nécessite pas de modification du modèle pour ajouter de nouveaux éléments, mais la création reste presque aussi fastidieuse... Dans tous les cas, il faut définir le modèle d'une façon ou d'une autre et c'est ce qui prend du temps.
    Elle ne permet pas non plus d'assurer l'intégrité des données aussi bien que la modélisation classique, a commencer par l’intégrité référentielle.
    A mon sens, elle peut être mise en œuvre pour une partie du modèle dont on sait que les évolutions seront très fréquentes, mais la généraliser à toute une base me semble un peu risqué.
    De plus, maintenant, je partirais plutôt comme le disais stringBuilder sur une solution à base d'XML (ou JSON ).

    Mais pour en revenir au cas de précis de Daily45, vu que le modèle objet semble bien construit - et malgré tout le mal que je pense des ORM - pourquoi ne pas laisser un ORM construire la base à partir du modèle objet ?
    il faudra certainement une passe manuelle derrière pour vérifier qu'il n'a pas (encore) fait un truc pourri, mais je pense que ça peut faire gagner du temps pour la création initiale de la base. rien n'oblige ensuite à l'utiliser dans le code pour toutes les opérations d'accès aux données, mais dans le cas présent, ça permettrai la création rapide d'une base sans doute potable, qu'il restera à peaufiner certainement.

    Ce n'est qu'un avis qui ne se fonde sur pas grand chose (je n'ai jamais utilisé d'ORM pour générer une BDD, seulement pour l’accès aux données d'une base existante, et sous la torture ), mais je me dis que s'il peut, depuis le modèle objet, générer assez proprement les tables avec les bonnes colonnes et les bons types (ou presque), voire les bonnes contraintes d'intégrité en quelques minutes, pourquoi s'en priver...

    My 2 cents.

  18. #18
    Candidat au Club
    Homme Profil pro
    Président des Etats-Unis d'Amérique
    Inscrit en
    Septembre 2017
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Président des Etats-Unis d'Amérique
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2017
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Encore une fois, merci à tous pour vos conseils et pour tous ces éléments.

    Je pense que je vais tenter de modéliser toutes mes tables normalement, sans modélisation par métadonnée. Comme proposé par aieeeuuuuu, je vais voir si je peux trouver un moyen de générer automatiquement un schéma en fonction de mes classes Python. Je repasserai par-dessus pour améliorer/corriger les éventuelles erreurs et ça finira bien par se faire ! :-) Si je dois administrer mon jeu pendant les dix prochaines années, autant que la BDD soit irréprochable et puisse me permettre d'analyser mes données dans tous les sens sans aucune contrainte !

    Sinon, pour information, je suis parti sur PostgreSQL, qui me parait être une solution complète, stable et performante.

Discussions similaires

  1. migration des données
    Par phpdev dans le forum Outlook
    Réponses: 2
    Dernier message: 08/09/2008, 20h08
  2. Migration des données de EXCEl vers Oracle
    Par shark84 dans le forum Développement de jobs
    Réponses: 1
    Dernier message: 25/04/2008, 15h03
  3. Plantage d'un serveur > migration des données
    Par cedtic dans le forum SQL Procédural
    Réponses: 0
    Dernier message: 15/10/2007, 16h00
  4. [WD55] Migration des données HF vers MySQL ou Access
    Par developper2006 dans le forum WinDev
    Réponses: 1
    Dernier message: 21/02/2007, 13h31
  5. [Debutant] Conception du traitement des données
    Par badack dans le forum JDBC
    Réponses: 6
    Dernier message: 04/01/2007, 15h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo