Les grands principes de nomenclature – Partie 2 : les données

Cette partie là sera un poil plus rapide que la partie précédente (Les grands principes de nomenclature – Partie 1 : les classes), il s’agit de déterminer proprement la façon dont on doit nommer les données des bases de données (bases, tables, colonnes) ainsi que les requêtes sur ces données. Une bonne adéquation entre la nomenclature de vos données, d’une part, et la nomenclature de vos classes, d’autre part, vous permettra d’obtenir un code plus clair, plus lisible, et par conséquent plus maintenable.

Les bases, tables et colonnes

base de données

Le nom d’une base de donnée est aussi déterminant qu’il importe peu en réalité; dans la plupart des cas, votre application n’utilisera qu’une base de données et votre code ne se préoccupera de son nom que dans l’implémentation de la connexion. Cependant, il est bon d’avoir en tête un certain nombre de guidelines; en effet, il arrivera que vos applications utilisent plusieurs bases de données, mais également (bien plus fréquemment, d’ailleurs) que votre serveur déploient plusieurs bases de données.

Les règles de nomenclature dépendent ici grandement du type d’application que vous êtes en train de mettre en place; par exemple, si vous développez un logiciel que vous allez éditer, le nom de votre base devra être générique (par exemple le nom de votre logiciel); si, en revanche, vous développez, sur un même serveur, des bases de structure identique pour des clients différents, vous spécifierez le nom de votre client dans votre base (un bon exemple similaire consiste en un serveur qui déploierait un certain nombre de blogs wordpress pour différents sites, et dont les base de données pourraient se nommer de la forme wp_mondomaine, wp_monautredomaine, etc.).

Concernant la nomenclature à proprement parler, je ne saurai que trop vous inciter à ne pas utiliser de majuscule; une autre école est celle du tout majuscules, justement; c’est votre choix, mais l’essentiel est d’éviter de mêler majuscules et minuscules. Soyons clair : la plupart des SGBD ne sont pas sensibles à la casse et gèreront indifféremment mabase, MABASE, MaBase et maBase. Mais suivez-moi simplement jusqu’au bout de l’article et vous verrez que je veux en venir quelque part.

Donc, je disais, tout en minuscules; aussi, et assez naturellement, séparez — si vous le souhaitez — les mots qui constituent éventuellement le nom de votre base par le caractère underscore (« _ »). Par exemple :

  • lemondedudev
  • wp_lemondedudev
  • lemonde_dudev

Les tables

Les noms des tables sont intimement liés à votre modèle objet (par exemple des CRUD auront des tables équivalentes possédant le même nom, à la nomenclature près : Customer et customer, PersonnePhysique et personne_physique, etc.). Les règles de nomenclature sont ici les mêmes que pour les bases de données; évitez, si possible, d’utiliser des mots réservés par SQL comme nom de table, même si vous pouvez toujours échapper le nom de la table (par exemple, sous MySQL, avec le caractère `).

Concernant les vues, déterminez un préfixe (ou un suffixe) que vous garderez dans l’ensemble de vos développements sur cette base (et si possible de toutes les bases); par exemple une vue sur les customer pourrait s’appeler v_customer.

Les colonnes

Nomenclature toujours identique, guidelines relativement similaires (pas de mot réservé SQL, corrélation éventuelle avec votre modèle objet, etc.). À cela, je me permets d’ajouter un certain nombre de règles :

Le fond et pas la forme

Lorsque vous écrivez une feuille de style CSS pour une page web, vous allez décrire la classe qui permet d’afficher ce titre en vert fluo, en Arial et en majuscules que (étonnamment) vous trouvez magnifique. Une erreur classique consiste à appeler cette classe titreVert, ou titreVertMajArial, etc. Ce genre de nom est techniquement tout à fait acceptable, mais vos clients vous demanderont sûrement, après avoir un petit peu vomi, de remplacer le vert par un beau gris anthracite vraiment moins engagé (du coup beaucoup plus engageant). L’ennui est que vous vous retrouvez avec un dilemme (deux « m », de dilemmâ, en grec; c’est « indemne » qui s’écrit avec un « m » immédiatement suivi d’un « n ») :

  • vous ne modifiez pas votre feuille de style et vous avez maintenant une classe titreVert qui décrit un titre gris;
  • vous modifiez le titre de votre classe dans votre feuille de style et vous devez modifier ce nom à chaque occurrence de votre application (vous ne le ferez pas, vous et moi le savons bien).

La solution consiste à séparer le fond de la forme : votre titre est, admettons, un titre d’article, et ce qu’il soit vert ou gris; alors appelez-le titreArticle.

De la même manière, vos colonnes décrivent des données, et peu importe de savoir si ces données sont des chaînes de caractères, des dates, des nombres (notamment la différence entre integer, decimal, double, etc.); aussi, épargnez-vous de préfixer ou de suffixer par type de donnée (« _s » pour des string, « _i » pour des entiers, etc.). Ceci est valable également pour les alias (SELECT SUM(amount) AS total_amount, par exemple).

Concernant les références, pensez à mettre en place des règles que vous respectez tout au long de vos développements :

  • si un champ référence l’id de la table customer, appelez-le id_customer, ou customer_id
  • pour les clés étrangères, utilisez toujours la même structure (par exemple, « fk_ » suivi de la table référencée, puis de la table référençant);
  • idem pour les index et les clés uniques

Enfin, dernier petit conseil, pour les colonnes représentant des booléen (je parle du fond; le type de données peut tout à fait être un smallint, un tinyint ou un double (?!!) si ça vous chante), ne préfixez pas votre colonne par « is_ », ça compliquerait un peu votre corrélation entre colonnes de tables et propriétés de classes; ainsi :

  • la table customer dispose d’un champ active
  • la classe Customer dispose d’une propriété booléenne active à laquelle sont attachés les accesseurs setActive(value) et isActive()

Les requêtes

Nomenclature

C’est ici que l’histoire du « tout en minuscules » va prendre tout son sens; lorsque vous écrivez des requêtes, écrivez tous les mots réservés SQL en majuscules, cela améliorera d’autant votre lecture des requêtes :

SELECT
    id, last_name, first_name
FROM
    customer
WHERE
    UPPER(last_name) LIKE 'A%';

Règles d’écriture

Listez vos données

Bannissez, définitivement et une bonne fois pour toutes (à moins d’avoir une excellente raison de le faire), le « SELECT *« ; il existe des cas dans lesquels cela peut avoir du sens (typiquement, si vous avez besoin de dumper l’intégralité d’une table, encore que ça reste — selon moi — un peu à gerber), mais dans la plupart des cas cela ne fait que masquer l’information que vous cherchez à récupérer (et en général, vous allez traiter les données que vous récupérez).

Typiquement, lors du chargement (ou initialisation, ou encore init()) d’un CRUD, vous faites un SELECT sur l’ensemble des colonnes correspondant aux propriétés de votre CRUD, pour ensuite initialiser ses propriétés :

$query = "SELECT id, last_name, first_name FROM customer WHERE id = ?";
// ... on assigne ici la valeur de l'id, puis on exécute la requête et on récupère le résultat, s'il existe, dans un tableau $row
$this->setId($row['id']);
$this->setLastName($row['last_name']);
$this->setFirstName($row['first_name']);
// ...
Liez correctement les colonnes aux tables

Lorsque vous joignez plusieurs tables, veillez à ne laisser aucun doute sur l’appartenance d’une colonne à l’une ou l’autre table; attention, je vous entends déjà me dire que, de toute façon, en cas d’ambiguité la requête ne s’exécutera pas, et c’est vrai; mais vous pouvez tout à fait lever l’ambiguité pour la machine, sans pour autant la lever pour le lecteur de votre code que vous êtes et qu’un autre sera peut-être plus tard :

SELECT
    c1.last_name, c1.first_name, c2.last_name, c2.first_name
FROM
    customer c1, customer c2, association ass
WHERE
    ass.parent_id = c1.id
    AND ass.child_id = c2.id

Cet exemple est un peu idiot, je suis le premier à le reconnaître (on peut notamment discuter de la pertinence d’une table telle que la table « association », ou encore du nom de ses champs), mais je rappellerai simplement qu’il vous arrivera de devoir travailler sur un projet déjà existant et que, parfois, vous devrez faire avec l’existant sans le modifier.

Dans cet exmple, donc, si idiot soit-il, il n’est pas évident, de prime abord, de déterminer quel client est l’enfant de l’autre (si c’est évident pour vous, imaginez un exemple plus complexe).

Comparez à ceci :

SELECT
    parent.last_name, parent.first_name, child.last_name, child.first_name
FROM
    customer parent, customer child, association ass
WHERE
    ass.parent_id = parent.id
    AND ass.child_id = child.id

Pour citer le grand philosophe Dany Boon :

Sur le plan grammatical, c’est déjà les vacances, non ?

Paramétrez vos requêtes

Il y a de nombreux intérêts à paramétrer vos requêtes, notamment :

  • les requêtes restent lisibles car vous ne les échappez pas sans arrêt pour y intégrer de variables;
  • votre applicatif se charge seul d’échapper vos données lorsque cela est nécessaire (si un de vos variables contient, par exemple, une apostrophe).

Chaque langage de programmation dispose de sa syntaxe pour paramétrer des requêtes SQL, reposant sur un système de placeholders à initialiser :

Par ex, en Java :

PreparedStatement ps = maConnexion.prepareStatement("UPDATE customers SET city = ? WHERE id = ?");
ps.setString(1,"PARIS");
ps.setInt(2,247);

fabriquera la requête suivante :

UPDATE customers SET city = 'PARIS' WHERE id = 247;

Laisser un commentaire

*