In realtà, il codice OO è molto meno riutilizzabile, e questo è di progettazione. L'idea alla base di OOP è limitare le operazioni su particolari parti di dati a un determinato codice privilegiato che si trova nella classe o nella posizione appropriata nella gerarchia dell'ereditarietà. Ciò limita gli effetti avversi della mutabilità. Se una struttura di dati cambia, ci sono solo così tante posizioni nel codice che possono essere responsabili.
Con l'immutabilità, non ti importa chi può operare su una data struttura di dati, perché nessuno può modificare la tua copia dei dati. Ciò rende molto più semplice la creazione di nuove funzioni per lavorare su strutture di dati esistenti. Basta creare le funzioni e raggrupparle in moduli che sembrano appropriati dal punto di vista del dominio. Non devi preoccuparti di dove inserirli nella gerarchia dell'eredità.
L'altro tipo di riutilizzo del codice sta creando nuove strutture di dati per lavorare su funzioni esistenti. Questo è gestito in linguaggi funzionali usando funzionalità come generici e classi di tipi. Ad esempio, la classe di tipi Ord di Haskell consente di utilizzare la sort
funzione su qualsiasi tipo con Ord
un'istanza. Le istanze sono facili da creare se non esistono già.
Fai il tuo Animal
esempio e considera di implementare una funzione di alimentazione. L'implementazione OOP semplice è quella di mantenere una raccolta di Animal
oggetti e di eseguirne il ciclo tutti, chiamando il feed
metodo su ciascuno di essi.
Tuttavia, le cose si complicano quando si arriva ai dettagli. Un Animal
oggetto naturalmente sa che tipo di cibo mangia e di quanto ha bisogno per sentirsi pieno. Essa non naturalmente sa dove il cibo è conservato e quanto è disponibile, quindi un FoodStore
oggetto è appena diventato una dipendenza di ogni Animal
, sia come campo Animal
oggetto o passato come parametro del feed
metodo. In alternativa, per mantenere la Animal
classe di più coesa, si potrebbe spostare feed(animal)
l' FoodStore
oggetto, o si potrebbe creare un abominio di una classe chiamato AnimalFeeder
o qualcosa del genere.
In FP, non vi è alcuna inclinazione per i campi di Animal
rimanere sempre raggruppati, il che ha alcune interessanti implicazioni per la riusabilità. Diciamo che avere una lista di Animal
record, con campi come name
, species
, location
, food type
, food amount
, ecc Hai anche un elenco di FoodStore
record con campi come location
, food type
e food amount
.
Il primo passo per l'alimentazione potrebbe essere quello di mappare ciascuno di quegli elenchi di record su elenchi di (food amount, food type)
coppie, con numeri negativi per le quantità degli animali. È quindi possibile creare funzioni per fare ogni sorta di cose con queste coppie, come sommare le quantità di ciascun tipo di cibo. Queste funzioni non appartengono perfettamente a uno Animal
o un FoodStore
modulo, ma sono altamente riutilizzabili da entrambi.
Finisci con un mucchio di funzioni che fanno cose utili [(Num A, Eq B)]
riutilizzabili e modulari, ma hai difficoltà a capire dove metterle o come chiamarle come gruppo. L'effetto è che i moduli FP sono più difficili da classificare, ma la classificazione è molto meno importante.