Recommandations

Recommandations pour l'orienté-objet

Pas d'orienté-objet là où F♯ est bon

Inférence marche mieux avec une expression telle que fonction(objet) que objet.membre

Hiérarchie simple d'objets

  • ❌ Éviter héritage

  • ✅ Préférer type Union et pattern matching exhaustif, + simple en général

  • En particulier les types récursifs comme les arbres, épaulés par fonction fold

  • https://fsharpforfunandprofit.com/series/recursive-types-and-folds/

Égalité structurelle

  • ❌ Éviter classe (égalité par référence par défaut)

  • ✅ Préférer un Record ou une Union

  • ❓ Envisager égalité structurelle custom / performance

  • https://www.compositional-it.com/news-blog/custom-equality-and-comparison-in-f/

Orienté-objet recommandé

  1. Encapsuler état mutable → dans une classe

  2. Grouper fonctionnalités → dans une interface

  3. API expressive et user-friendly → méthodes tuplifiées

  4. API F♯ consommée en C♯ → membres d'extension

  5. Gestion des dépendances → injection dans constructeur

  6. Dépasser limites des fonctions d'ordre supérieur

Classe pour encapsuler un état mutable

Interface pour grouper des fonctionnalités

serialize et deserialize forment un groupe cohérent → Les grouper dans un objet

💡 Préférer une interface à un Record

  • Paramètres sont nommés dans les méthodes

  • Objet facilement instanciable avec une expression objet

API expressive

  • Méthode Add surchargée vs add2, add3

  • Une seule méthode Log avec paramètre optionnel retryPolicy

🔗 F♯ component design guidelines - Libraries used in C♯

API F♯ consommée en C♯ - Type

Ne pas exposer ce type tel quel :

💡 Pour faciliter la découverte du type et l'usage de ses fonctionnalités en C♯

  • Mettre le tout dans un namespace

  • Augmenter le type avec fonctionnalités du module compagnon

👉 L'API consommée en C♯ est +/- équivalente à :

Gestion des dépendances

Technique FP

Paramétrisation des dépendances + application partielle

  • Marche à petite dose : peu de dépendances, peu de fonctions concernées

  • Sinon, vite pénible à coder et à utiliser 🥱

Technique OO

Injection de dépendances

  • Injecter les dépendances dans le constructeur de la classe

  • Utiliser ces dépendances dans les méthodes

👉 Offre une API + user-friendly 👍

✅ Particulièrement recommandé pour encapsuler des effets de bord :

  • Connexion à une BDD, lecture de settings...

Techniques FP++

Dependency rejection = pattern sandwich

  • Rejeter dépendances dans couche Application, hors de couche Domaine

  • Puissant et simple 👍

  • ... quand c'est adapté ❗

Monade Reader

  • Pour fans de Haskell, sinon trop disruptif 😱

🔗 Six approaches to dependency injection, F# for Fun and Profit, Dec 2020

Limites des fonctions d'ordre supérieur

Mieux vaut passer un objet plutôt qu'une lambda en paramètre d'une fonction d'ordre supérieure dans certains cas :

Lambda est une commande 'T -> unit

  • ✅ Préférer déclencher un effet de bord via un objet : type ICommand = abstract Execute : 'T -> unit

Arguments de la lambda pas explicites

  • let test (f: float -> float -> string) =...

  • ✅ Solution 1 : type wrappant les 2 args float : f: Point -> string avec type Point = { X: float; Y: float }

  • ✅ Solution 2 : interface + méthode pour avoir paramètres nommés : type IXxx = abstract Execute : x:float -> y:float -> string

Lambda "vraiment" générique

✅ Solution : wrapper la fonction dans un objet

Mis à jour

Ce contenu vous a-t-il été utile ?