L'intérêt du

typage statique

Jeroen Engels (Yeuroune)

L'intérêt du

typage statique avec

Jeroen Engels (Yeuroune)

Pourquoi               ?

Langage fonctionnel pur

Garantit aucun crash

Pour applications web

C'est quoi le typage ?

Type = Ensemble de valeurs possibles

age : Int
age = 30

nom : String
nom = "Jeroen Engels"

Typage dynamique

Dynamique : Vérification au cours de l'exécution (JavaScript, Python, Clojure, ...)

# Python

>>> "string" + 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects

Typage statique

Statique : Vérifiés avant l'exécution​

(Elm, Haskell, Java, C, ...)

Syntaxe Elm

Déclaration de fonctions

maFonction : TypeParametre1 -> TypeParametre2 -> TypeDeRetour
maFonction parametre1 parametre2 =
    valeurDeLaFonction

Appel de fonctions

variable : Type
variable =
  maFonction argument1 argument2

Définition de type

type alias Prenom = String

type alias Nom =
  { prenom : Prenom
  , age : Int
  }

type Sexe
  = Homme
  | Femme
  | Autre String

Intérêts du typage statique

Trouver des erreurs tôt

quantite : Int
quantite = "100" -- NON!

Trouver des erreurs tôt

Maintenabilité

"Ça compile, donc ça marche"

Moins de tests

Seulement sur la logique métier

Documentation

Toujours à jour

prenom : String -- Garanti par le compilateur
prenom =
  "Jeroen"
  

-- Si jamais on change
prenom : String
prenom =
  1000 -- Erreur de compilation
  

Fournit une documentation minimale, même si le code est compliqué

a : (Nom -> Nom) -> User -> User
a b c =
  d (b (e c)) c

Délimite les possibilités

addition : Int -> Int -> Int

nomUtilisateur : User -> String

modifiePrenom : Prenom -> User -> User

Créer des garanties

Créer nos propres types

Créer nos propres contraintes

=

Garantie

Contrainte

=

Contrainte : pas de null en Elm

 Garantie : Toute valeur annoncée est vraiment présente et utilisable

=

(pas de NullPointerException)

Modélisation de données

type alias RequeteAuServeur data =
  { enCours : Bool
  , enErreur : Bool
  , données : Maybe data
  }
maRequete : RequeteAuServeur String
maRequete =
  { enCours = True
  , enErreur = True
  , données = Just "Jeroen"
  }

Custom types

type RequeteAuServeur data
  = NonDemarree
  | EnCours
  | EnErreur
  | EnSucces data

Making Impossible States Impossible

par Richard Feldman

"Ça ne résoud pas mes

problèmes de logique métier"

Problèmes de logique métier

 

 

Problèmes de types

type alias User =
  { nom : String
  -- "admin" ou "user"
  , role : String
  }

peutSupprimerBaseDeDonnees : User -> Bool
peutSupprimerBaseDeDonnees user =
    if user.role == "user" then
        False
    else
        True

user : User
user =
  { nom = "Jeroen Engels"
  , role = "User"
  }
type alias User =
  { nom : String
  , role : Role
  }

type Role
  = Admin
  | User

peutSupprimerBaseDeDonnees : User -> Bool
peutSupprimerBaseDeDonnees user =
    case user.role of
    	Admin -> True
    	User -> False

Mélanger des valeurs similaires

type alias User =
  { login : String
  , motDePasse : String
  }

modifieMotDePasse : String -> User -> User
modifieMotDePasse motDePasse user =
  { user | login = motDePasse }

Éviter "primitive obsession"

type alias User =
  { login : Login
  , motDePasse : MotDePasse
  }

type Login
  = Login String

type MotDePasse
  = MotDePasse String

modifieMotDePasse : MotDePasse -> User -> User
modifieMotDePasse motDePasse user =
  { user | login = motDePasse } -- Erreur

Valeurs de types primitifs

Garantir un mot de passe fort

type alias User =
  { motDePasse : MotDePasse
  }

type MotDePasse
  = MotDePasse String

modifieMotDePasse : MotDePasse -> User -> User
modifieMotDePasse motDePasse user =
  { user | motDePasse = motDePasse }

utilisateurAvecMotDePasse =
  modifieMotDePasse (MotDePasse "a") utilisateur
module MotDePasse exposing
  (MotDePasse, fromString, comparer)
-- Ne pas faire MotDePasse(..)

type MotDePasse
  = MotDePasse String
  
{-| Si mdp est fort, alors retourne Just mdp, sinon Nothing -}
fromString : String -> Maybe MotDePasse

comparer : String -> MotDePasse -> Bool

Mot de passe fort avec des types opaques

Mot de passe fort avec des types opaques

import MotDePasse exposing (MotDePasse)

modifieMotDePasse : MotDePasse -> User -> User
modifieMotDePasse motDePasse user =
  { user | motDePasse = motDePasse }

utilisateurAvecMotDePasse =
  case MotDePasse.fromString "a" of
    Just mdp -> 
      modifieMotDePasse mdp utilisateur
    Nothing -> 
      utilisateur

Types opaques

Permet aussi de limiter les

opérations permises sur un type

Exiger des données

-- Rendre Preuve opaque
type Preuve = Preuve

type Role
  = Admin Preuve
  | User

supprimerBaseDeDonnees : Preuve -> DemandeDeSuppression

etc...

Jeroen Engels (Yeuroune)

jfmengels sur le Slack Elm

https://slides.com/jeroenengels/typage-statique-esgi

https://guide.elm-lang.org/

Apprendre

Slides :

elm-radio.com

Made with Slides.com