Dans cette vidéo de Rich Hickey , le créateur de Clojure, il conseille d'utiliser la carte pour représenter les données au lieu d'utiliser une classe pour les représenter, comme cela est fait en Java. Je ne comprends pas comment cela peut être mieux, car comment l'utilisateur de l'API peut-il savoir quelles sont les clés d'entrée si elles sont simplement représentées sous forme de cartes.
Exemple :
PersonAPI {
Person addPerson(Person obj);
Map<String, Object> addPerson(Map<String, Object> personMap);
}
Dans la deuxième fonction, comment l'utilisateur de l'API peut-il savoir quelles sont les entrées pour créer une personne?
Réponses:
Résumé Exagg'itive (TM)
Vous obtenez quelques choses.
Il y a un inconvénient fatal.
Le fait est que vous pouvez obtenir une introspection en utilisant, euh, l'introspection. C'est ce qui se produit généralement:
En d'autres termes, si vous n'avez jamais besoin d'interfacer avec FP, vous n'avez pas à suivre les conseils de Rich Hickey.
Dernier point, mais pas le moindre (ni le plus joli), bien que l'utilisation
String
comme clé de propriété ait le sens le plus simple, vous n'avez pas besoin d'utiliser leString
s. De nombreux systèmes hérités, y compris Android ™, utilisent largement les identifiants entiers dans l'ensemble du cadre pour faire référence aux classes, propriétés, ressources, etc.Android est une marque déposée de Google Inc.
Vous pouvez également rendre les deux mondes heureux.
Pour le monde Java, implémentez les getters et setters comme d'habitude.
Pour le monde de la PF, implémentez le
Object getPropertyByName(String name)
void setPropertyByName(String name, Object value) throws IllegalPropertyChangeException
List<String> getPropertyNames()
Class<?> getPropertyValueClass(String name)
À l'intérieur de ces fonctions, oui, du code laid, mais il y a des plugins IDE qui le rempliront pour vous, en utilisant ... euh, un plugin intelligent qui lit votre code.
Le côté Java des choses sera aussi performant que d'habitude. Ils n'utiliseront jamais cette laideur du code. Vous voudrez peut-être même le cacher à Javadoc.
Le côté FP du monde peut écrire le code "leet" qu'il veut, et il ne vous crie généralement pas que le code est lent.
En général, l'utilisation d'une carte (sac de propriété) à la place d'un objet est courante dans le développement de logiciels. Il n'est pas propre à la programmation fonctionnelle ou à tout type de langage particulier. Ce n'est peut-être pas une approche idiomatique pour une langue donnée, mais certaines situations l'exigent.
En particulier, la sérialisation / désérialisation nécessite souvent une technique similaire.
Juste quelques réflexions générales concernant la "carte comme objet".
la source
commonplace
me semble un peu fort. Je veux dire qu'il est utilisé comme vous le décrivez, mais c'est aussi une de ces choses notoirement non délicates / fragiles (comme des tableaux d'octets ou des pointeurs nus) que les bibliothèques essaient de cacher.C'est un excellent discours de quelqu'un qui sait vraiment de quoi il parle. Je recommande aux lecteurs de regarder le tout. Cela ne dure que 36 minutes.
Un de ses principaux points est que la simplicité ouvre plus tard des opportunités de changement. Le choix d'une classe pour représenter un
Person
offre l'avantage immédiat de créer une API statiquement vérifiable, comme vous l'avez souligné, mais cela s'accompagne du coût de la limitation des opportunités ou de l'augmentation des coûts de changement et de réutilisation ultérieurement.Son point de vue est que l'utilisation de la classe pourrait être un choix raisonnable, mais cela devrait être un choix conscient qui vient avec une pleine conscience de son coût, et les programmeurs font traditionnellement un très mauvais travail de remarquer ces coûts, sans parler de les prendre en considération. Ce choix doit être réévalué à mesure que vos besoins augmentent.
Voici quelques changements de code (dont un ou deux ont été mentionnés dans l'exposé) qui sont potentiellement plus simples à l'aide d'une liste de cartes par rapport à l'utilisation d'une liste d'
Person
objets:Map
des primitives dans un format transmissible est hautement réutilisable et peut même être fournie dans une bibliothèque. UnPerson
objet est susceptible d'avoir besoin de code personnalisé pour accomplir le même travail).Nous résolvons ces types de problèmes tout le temps, et avons des modèles et des outils pour eux, mais nous nous arrêtons rarement pour penser si le choix d'une représentation de données plus simple et plus flexible au début aurait facilité notre travail.
la source
Choosing a class to represent a Person provides the immediate benefit of creating a statically-verifiable API... but that comes with the cost of limiting opportunities or increasing costs for change and reuse later on.
Mauvais et incroyablement malhonnête. Cela améliore vos chances de changer plus tard, car lorsque vous effectuez un changement de rupture, le compilateur trouvera et vous indiquera automatiquement chaque endroit qui doit être mis à jour pour mettre à jour votre base de code entière. C'est en code dynamique, où vous ne pouvez pas faire ça, que vous vous associez vraiment aux choix précédents!Si les données ont peu ou pas de comportement, avec un contenu flexible susceptible de changer, utilisez une carte. L'OMI, un "javabean" ou "objet de données" typique qui se compose d'un modèle de domaine anémique avec N champs, N setters et N getters, est une perte de temps. N'essayez pas d'impressionner les autres avec votre structure glorifiée en l'enveloppant dans une classe de fantaisie fantaisie. Soyez honnête, expliquez clairement vos intentions et utilisez une carte. (Ou, si cela a un sens pour votre domaine, un objet JSON ou XML)
Si les données ont un comportement réel significatif, c'est-à-dire des méthodes ( Tell, Don't Ask ), utilisez une classe. Et tapotez-vous dans le dos pour utiliser une vraie programmation orientée objet :-).
Si les données ont un comportement de validation essentiel et des champs obligatoires, utilisez une classe.
Si les données ont un comportement de validation modéré, c'est limite.
Si les données déclenchent des événements de changement de propriété, c'est en fait plus facile et beaucoup moins fastidieux avec une carte. Écrivez simplement une petite sous-classe.
Un inconvénient principal de l'utilisation d'une carte est que l'utilisateur doit convertir les valeurs en chaînes, en entiers, en faux, etc. Si cela est très ennuyeux et sujet aux erreurs, envisagez une classe. Ou considérez une classe d'assistance qui enveloppe la carte avec les getters appropriés.
la source
L'API pour a
map
a deux niveaux.L'API peut être décrite dans la carte par convention. Par exemple, la paire
:api api-validate
peut être placée sur la carte ou:api-foo validate-foo
être la convention. La carte peut même stockerapi api-documentation-link
.L'utilisation de conventions permet au programmeur de créer un langage spécifique au domaine qui standardise l'accès à travers les "types" mis en œuvre sous forme de cartes. L'utilisation
(keys map)
permet de déterminer les propriétés lors de l'exécution.Il n'y a rien de magique dans les cartes et il n'y a rien de magique dans les objets. Tout est expédié.
la source