Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Philosophie Fonctionnelle - Meetup CraftingSw Paris 2016

Philosophie Fonctionnelle - Meetup CraftingSw Paris 2016

Et si, au lieu d'essayer de vous présenter les outils du paradigme fonctionnel, et si nous parlions de la façon de "penser en fonctionnel" ?
Et si, nous expliquions le paradigme et non une implémentation spécifique ?
Et si, on parlais enfin des fondemements de ce paradigme ?

Contrairement à trop de présentation sur la programmation fonctionnel, découvrez ce paradigme à travers son modèle de pensée et non de ses outils.

Une présentation accessible à tous, garantie sans jargon ou concepts complexes pour un usage du fonctionnel au quotidien.

Beb422437c1dfb5366f197919e41ac50?s=128

Arnaud LEMAIRE
PRO

December 19, 2016
Tweet

Transcript

  1. Philosophie Fonctionnelle

  2. None
  3. Philosophie Fonctionnelle Arnaud LEMAIRE | @lilobase

  4. Les paradigmes ne sont pas mutuellement exclusifs Impératif Objet Fonctionnel

  5. C’est quoi un état ?

  6. Une valeur qui change en fonction du temps let variable;


    
 variable = "foo";
 console.log(variable);
 
 variable = "bar";
 console.log(variable); "foo" "bar" temps
  7. Et les problèmes arrivent quand on multiplie les sources de

    modifications "foo" "bar" invalid value context A context B
  8. Une source infinie de bugs…

  9. C’est pourquoi votre debogueur est une machine à remonter le

    temps
  10. Très souvent vous avez un gros entrepôt à état pour

    toute l’application La base de donnée (on en reparlera…)
  11. Et ne parlons pas des problèmes de concurrences

  12. La programmation fonctionnelle supprime le temps de l’équation temps x

    valeur = variable valeur = constante
  13. variable constante Sans empêcher une valeur de changer dans le

    temps
  14. variable constante Sans empêcher une valeur de changer dans le

    temps
  15. variable constante Sans empêcher une valeur de changer dans le

    temps
  16. -Michael Feathers « OO makes code understandable by encapsulating moving

    parts. FP makes code understandable by minimizing moving parts »
  17. C’est quoi la différence entre une valeur et une fonction

    ?
  18. valeur accessible « plus tard » = fonction La fonction

    n'est qu'une constante dont le contenus est disponible « plus tard » valeur accessible maintenant = constante const hello = "world"; const pow2 = (x) => x ** 2;
  19. Cela permet notamment l’évaluation paresseuse (lazy evaluation) Au lieu d’avoir

    un accès immédiat à une valeur const result = 
 heavy_process(some, args); const lazy_result = () => 
 heavy_process(some, args); L’on place la valeur au sein d’une fonction
  20. Fonction et valeur sont donc considérées à égalité L’on peut

    manipuler les fonction comme des valeurs = fonctions d’ordre supérieures const pow = x => y => y ** x;
 const pow3 = pow(3);
 console.log(pow3(3)); //print 27
  21. Fonction et valeur sont donc considérées à égalité Calculée, une

    fonction peut être remplacée par une constante = mémoïzation const memoize = (f) => {
 const memo = {};
 return (...args) => (args in memo) ? 
 memo[args] : (memo[args] = f(...args));
 };
 
 const add = (x, y) => x + y;
 const memoized_add = memoize(add);
 memoized_add(3, 4);
  22. Constantes et fonctions sont considérés à « équivalence » La

    différence se trouve l’immédiateté de l’accès à l’information contenue dans la référence associée
  23. C’est quoi un objet ?

  24. En poo les types sont très souvent associés à des

    structures de données nommées Les types en Orienté Objet, le typage « nominatif » Il n’y a pas de différence entre la « forme » de la donnée et ses comportements circle = Circle.new(5, 7, 15) circle.move(3, 10)
 circle.scale(20) Deux types sont égaux si ils portent le même nom
  25. Il était des fonctions qui partageaient des pointeurs function copyF($fromPath,

    $toPath) {
 $fromHandle = fopen($fromPath, 'r');
 $toHandle = fopen($toPath, 'w+');
 $contentToCopy = fread(
 $fromHandle, filesize($fromPath));
 fwrite($toHandle, $contentToCopy);
 } 
 function copyO($fromPath, $toPath) {
 $from = new SplFileObject($fromPath);
 $to = new SplFileObject($toPath);
 $content = $from->fread($from->getSize());
 $to->fwrite($content);
 }
  26. Une map de fonctions ? const triangle = {
 


    rotate: (d) => (…),
 
 move: (x, y) => (…),
 
 //...
 };
  27. Un ensemble de fonction qui reçoivent le même paramètre ?

    class Triangle:
 
 def rotate(self, degrees):
 //...
 
 def move(self, x, y):
 //...
 
 //...
  28. Une map de fonctions appliquées partiellement sur une même référence

    const square = (l, x, y) => {
 const that = [l, x, y];
 
 const rotate = (self, d) => (…);
 const move = (self, x, y) => (…);
 
 return {
 rotate: (d) => rotate(that, d),
 move: (x, y) => move(that, x, y)
 //...
 }
 };
 
 const obj = square(5, 10, 15);
 obj.rotate(…);
  29. C’est pourquoi l’objet peut être exprimé en fonctionnel mais pas

    l’inverse Un langage fonctionnel pourra toujours exprimer la notion « d’objet », mais un langage objet ne garantie pas la possibilité d’utiliser un style fonctionnel (La plupart des langages possèdent maintenant des constructions fonctionnelles)
  30. -Douglas Crockford « I'm now thinking I've got two completely

    different types of objects: those containing only data, which are things I share with JSON; and things containing only methods, which are things I can share with applications »
  31. Quelles différences entre l’objet et le fonctionnel ?

  32. Les objets proposent une interface à des types de données

    « complexes » La poo repose sur des structures de données « intelligentes » Le style fonctionnelle utilise très peu de type différents manipulé par des fonctions génériques circle = Circle.new(5, 7, 15)
 circle.move(3, 10)
 circle.scale(20) circle = [5, 7, 15]
 move_to(circle, 3, 10)
 scale(circle, 20)
  33. Ce qui permet d’exprimer un algorithme complex qu’en composant des

    fonctions existantes Ces fonctions génériques peuvent être composés entre elles move_to_and_scale = -> (circle) { 
 move_to(scale(circle, 20), 3, 10) 
 }
  34. Un objet est de la donnée sur laquelle l’on va

    venir appliquer du comportement La closure est une « inverse » d’objet Une closure est du comportement qui attend de la donnée circle = Circle.new(5, 7, 15)
 circle.move(3, 10) move_to_parametrized = ->(x, y) {
 -> (circle) { move_to(circle, x, y) }}
 circle = [5, 7, 15]
 move_to_5_15 = move_to_parametrized(5, 15);
 move_to_5_15(circle)
  35. Le pattern matching est une sorte d’inverse du polymorphisme type

    'a tree = | Node of 'a tree * 'a * 'a tree | Leaf;; let rec fold_tree f a t = match t with | Leaf -> a | Node (l, x, r) -> f x (fold_tree f a l) (fold_tree f a r);; Le pattern matching permet d’adapter un comportement en se basant sur la structure ou le type de la donnée
  36. Smart data-types vs smart functions La programmation fonctionnelle possède des

    structure de donnée très simple, sur lesquelles des fonctions vont pouvoir adapter leurs comportement
  37. -Alan Perlis « It is better to have 100 functions

    operate on one data structure than 10 functions on 10 data structures »
  38. C’est quoi une fonction ?

  39. Considérer son logiciel comme un ensemble de fonctions de transformations

    Ensemble de départ Ensemble d’arrivé fonction Type de départ Type d’arrivée
  40. En programmation fonctionnelle le système de type représente une «

    forme » (une structure) de donnée Les types en fonctionnel, le typage structurel Toute fonction acceptant une pair d’entier sera compatible avec ce type type pair_of_ints = { a : int; b : int };;
  41. Les types algébriques permettent de réaliser des produits et des

    sommes de types Les types en fonctionnelle, le typage algébrique type Suit = Spades | Hearts | Clubs | Diamonds type Rank = Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten | Jack | Queen | King | Ace type Card = Rank * Suit type Deck = Card list
  42. Qui peuvent être combinées ensemble f() g() compose(f,g) type A

    type B type C type A type C
  43. Typage structurel & algébrique En séparant les types des comportements

    associés et en permettant la combinaison de type, les langages fonctionnels permettent de représenter plus facilement des situations métiers plus complexes
  44. Ok, mais moi demain je fais quoi ?

  45. Immutabilité partout Eviter les mutations dans son code const constant

    = "everywhere"; Même pour les boucles (ça se remplace très bien par le trio : map, reduce, filter)
  46. Eviter les mutations dans son code Créez une nouvelle valeur

    depuis un objet : 
 class Circle 
 def initialize r, x, y
 @r = r
 @x = x
 @y = y
 end
 
 def move x, y
 Circle.new(@r, @x + x, @y + y)
 end
 end
  47. Eviter les mutations dans son code Créez une nouvelle valeur

    avec un reducer function todos(state = [], action) {
 switch (action.type) {
 case ADD_TODO:
 return [
 ...state,
 {
 text: action.text,
 completed: false
 }
 ]
 case TOGGLE_TODO:
 return state.map((todo, index) => {
 if (index === action.index) {
 return Object.assign({}, todo, {
 completed: !todo.completed
 })
 }
 return todo
 })
 default:

  48. Utilisez des types algébriques Ça existe même en javascript… (tcomb)

    const Min = t.refinement(
 t.String, (s) => s.length > 2);
 const Max = t.refinement(
 t.String, (s) => s.length < 5);
 
 const MinMax = t.intersection([Min, Max]);
 
 MinMax.is('abc'); // => true
 MinMax.is('a'); // => false
 MinMax.is('abcde'); // => false
  49. Ils sont indépendant, conservent leur propre état et communiquent via

    des messages immutable Utiliser des acteurs
  50. Isolez les parties impératives Functional core / Imperative shell Business

    domain (functional) Utilisez des objets valeurs pour faire l’échange entre les deux couches
  51. Commencez à utiliser de l’Event Sourcing

  52. Merci Arnaud LEMAIRE | @lilobase