En fait, le code OO est beaucoup moins réutilisable, et c'est par conception. L'idée derrière la POO est de restreindre les opérations sur des éléments de données particuliers à un certain code privilégié qui se trouve soit dans la classe, soit à l'endroit approprié dans la hiérarchie d'héritage. Cela limite les effets néfastes de la mutabilité. Si une structure de données change, il n'y a que peu d'endroits dans le code qui peuvent être responsables.
Avec l'immuabilité, vous ne vous souciez pas de savoir qui peut opérer sur une structure de données donnée, car personne ne peut modifier votre copie des données. Cela facilite la création de nouvelles fonctions pour travailler sur les structures de données existantes. Il vous suffit de créer les fonctions et de les regrouper en modules qui semblent appropriés du point de vue du domaine. Vous n'avez pas à vous soucier de leur emplacement dans la hiérarchie d'héritage.
L'autre type de réutilisation de code consiste à créer de nouvelles structures de données pour travailler sur les fonctions existantes. Ceci est géré dans des langages fonctionnels utilisant des fonctionnalités comme les génériques et les classes de types. Par exemple, la classe de type Ord de Haskell vous permet d'utiliser la sort
fonction sur n'importe quel type avec une Ord
instance. Les instances sont faciles à créer si elles n'existent pas déjà.
Prenez votre Animal
exemple et envisagez d'implémenter une fonction d'alimentation. L'implémentation POO simple consiste à maintenir une collection d' Animal
objets et à parcourir tous ces éléments, en appelant la feed
méthode sur chacun d'eux.
Cependant, les choses deviennent délicates lorsque vous descendez dans les détails. Un Animal
objet sait naturellement quel type de nourriture il mange et combien il a besoin pour se sentir rassasié. Il ne sait pas naturellement où la nourriture est conservée et combien est disponible, donc un FoodStore
objet vient de devenir une dépendance de chacun Animal
, soit en tant que champ de l' Animal
objet, soit transmis en tant que paramètre de la feed
méthode. Alternativement, pour garder la Animal
classe plus cohérente, vous pouvez vous déplacer feed(animal)
vers l' FoodStore
objet, ou vous pouvez créer une abomination d'une classe appelée un AnimalFeeder
ou un tel.
Dans FP, il n'y a aucune tendance à ce que les champs d'un Animal
restent toujours regroupés, ce qui a des implications intéressantes pour la réutilisabilité. Disons que vous avez une liste de Animal
dossiers, avec des domaines comme name
, species
, location
, food type
, food amount
, etc. Vous avez également une liste des FoodStore
enregistrements avec des champs tels que location
, food type
et food amount
.
La première étape de l'alimentation pourrait consister à faire correspondre chacune de ces listes d'enregistrements à des listes de (food amount, food type)
paires, avec des nombres négatifs pour les quantités des animaux. Vous pouvez ensuite créer des fonctions pour faire toutes sortes de choses avec ces paires, comme additionner les quantités de chaque type de nourriture. Ces fonctions n'appartiennent pas parfaitement à un Animal
ou à un FoodStore
module, mais sont hautement réutilisables par les deux.
Vous vous retrouvez avec un tas de fonctions qui font des choses utiles avec [(Num A, Eq B)]
qui sont réutilisables et modulaires, mais vous avez du mal à savoir où les mettre ou comment les appeler en tant que groupe. L'effet est que les modules FP sont plus difficiles à classer, mais la classification est beaucoup moins importante.