In object-oriented programming, encapsulation is always and everywhere regarded as a highly significant design virtue, but the Clojure people have a bit of a different assessment, particularly when it comes to information. In one talk, Rich Hickey pointed out that encapsulation is for hiding implementation details, but information doesn't *have* an implementation; there are no innards to encapsulate *unless you add them*. Stuart Halloway gave one talk where he made a brilliant point about how abstraction is valuable for *commands*, because then it limits what you have to know, but it's not valuable for *queries*, because then the abstraction (i.e. the custom accessors that "encapsulate" your data) only limits what you can perceive.
And of course, there's Alan Perlis's old saw that "it is better to have a hundred functions operate on one data structure than to have ten functions operate on ten data structures"--that is to say, by using generic data structures (e.g. maps) to directly represent information in your domain, you can reuse all of the generic functions that operate on those data structures, whereas encapsulated data screws your clients because it renders all of their generic collections libraries useless. (This is one of the ways in which OOP has failed to deliver on its promise of pervasive code reuse.) Some of Rich Hickey's talks that touch on the subject: http://www.infoq.com/presentations/Value-Values http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey As for your particular example, I recommend looking at defrecord, which generates a data structure that behaves like a map (it can be perceived and manipulated generically), as well as various constructors and readers and so forth for that type. defrecord also lets you specify protocols for your data type. See: http://clojure.org/datatypes Also be sure to check out Prismatic's survey of Clojure's choices for doing "object"-like things: https://github.com/Prismatic/eng-practices/blob/master/clojure/20130926-data-representation.md#data-types On Wednesday, June 25, 2014 6:34:50 PM UTC-7, Mark P wrote: > > I've only recently started real clojure development, so very much still > learning what styles work and what don't. I have a question about naming > attribute getters... > > Suppose I want to model "fruit" entities. I will use a hash-map to > represent the data for each such entity, and will defn a "make" function to > construct fruit instances. I will put "make" and any other fruit-related > functions within a new namespace "myprog.fruit". > > Because my data representation is a map, strictly speaking I don't need > any attribute getter functions. Because I could simply use the attribute > keywords in the map as my getter functions, eg (:color fru). But I will > create actual getter functions within my namespace anyway, for a few > reasons. > > 1. It will signal to any users of my fruit library, which attributes > are "official" and are expected to be used / supported, versus attributes > which are more of an implementation detail. > 2. Some attributes will simply be (defn color [fru] (:color fru)), > whereas others are less direct, eg (defn red? [fru] (= :red fru)) or > another eg (defn packingvol [{:keys [size]}] (* size size size)). > 3. Down the track I can change my data representation, and just > reimplement the getter functions. Users of my fruit library who have > stuck > to my getter functions interface will not need to change a thing. > > This approach seems okay to me so far, though I am open to critiques and > alternative suggestions. But one issue has come to mind... leading to the > question of this post... > > At the end of 2. above, I have defined a local let symbol "size" as part > of the map destructuring. But it so happens I have already defined a size > getter, namely (defn size [fru] (:size fru)). So within the definition of > packingvol my size getter is masked by the local symbol "size". Now I'm > not sure this masking causes much harm... I don't actually need to use the > size getter here, and if I really needed it I could always use > "myprog.fruit/size"... But something still makes me feel uncomfortable > about it, maybe because this masking could end up happening a lot within my > fruit.clj source code file. > > Now I could just switch to a new naming convention for my getters, ie > "color-get", "red?-get", "size-get", "packingvol-get" etc. But I'm not > sure I like the extra verbosity. And for users of my fruit library - who > will be working in a different namespace - this problem mostly goes away as > they will probably be namespace-qualifying access to my getters. > > Is using self-named attribute getters a good idea? > > Thanks, > > Mark. > > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.