Dalla mia (ammessa limitata) esposizione a linguaggi di programmazione funzionale, come Clojure, sembra che l'incapsulamento dei dati abbia un ruolo meno importante. Di solito vari tipi nativi come mappe o set sono la valuta preferita per rappresentare i dati, rispetto agli oggetti. Inoltre, tali dati sono generalmente immutabili.
Ad esempio, ecco una delle citazioni più famose della fama di Rich Hickey of Clojure, in un'intervista sull'argomento :
Fogus: seguendo questa idea, alcune persone sono sorprese dal fatto che Clojure non si cimenta nell'incapsulamento dei dati sui suoi tipi. Perché hai deciso di rinunciare a nascondere i dati?
Hickey: chiariamo che Clojure enfatizza fortemente la programmazione alle astrazioni. Ad un certo punto, però, qualcuno dovrà avere accesso ai dati. E se hai una nozione di "privato", hai bisogno delle corrispondenti nozioni di privilegio e fiducia. E ciò aggiunge una tonnellata di complessità e poco valore, crea rigidità in un sistema e spesso costringe le cose a vivere in posti dove non dovrebbero. Ciò si aggiunge alle altre perdite che si verificano quando le informazioni semplici vengono inserite in classi. Nella misura in cui i dati sono immutabili, ci sono pochi danni che possono derivare dalla fornitura dell'accesso, oltre al fatto che qualcuno potrebbe arrivare a dipendere da qualcosa che potrebbe cambiare. Bene, okay, le persone lo fanno sempre nella vita reale e quando le cose cambiano si adattano. E se sono razionali, sanno quando prendono una decisione in base a qualcosa che può cambiare e che in futuro potrebbero aver bisogno di adattarsi. Quindi, è una decisione di gestione del rischio, una che penso che i programmatori dovrebbero essere liberi di prendere. Se le persone non hanno la sensibilità per desiderare di programmare le astrazioni e diffidare dal sposare i dettagli dell'implementazione, allora non saranno mai buoni programmatori.
Proveniente dal mondo OO, questo sembra complicare alcuni dei principi sanciti che ho imparato negli anni. Questi includono Information Hiding, Law of Demeter e Uniform Access Principle, per citarne alcuni. Il filo conduttore è che l'incapsulamento ci consente di definire un'API affinché gli altri sappiano cosa dovrebbero e non dovrebbero toccare. In sostanza, la creazione di un contratto che consente al manutentore di alcuni codici di apportare liberamente modifiche e refactoring senza preoccuparsi di come introdurre bug nel codice del consumatore (principio Open / Closed). Fornisce inoltre un'interfaccia pulita e curata per gli altri programmatori per sapere quali strumenti possono utilizzare per ottenere o basarsi su tali dati.
Quando è possibile accedere direttamente ai dati, il contratto API viene interrotto e tutti i vantaggi dell'incapsulamento sembrano scomparire. Inoltre, i dati strettamente immutabili sembrano rendere molto meno utile il passaggio di strutture specifiche del dominio (oggetti, strutture, record) nel senso di rappresentare uno stato e l'insieme di azioni che possono essere eseguite su quello stato.
In che modo le basi di codici funzionali affrontano questi problemi che sembrano sorgere quando le dimensioni di una base di codice aumentano in modo tale che le API devono essere definite e molti sviluppatori sono coinvolti nel lavorare con parti specifiche del sistema? Sono disponibili esempi di questa situazione che dimostrano come questo viene gestito in questo tipo di basi di codice?
Also, strictly immutable data seems to make passing around domain-specific structures (objects, structs, records) much less useful in the sense of representing a state and the set of actions that can be performed on that state.
Non proprio. L'unica cosa che cambia è che le modifiche finiscono su un nuovo oggetto. Questa è una grande vittoria quando si tratta di ragionare sul codice; passare oggetti mutabili significa dover tenere traccia di chi potrebbe mutarli, un problema che si ingrandisce con la dimensione del codice.