Démarrer la programmation fonctionnelle avec : Grokking Simplicity

Maxime Pawlak
7 min readApr 7, 2024
grokking Simplicity

Introduction

Cet article est la retranscription des 3 vidéos faites suite à la lecture du livre “grokking Simplicity”. Une playlist est disponible ici : https://www.youtube.com/watch?v=dBnvmmivKKE&list=PLG94xMtVhh28vgvLAaYA_aGZ23IF6uIe1

La 3e vidéo est un résumé (pour ceux qui n’ont pas le temps).

TL;DR

  1. Programmation Fonctionnelle (FP) : La FP se concentre sur l’utilisation de fonctions pures et l’évitement des états partagés et des effets secondaires pour simplifier le développement logiciel.
  2. Actions, Calculs, et Données : Distinction clé en FP, où les actions affectent le monde extérieur, les calculs transforment des entrées en sorties sans effet secondaire, et les données représentent des faits immuables.
  3. Immutabilité : La FP privilégie les données immuables pour éviter les bugs liés aux états changeants et faciliter le raisonnement sur le code.
  4. Extraction des Calculs : Transformer les actions en calculs et données pour améliorer la testabilité et la réutilisabilité du code.
  5. Design Stratifié : Organisation du code en couches d’abstraction pour clarifier la séparation des préoccupations et améliorer la modularité.
  6. Fonctions de Première Classe : En FP, les fonctions peuvent être passées en arguments, retournées par d’autres fonctions, ou assignées à des variables, offrant une grande flexibilité dans la composition du code.
  7. Fonctions d’Ordre Supérieur : Utilisation de fonctions qui prennent d’autres fonctions comme arguments ou les retournent, permettant des abstractions puissantes et une réduction de la duplication du code.
  8. Map, Filter, et Reduce : Trois outils essentiels en FP pour manipuler des collections de manière expressive et concise, transformant, filtrant, et résumant les données.
  9. Pragmatisme et Accessibilité : “Grokking Simplicity” montre comment la FP est applicable et bénéfique dans des scénarios de développement logiciel réels, indépendamment du langage de programmation utilisé.

Introduction à la Programmation Fonctionnelle

La programmation fonctionnelle (FP) est un paradigme de programmation centré sur l’utilisation de fonctions et l’évitement des états partagés et des effets secondaires. Contrairement aux approches impératives ou orientées objet, la FP se concentre sur le “quoi” plutôt que le “comment”, en décrivant les opérations comme des évaluations de fonctions plutôt que des instructions exécutées séquentiellement. Cette approche est inspirée des mathématiques et vise à augmenter la prévisibilité, la testabilité et la simplicité du code.

Actions, Calculs, et Données : La Triade Fondamentale

Actions

Les actions sont des opérations qui ont un effet sur le monde extérieur ou qui dépendent du contexte d’exécution. Elles peuvent modifier des états, écrire dans un fichier, ou envoyer une requête réseau. Bien que nécessaires, les actions introduisent de l’incertitude dans le code car leur résultat peut varier et elles peuvent avoir des effets secondaires imprévus. En FP, les actions sont isolées et gérées de manière à minimiser leur impact sur le système global.

Calculs

Les calculs sont des fonctions pures qui, pour un ensemble donné d’entrées, produiront toujours le même résultat sans modifier l’état extérieur. Cette prévisibilité rend les calculs faciles à tester, à raisonner et à réutiliser. En FP, une grande partie de la logique est exprimée sous forme de calculs pour tirer parti de ces propriétés.

Données

Les données sont traitées comme immuables dans la FP. Au lieu de modifier les données en place, les opérations fonctionnelles retournent de nouvelles instances de données modifiées. Cette approche réduit les bugs difficiles à tracer liés aux modifications d’état et facilite le raisonnement sur le code, car le flux de données à travers le système est plus clair et plus prévisible.

Distinguer et Appliquer ces Concepts

Extraire les Calculs des Actions

Un principe clé en FP est d’extraire les calculs des actions. Par exemple, considérons une fonction qui calcule le prix total d’une commande en appliquant une remise et en ajoutant des taxes. Si cette fonction lit également les données de la commande depuis une base de données (une action) et enregistre le résultat (une autre action), elle mélange calculs et actions, ce qui rend le test et la réutilisation difficiles.

En extrayant le calcul pur (calcul du prix total) dans sa propre fonction, on obtient une fonction pure facile à tester et à réutiliser dans différents contextes, sans se soucier des détails d’implémentation des actions.

Immutabilité des Données

L’immutabilité des données est un concept où toute modification d’une structure de données crée une nouvelle structure sans changer l’original. Cela élimine une classe entière de bugs liés à des états partagés et changeants, rendant le code plus sûr et plus prévisible. L’immutabilité facilite également la programmation concurrente, car il n’y a pas de conflits d’accès en écriture à gérer.

Design Stratifié

Le design stratifié en FP consiste à organiser le code en couches d’abstraction. Les calculs, étant des fonctions pures, forment le cœur de cette structure, avec des données immuables circulant entre eux. Les actions sont placées aux frontières du système, là où elles interagissent avec le monde extérieur.

Cette organisation clarifie la séparation des préoccupations, permettant aux développeurs de se concentrer sur la logique métier sans être distraits par les détails d’interaction avec l’environnement. En conséquence, le code devient plus modulaire, plus facile à tester et à maintenir.

La deuxième partie de la présentation “Grokking Simplicity” se concentre sur l’utilisation des abstractions de première classe, notamment les fonctions de première classe et les trois outils fonctionnels essentiels : map, filter et reduce. Cette section approfondit comment ces concepts peuvent transformer radicalement la façon dont nous écrivons et comprenons le code en adoptant une approche fonctionnelle.

Introduction aux Abstractions de Première Classe

Les abstractions de première classe en programmation fonctionnelle permettent d’exprimer les opérations logiques de manière plus flexible et réutilisable. En FP, une valeur de première classe est une entité qui peut être passée en argument, retournée par une fonction, ou assignée à une variable. Les fonctions, en tant que telles, sont traitées comme des valeurs de première classe, ce qui signifie qu’elles peuvent être manipulées avec la même facilité que les types de données primitifs. Cette capacité ouvre la porte à des techniques de composition et d’abstraction puissantes, où les fonctions peuvent être utilisées pour encapsuler non seulement des calculs mais aussi des comportements.

Fonctions de Première Classe et d’Ordre Supérieur

Fonctions de Première Classe

En FP, traiter les fonctions comme des valeurs de première classe permet une grande expressivité. Par exemple, une fonction peut être passée comme argument à une autre fonction, permettant des modèles de conception flexibles tels que les callbacks et les fonctions de rappel. Cela facilite la création de code modulaire et réutilisable, où les comportements spécifiques peuvent être injectés dans des opérations génériques.

Fonctions d’Ordre Supérieur

Les fonctions d’ordre supérieur prennent d’autres fonctions comme arguments ou les retournent. Cette caractéristique est au cœur de l’abstraction fonctionnelle, permettant aux développeurs de créer des fonctions génériques qui implémentent des algorithmes où seule une partie du comportement est spécifiée par la fonction passée en argument. Cela réduit la duplication du code et favorise un style de programmation déclaratif, où ce que doit faire le code est exprimé plutôt que comment il doit être fait.

Les Trois Outils Fonctionnels Essentiels : Map, Filter, et Reduce

Map

La fonction map applique une fonction donnée à chaque élément d'une collection, produisant une nouvelle collection de résultats. Elle incarne le principe de transformation de données sans mutation, essentiel en FP. map permet d'appliquer des calculs de manière isolée à des éléments de données, facilitant le raisonnement sur les opérations individuelles sans se préoccuper du contexte plus large.

Filter

filter sélectionne les éléments d'une collection qui satisfont à un prédicat donné, renvoyant une nouvelle collection composée uniquement de ces éléments. Cet outil est fondamental pour travailler avec des ensembles de données, permettant aux développeurs de déclarer facilement quelles données sont pertinentes pour un calcul ultérieur sans modifier la collection originale.

Reduce

La fonction reduce (aussi connue sous le nom de fold) consolide une collection en une seule valeur, en appliquant une fonction combinatoire aux éléments de la collection de manière séquentielle. reduce est extrêmement versatile, capable de modéliser une large gamme d'opérations, de la somme des éléments d'un tableau à la construction de structures de données plus complexes à partir d'une collection.

Application Pratique

L’utilisation de ces outils fonctionnels dans des scénarios réels peut significativement simplifier le traitement des collections de données. Par exemple, considérons un cas d’usage où il faut transformer une liste d’objets représentant des utilisateurs, filtrer ceux qui répondent à certains critères, puis résumer une propriété spécifique de l’ensemble filtré. En utilisant map, filter, et reduce, cette opération peut être exprimée de manière concise et lisible, avec chaque étape clairement identifiable et isolée des autres.

Conclusion

Les concepts de fonctions de première classe et d’ordre supérieur, ainsi que les outils fonctionnels map, filter, et reduce, représentent le cœur de la programmation fonctionnelle et offrent une puissante abstraction pour manipuler et transformer les données.

--

--

Maxime Pawlak

#dataScientist #techplorator #prototypeur #entrepreneur