Modélisation avec les ADT
Rendre les états illégaux impossibles à représenter
Modélisation avec les ADT est une leçon Scala for Backend Engineering & Functional Programming gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Scala for Backend Engineering & Functional Programming, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Scala for Backend Engineering & Functional Programming comprend 4 leçons au total.
Types de données algébriques
Les types de données algébriques (ADT) sont le fondement de la modélisation fonctionnelle des domaines. Ils combinent les types produit (AND) et les types somme (OR) pour décrire les données avec précision.
- Produit : un enregistrement comportant plusieurs champs.
- Somme : un choix entre plusieurs variantes.
case class Point(x: Int, y: Int) // product type
object Main:
def main(args: Array[String]): Unit =
println(Point(1, 2))Types produit
Un type produit regroupe plusieurs valeurs. En Scala, une case class est un produit : une instance contient tous ses champs simultanément.
case class User(name: String, age: Int)
object Main:
def main(args: Array[String]): Unit =
val u = User("Ada", 36)
println(u.name)
println(u.age)Types somme
Un type somme est une valeur qui correspond exactement à l’une de plusieurs variantes. Les énumérations de Scala 3 l’expriment directement.
enum PaymentMethod:
case Cash
case Card(number: String)
case Crypto(wallet: String)
object Main:
def main(args: Array[String]): Unit =
val p: PaymentMethod = PaymentMethod.Card("1234")
println(p)Rendre les états illégaux impossibles à représenter
Le principe essentiel consiste à concevoir les types de sorte que les données invalides ne puissent même pas être construites. Si le système de types interdit un état incorrect, vous n’avez jamais besoin de le vérifier à l’exécution.
enum Connection:
case Disconnected
case Connected(sessionId: String)
object Main:
def main(args: Array[String]): Unit =
// No way to have a sessionId while Disconnected
val c: Connection = Connection.Connected("abc")
println(c)Mauvaise conception ou bonne conception
Un enregistrement plat avec des champs pouvant être nuls favorise les états illégaux. Modéliser chaque cas comme une variante permet de les éliminer.
- Mauvais :
case class Conn(connected: Boolean, sessionId: String)autorise connected=false avec un sessionId. - Bon : un type somme associe le champ à l’état approprié.
enum Door:
case Open
case Closed
case Locked(key: String)
object Main:
def main(args: Array[String]): Unit =
val d: Door = Door.Locked("k1")
println(d)Combiner produits et sommes
Les modèles réels imbriquent des produits dans des sommes, et inversement. Chaque variante peut contenir son propre produit de champs.
case class Address(city: String, zip: String)
enum Contact:
case Email(value: String)
case Postal(address: Address)
object Main:
def main(args: Array[String]): Unit =
val c: Contact = Contact.Postal(Address("Paris", "75001"))
println(c)Correspondance de motifs sur les ADT
Vous utilisez les ADT avec la correspondance de motifs. Comme le type est fermé, le compilateur vous avertit si vous oubliez une variante.
enum Shape:
case Circle(r: Double)
case Rect(w: Double, h: Double)
object Main:
def area(s: Shape): Double = s match
case Shape.Circle(r) => 3.14159 * r * r
case Shape.Rect(w, h) => w * h
def main(args: Array[String]): Unit =
println(area(Shape.Rect(2, 3)))ADT récursifs
Les ADT peuvent se référer à eux-mêmes, ce qui permet de modéliser naturellement les arbres, les listes et les expressions.
enum Expr:
case Num(value: Int)
case Add(left: Expr, right: Expr)
object Main:
def eval(e: Expr): Int = e match
case Expr.Num(v) => v
case Expr.Add(l, r) => eval(l) + eval(r)
def main(args: Array[String]): Unit =
val e = Expr.Add(Expr.Num(2), Expr.Num(3))
println(eval(e))Gérer l’absence avec Option
Utilisez Option plutôt que null pour modéliser un champ potentiellement absent. Le type rend l’absence explicite et impose sa gestion.
case class Profile(name: String, nickname: Option[String])
object Main:
def main(args: Array[String]): Unit =
val p = Profile("Grace", None)
println(p.nickname.getOrElse("(none)"))Modéliser précisément les quantités
Évitez l’obsession des types primitifs. Au lieu d’utiliser des Int et des String bruts, encapsulez les quantités porteuses de sens afin que les types documentent l’intention et évitent les confusions.
case class Quantity(value: Int)
case class Price(cents: Long)
case class LineItem(qty: Quantity, price: Price)
object Main:
def main(args: Array[String]): Unit =
val item = LineItem(Quantity(3), Price(500))
println(item)Pourquoi les ADT sont importants
Les ADT vous apportent fiabilité et clarté.
- Les états invalides ne peuvent pas être construits.
- La correspondance exhaustive détecte les cas oubliés lors de la compilation.
- La structure des données documente le domaine.
enum OrderStatus:
case Pending
case Shipped(tracking: String)
case Delivered(at: Long)
object Main:
def main(args: Array[String]): Unit =
val s: OrderStatus = OrderStatus.Shipped("TRK1")
println(s)Vérification rapide
Vérifiez votre compréhension de la modélisation fondée sur les ADT.
Récapitulatif
Vous avez appris à modéliser un domaine avec des ADT.
- Les types produit (
case class) combinent des champs avec AND. - Les types somme (
enum) proposent un choix avec OR. - Imbriquez-les pour modéliser des domaines riches et des structures récursives.
- Utilisez
Optionplutôt que null. - Concevez vos types de sorte que les états illégaux ne puissent pas être représentés.
enum Event:
case Created(id: Int)
case Deleted(id: Int, reason: String)
object Main:
def describe(e: Event): String = e match
case Event.Created(id) => s"created $id"
case Event.Deleted(id, reason) => s"deleted $id: $reason"
def main(args: Array[String]): Unit =
println(describe(Event.Deleted(1, "spam")))Apprends Scala avec un tuteur IA — gratuit
Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.
- Cours
- 39
- Leçons
- 143
Questions Fréquemment Posées
La leçon « Modélisation avec les ADT » est-elle gratuite ?
Oui — le texte complet de « Modélisation avec les ADT » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Scala for Backend Engineering & Functional Programming, passe à CoddyKit PRO. Le cours Scala for Backend Engineering & Functional Programming comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Modélisation avec les ADT » ?
Rendre les états illégaux impossibles à représenter Tu pratiques Scala for Backend Engineering & Functional Programming avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Scala for Backend Engineering & Functional Programming ?
Aucune expérience préalable n'est requise. Scala for Backend Engineering & Functional Programming sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.
Combien de temps prend la leçon « Modélisation avec les ADT » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Scala for Backend Engineering & Functional Programming ?
Oui. Chaque leçon Scala for Backend Engineering & Functional Programming inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Modélisation avec les ADT
- Constructeurs intelligents
- Nouveaux types
- Composition des domaines