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.

Reply via email to