D'après mon exposition (certes limitée) aux langages de programmation fonctionnels, tels que Clojure, il semble que l'encapsulation des données ait un rôle moins important. Habituellement, divers types natifs tels que des cartes ou des ensembles sont la devise préférée pour représenter les données, par rapport aux objets. En outre, ces données sont généralement immuables.
Par exemple, voici l'une des citations les plus célèbres de la renommée de Rich Hickey of Clojure, dans une interview à ce sujet :
Fogus: Suite à cette idée, certaines personnes sont surprises par le fait que Clojure ne s'engage pas dans l'encapsulation de masquage de données sur ses types. Pourquoi avez-vous décidé de renoncer à la dissimulation de données?
Hickey: Soyons clairs, Clojure met fortement l'accent sur la programmation des abstractions. À un moment donné cependant, quelqu'un devra avoir accès aux données. Et si vous avez une notion de «privé», vous avez besoin des notions correspondantes de privilège et de confiance. Et cela ajoute une tonne de complexité et peu de valeur, crée de la rigidité dans un système et oblige souvent les choses à vivre dans des endroits où elles ne devraient pas. Ceci s'ajoute à l'autre perte qui se produit lorsque de simples informations sont mises dans les classes. Dans la mesure où les données sont immuables, il y a peu de mal à fournir l'accès, à part le fait que quelqu'un pourrait en venir à dépendre de quelque chose qui pourrait changer. Bon, d'accord, les gens font ça tout le temps dans la vraie vie, et quand les choses changent, ils s'adaptent. Et s'ils sont rationnels, ils savent quand ils prennent une décision basée sur quelque chose qui peut changer qu'ils pourraient à l'avenir devoir s'adapter. C'est donc une décision de gestion des risques, une décision que les programmeurs devraient être libres de prendre. Si les gens n'ont pas la sensibilité de vouloir programmer des abstractions et de se méfier des détails d'implémentation, alors ils ne seront jamais de bons programmeurs.
Venant du monde OO, cela semble compliquer certains des principes consacrés que j'ai appris au fil des ans. Il s'agit notamment de la dissimulation d'informations, de la loi de Déméter et du principe d'accès uniforme, pour n'en nommer que quelques-uns. Le fil conducteur étant que l'encapsulation nous permet de définir une API pour que les autres sachent ce qu'ils doivent et ne doivent pas toucher. Essentiellement, la création d'un contrat qui permet au mainteneur d'un code d'effectuer librement des modifications et des refactorings sans se soucier de la façon dont il pourrait introduire des bogues dans le code du consommateur (principe ouvert / fermé). Il fournit également une interface propre et organisée permettant aux autres programmeurs de savoir quels outils ils peuvent utiliser pour accéder à ces données ou les développer.
Lorsque l'accès direct aux données est autorisé, ce contrat d'API est rompu et tous ces avantages d'encapsulation semblent disparaître. De plus, les données strictement immuables semblent rendre le contournement des structures spécifiques au domaine (objets, structures, enregistrements) beaucoup moins utile dans le sens de représenter un état et l'ensemble des actions qui peuvent être effectuées sur cet état.
Comment les bases de code fonctionnelles répondent-elles à ces problèmes qui semblent survenir lorsque la taille d'une base de code augmente énormément, de sorte que les API doivent être définies et que de nombreux développeurs sont impliqués dans le travail avec des parties spécifiques du système? Existe-t-il des exemples de cette situation qui montrent comment cela est géré dans ce type de bases de code?
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.
Pas vraiment. La seule chose qui change, c'est que les modifications aboutissent sur un nouvel objet. C'est une énorme victoire quand il s'agit de raisonner sur le code; faire passer des objets mutables signifie avoir à garder une trace de qui pourrait les muter, un problème qui évolue avec la taille du code.