TW3 — Technologies du Web 3

La couche modèle

Rôle du modèle dans une architecture MVC, validation des données, distinction entre services et contrôleurs, et pourquoi ne pas écrire de SQL dans un contrôleur.

Le modèle est le cœur de l'application : c'est lui qui sait ce qu'est une donnée, comment elle se valide et comment on y accède. Bien isolé, il rend le reste du code plus simple et plus sûr.

🎯 Le rôle du modèle

Un modèle porte trois responsabilités :

  • décrire la structure d'une donnée (ses champs, ses types) ;
  • valider les entrées avant de toucher à la base ;
  • accéder aux données (lecture, écriture, recherche).
// models/article.js
export function validateArticle(data) {
  const errors = []
  if (typeof data.titre !== "string" || data.titre.length === 0)
    errors.push("Le titre est requis.")
  if (typeof data.prix !== "number" || data.prix < 0)
    errors.push("Le prix doit être un nombre positif.")
  return errors
}

✅ Valider au plus tôt

Validez à la frontière (quand les données entrent), pas au milieu d'une requête SQL. Cela évite les données corrompues et les erreurs difficiles à tracer.

Ne faites confiance à aucune donnée venant du client. Toujours valider req.body avant de l'insérer ou de l'utiliser.

🧩 Services vs contrôleurs

Ces deux couches sont souvent confondues. Voici la distinction :

CoucheParle HTTP ?Contient l'accès BDD ?Réutilisable hors web ?
ContrôleurOuiNon (délègue)Non
ServiceNonNon (appelle le modèle)Oui
ModèleNonOuiOui
// services/articleService.js
import { Article } from "../models/article.js"

export async function publierArticle(data) {
  const errors = Article.validate(data)
  if (errors.length) throw new Error(errors.join(" "))
  return Article.create({ ...data, publieLe: new Date() })
}

Le service contient la règle « publier = valider + horodater ». Le contrôleur se contente d'appeler publierArticle et de renvoyer le résultat.

🚫 Pas de SQL dans le contrôleur

Mélanger SQL et logique HTTP crée trois problèmes :

  • le contrôleur devient énorme et illisible ;
  • la même requête est dupliquée à plusieurs endroits ;
  • on ne peut pas tester la logique sans démarrer un serveur.
// ❌ À éviter
app.post("/articles", async (req, res) => {
  const { titre, prix } = req.body
  await db.query("INSERT INTO articles (titre, prix) VALUES ($1, $2)", [titre, prix])
  res.status(201).json({ ok: true })
})
// ✅ Préférer
app.post("/articles", async (req, res) => {
  try {
    const article = await publierArticle(req.body) // service
    res.status(201).json(article)
  } catch (e) {
    res.status(400).json({ error: e.message })
  }
})

➡️ Suite

La page Introduction aux ORM montre comment déléguer l'accès aux données à un ORM au lieu d'écrire du SQL.

Quiz du chapitre

5 questions
0 / 5 répondue0%
  1. 1Où doit-on valider les données venant du client ?
  2. 2Quelle couche est réutilisable hors d'un contexte web ?
  3. 3Pourquoi éviter le SQL direct dans un contrôleur ?
  4. 4Qui porte l'accès à la base de données dans une architecture MVC propre ?
  5. 5Que contient typiquement un service ?
Répondez à toutes les questions pour valider.

MVC & ORM

Terminez le quiz du chapitre pour le marquer comme complété.

Tableau de bord

On this page