- les installations
- spécifications de l'application
- création de la base et des tables
- création du projet Eclipse, mise en place du log
- mise en place de l'authentification Tomcat
- connexion Java-MySQL
- récupérations d'informations dans la base
- génération du flux XML des actualités
- transformation et affichage du flux XML
- construction du modèle des pages HTML
- écriture des requêtes de modification/ajout/suppression
- écriture des pages de modification/ajout/suppression
- prototype + scriptaculous : le javascript fiable, facile et spectaculaire
- saisie facile des dates
- validation des données saisies
- écriture de la servlet publique
- génération du flux Atom
(en passant, les étapes correspondent grosso modo aux étapes que je suis quand je développe une application. Une application même modeste c'est un gros truc (une vingtaine d'heures pour celle là en comptant les recherches sur google et les essais). C'est pour ça qu'il est important de se fixer des petits pas, toujours plus ou moins les mêmes, à réaliser les uns après les autres pour avancer, sinon on a vite fait de partir dans tous les sens sans avancer réellement).
En analysant les spécifications, on peut distinguer plusieurs entités de différentes natures :
- un jeu bien sûr
- un éditeur (Sony, Activision,...)
- un support (Wii, PSP, PS3,...)
- un format (ou territoire) (EU, US, Jap)
- une sortie
Si on s'intéresse aux relations entre ces objets on a d'après les spécifications :
- un jeu a un éditeur unique, mais un éditeur peut produire plusieurs jeux
- un jeu peut sortir sur plusieurs supports, et un support peut accueillir plusieurs jeux
- un jeu, sur un support donné, peut sortir sur plusieurs territoires (une seule fois pour chaque au maximum) et un territoire peut avoir plusieurs jeux différents qui sortent dessus
- une sortie se caractérise donc par un jeu sur un support dans un territoire
En terme relationnels on a donc (par convention N signifie ici "nombre quelconque") :
- jeu-éditeur : relation 1-N (un seul éditeur par jeu, N jeux par éditeur)
- jeu-support : relation N-N (N supports par jeu, N jeux par support)
- jeu-format : relation N-N? En fait le format d'un jeu n'est intéressant pour nous que si le jeu est associé à un support (exemple : sur XBox360 Final Fantasy XIII ne sortira pas au Japon, contrairement à la PS3). Donc :
- jeu-format-support : triplet définissant de manière unique une sortie
(il n'y a pas de solution unique, certaines interprétations des spécifications peuvent être fausses, c'est pour ça qu'il est utile de s'assurer auprès du client à chaque étape qu'on comprend bien son besoin. Ici vu que c'est moi le client je suis d'accord avec moi-même

Une fois qu'on a dégagé ces relations, le plus dur est fait au niveau du design de la base de données.
En effet :
- relation 1-N => l'identifiant de la table unique va se retrouver dans la table N
- relation N-N => une table de liaison intermédiaire entre nos deux tables est nécessaire pour obtenir cette articulation
Ce qui donne :
- une table éditeur toute simple
- une table support toute simple
- une table format toute simple
- une table jeu, comportant l'identifiant de son éditeur
- une table de liaison entre un jeu et un support
- une table de liaison entre un jeu, un support et un format (ce sera notre table "sortie")
Avant d'attaquer nos tables, créons notre base (explications minimales, ne pas hésiter à se manifester si quelque chose bloque !) :
- Vérifier que le démon mysqld est lancé par le prefpane MySQL
- Avec l'application MySQL Administrator, se connecter (root sans mot de passe sur localhost:3306 par défaut)
- Créer un utilisateur (Accounts) videogames (mot de passe videogames)
- Choisir cet utilisateur dans la liste et configurer les hosts (enlever % et ajouter localhost, 127.0.0.1 et le nom de l'ordinateur (mini.local pour moi par exemple) (sur mon image j'ai aussi configuré une plage d'IP (192.168.0.%) pour me connecter à la base depuis mon MacPro pour développer car Eclipse ramait trop sur le mini...)

- Sur l'onglet Catalogs, créer le schéma videogames_db (ne pas tenir compte des tables qu'on voit dans cette image, on va les créer juste après)

- Sur l'ongle users, pour chaque host de l'utilisateur videogames, choisir tous les droits et les ajouter pour le schéma videogames_db

On va ensuite créer les tables par script (en effet graphiquement, par l'application d'administration il y a quelques limitations, en particulier pour la création des dates).
On lance donc l'application MySQL Query Browser et on se connecte comme ceci :

On tape les scripts directement dans un onglet "Query", puis "Execute" pour les exécuter :

En script (My)SQL cela donne :
- table format :
CODE
CREATE TABLE `videogames_db`.`VG_FORMAT` (
`form_id` BIGINT NOT NULL AUTO_INCREMENT,
`form_label` VARCHAR(64) NOT NULL,
PRIMARY KEY (`form_id`)
)
CHARACTER SET utf8;
`form_id` BIGINT NOT NULL AUTO_INCREMENT,
`form_label` VARCHAR(64) NOT NULL,
PRIMARY KEY (`form_id`)
)
CHARACTER SET utf8;
Explications :
- form_id est l'identifiant de la table, c'est un nombre qui peut être grand (BIGINT), non nul (NOT NULL), qui s'incrémente seul si non spécifié lors d'une insertion de données (AUTO_INCREMENT) et qui sera l'accès privilégié à la table comme moyen de récupération d'une information en particulier (PRIMARY KEY)
- form_label est le nom du format, c'est une chaîne de caractères (64 maximum) qui ne peut être nulle
- table éditeur :
CODE
CREATE TABLE `videogames_db`.`VG_EDITEUR` (
`edit_id` BIGINT NOT NULL AUTO_INCREMENT,
`edit_name` VARCHAR(64) NOT NULL,
PRIMARY KEY (`edit_id`)
)
CHARACTER SET utf8;
`edit_id` BIGINT NOT NULL AUTO_INCREMENT,
`edit_name` VARCHAR(64) NOT NULL,
PRIMARY KEY (`edit_id`)
)
CHARACTER SET utf8;
Idem format
- jeu :
CODE
CREATE TABLE `videogames_db`.`VG_JEU` (
`jeu_id` BIGINT NOT NULL AUTO_INCREMENT,
`jeu_titre` VARCHAR(128) NOT NULL,
`jeu_editeur_id` BIGINT NOT NULL,
`jeu_description` TEXT,
`jeu_previews` TEXT,
`jeu_tests` TEXT,
`jeu_date_creation` TIMESTAMP NOT NULL,
`jeu_date_modification` TIMESTAMP NOT NULL,
PRIMARY KEY (`jeu_id`)
)
CHARACTER SET utf8;
`jeu_id` BIGINT NOT NULL AUTO_INCREMENT,
`jeu_titre` VARCHAR(128) NOT NULL,
`jeu_editeur_id` BIGINT NOT NULL,
`jeu_description` TEXT,
`jeu_previews` TEXT,
`jeu_tests` TEXT,
`jeu_date_creation` TIMESTAMP NOT NULL,
`jeu_date_modification` TIMESTAMP NOT NULL,
PRIMARY KEY (`jeu_id`)
)
CHARACTER SET utf8;
Explications :
- jeu_id idem
- jeu_titre : le titre du jeu, ne peut être nul
- jeu_editeur_id : notre identifiant caractérisant l'éditeur unique d'un jeu. Ne peut être nul
- jeu_description : texte long (idem pour jeu_previews et jeu_tests qui recevront des liens vers previews et tests)
- jeu_date_creation : date-heure non nulle
- jeu_date_modification : idem jeu_date_creation
- table support :
CODE
CREATE TABLE `videogames_db`.`VG_SUPPORT` (
`supp_id` BIGINT NOT NULL AUTO_INCREMENT,
`supp_label` INT,
PRIMARY KEY (`supp_id`)
)
CHARACTER SET utf8;
`supp_id` BIGINT NOT NULL AUTO_INCREMENT,
`supp_label` INT,
PRIMARY KEY (`supp_id`)
)
CHARACTER SET utf8;
Explications : idem tables éditeur et format
- liaison jeu-support :
CODE
CREATE TABLE `videogames_db`.`VG_JEU_SUPP` (
`jesu_jeu_id` BIGINT NOT NULL,
`jesu_supp_id` BIGINT NOT NULL,
`jesu_description` TEXT
)
CHARACTER SET utf8;
`jesu_jeu_id` BIGINT NOT NULL,
`jesu_supp_id` BIGINT NOT NULL,
`jesu_description` TEXT
)
CHARACTER SET utf8;
Explications :
- jesu_jeu_id : l'identifiant du jeu concerné
- jesu_supp_id : l'identifiant du support concerné
- jesu_description : un petit texte précisant les spécificités du jeu sur le support (ex: compatible Balance Board)
- liaison jeu-support-format :
CODE
CREATE TABLE `videogames_db`.`VG_JEU_SUPP_FORM` (
`jesf_jeu_id` BIGINT NOT NULL,
`jesf_supp_id` BIGINT NOT NULL,
`jesf_form_id` BIGINT NOT NULL,
`jesf_date` TIMESTAMP NULL,
`jesf_description` TEXT
)
CHARACTER SET utf8;
`jesf_jeu_id` BIGINT NOT NULL,
`jesf_supp_id` BIGINT NOT NULL,
`jesf_form_id` BIGINT NOT NULL,
`jesf_date` TIMESTAMP NULL,
`jesf_description` TEXT
)
CHARACTER SET utf8;
Explications : notre table des sorties
- jesf_jeu_id / jesf_supp_id / jesf_form_id : les identifiants standard
- jesf_date : la date de la sortie, peut-être nulle si la date est encore inconnue
- jesf_description : un petit texte décrivant les spécificités éventuelles de la sortie du jeu sur ce support (ex: pas de sang sur No More Heroes européen)
On va ensuite insérer quelques données pour pouvoir commencer à travailler (commit permet de valider l'insertion de données, rollback permet de les annuler) :
- les formats :
CODE
insert into VG_FORMAT(form_label) values('EU Pal');
insert into VG_FORMAT(form_label) values('US NTSC');
insert into VG_FORMAT(form_label) values('Jap NTSC');
commit;
insert into VG_FORMAT(form_label) values('US NTSC');
insert into VG_FORMAT(form_label) values('Jap NTSC');
commit;
- les supports :
CODE
insert into vg_support(supp_label) values ('Wii');
insert into vg_support(supp_label) values ('DS');
insert into vg_support(supp_label) values ('Mac');
insert into vg_support(supp_label) values ('PC');
insert into vg_support(supp_label) values ('PS3');
insert into vg_support(supp_label) values ('PS2');
insert into vg_support(supp_label) values ('PSP');
insert into vg_support(supp_label) values ('XBox360');
commit;
insert into vg_support(supp_label) values ('DS');
insert into vg_support(supp_label) values ('Mac');
insert into vg_support(supp_label) values ('PC');
insert into vg_support(supp_label) values ('PS3');
insert into vg_support(supp_label) values ('PS2');
insert into vg_support(supp_label) values ('PSP');
insert into vg_support(supp_label) values ('XBox360');
commit;
- les éditeurs (on ajoutera ultérieurement une page pour administrer cela, pour le moment on se contente d'en mettre quelques uns pour tester tout ça) :
CODE
insert into vg_editeur(edit_name) values('Nintendo');
insert into vg_editeur(edit_name) values('Codemasters');
insert into vg_editeur(edit_name) values('Sega');
insert into vg_editeur(edit_name) values('Konami');
insert into vg_editeur(edit_name) values('Activision');
insert into vg_editeur(edit_name) values('LucasArts');
insert into vg_editeur(edit_name) values('Disney Interactive');
insert into vg_editeur(edit_name) values('505 Games');
insert into vg_editeur(edit_name) values('Square Enix');
insert into vg_editeur(edit_name) values('GOA');
insert into vg_editeur(edit_name) values('Koei');
insert into vg_editeur(edit_name) values('MTV Games');
insert into vg_editeur(edit_name) values('2K Games');
insert into vg_editeur(edit_name) values('EA');
insert into vg_editeur(edit_name) values('Capcom');
insert into vg_editeur(edit_name) values('THQ');
insert into vg_editeur(edit_name) values('Warner Bros. Games');
insert into vg_editeur(edit_name) values('XSeed Games');
insert into vg_editeur(edit_name) values('Microsoft');
insert into vg_editeur(edit_name) values('Sony');
insert into vg_editeur(edit_name) values('Ubisoft');
insert into vg_editeur(edit_name) values('JoWood');
insert into vg_editeur(edit_name) values('Ignition');
insert into vg_editeur(edit_name) values('Bethesda Softworks');
insert into vg_editeur(edit_name) values('Gamecock Media Group');
insert into vg_editeur(edit_name) values('Marvelous');
insert into vg_editeur(edit_name) values('Level5');
insert into vg_editeur(edit_name) values('Atlus');
insert into vg_editeur(edit_name) values('Blizzard');
commit;
insert into vg_editeur(edit_name) values('Codemasters');
insert into vg_editeur(edit_name) values('Sega');
insert into vg_editeur(edit_name) values('Konami');
insert into vg_editeur(edit_name) values('Activision');
insert into vg_editeur(edit_name) values('LucasArts');
insert into vg_editeur(edit_name) values('Disney Interactive');
insert into vg_editeur(edit_name) values('505 Games');
insert into vg_editeur(edit_name) values('Square Enix');
insert into vg_editeur(edit_name) values('GOA');
insert into vg_editeur(edit_name) values('Koei');
insert into vg_editeur(edit_name) values('MTV Games');
insert into vg_editeur(edit_name) values('2K Games');
insert into vg_editeur(edit_name) values('EA');
insert into vg_editeur(edit_name) values('Capcom');
insert into vg_editeur(edit_name) values('THQ');
insert into vg_editeur(edit_name) values('Warner Bros. Games');
insert into vg_editeur(edit_name) values('XSeed Games');
insert into vg_editeur(edit_name) values('Microsoft');
insert into vg_editeur(edit_name) values('Sony');
insert into vg_editeur(edit_name) values('Ubisoft');
insert into vg_editeur(edit_name) values('JoWood');
insert into vg_editeur(edit_name) values('Ignition');
insert into vg_editeur(edit_name) values('Bethesda Softworks');
insert into vg_editeur(edit_name) values('Gamecock Media Group');
insert into vg_editeur(edit_name) values('Marvelous');
insert into vg_editeur(edit_name) values('Level5');
insert into vg_editeur(edit_name) values('Atlus');
insert into vg_editeur(edit_name) values('Blizzard');
commit;
[Edit]Un petit mot sur les règles de nommage des tables et colonnes : ça peut sembler chiant ou illisible mais ça fait en fait gagner énormément de temps d'avoir une règle immuable appliquée bêtement. En l'occurrence :
- les tables sont préfixées par un surnom unique pour la base ("vg_")
- les tables d'entités ont un nom lisible, les tables de liaison ont le nom accolé des tables qu'elles lient
- une colonne hérite du nom de la colonne qui la contraint au préfixe de table près (ex : "jesf_jeu_id" pour "jeu_id") (seul contre-exemple : j'aurai du appeler la colonne jeu_editeur_id "jeu_edit_id" pour être cohérent mais ça m'a échappé, tant pis

- les noms de colonnes sont préfixés par quatre lettres (ou moins, cf "jeu") représentatives du nom de la table. De fait tout nom de colonne est unique dans la base, ça évite de devoir lever soi-même les ambiguïtés dans les requêtes SQL.