The question of how to specify the "shape" of your data is an important 
one, and I think one of the contributions of Clojure is the way it isolates 
that problem, instead of complecting it with object-oriented design or 
static type checking. You might look at Prismatic Schema, a library that 
offers declarative data description and validation without the baggage of 
OOP or the complexity of static typing:

https://www.youtube.com/watch?v=o_jtwIs2Ot8
https://github.com/Prismatic/schema

There's also core.typed, an optional static type system for Clojure that 
allows you to specify your data's shape as a type of map, called a 
heterogeneous map:

https://github.com/clojure/core.typed/wiki/Types#heterogeneous-maps

There's also my own dynamic-object, which is an attempt to bring these 
ideas to Java development without ruining them:

https://github.com/rschmitt/dynamic-object (see in particular 
https://github.com/rschmitt/dynamic-object#schema-validation)

You can implement all the convenience functions you want; as long as you're 
not using them to encapsulate or abstract away your data, they're probably 
harmless. A function like 'red?' doesn't seem like it's adding too much 
value, but a less trivial function could easily be worth providing as part 
of your API. Just because your clients *can* use generic collections 
operations doesn't necessarily mean that they should *have to*.

I'm not sure I understand your question about namespacing. Creating a 
namespace for your code is basically mandatory--are you asking about the 
ideal granularity of namespaces? Prismatic has another eng-practices 
document dealing with namespace organization:

https://github.com/Prismatic/eng-practices/blob/master/clojure/20130927-ns-organization.md

On Wednesday, June 25, 2014 8:37:26 PM UTC-7, Mark P wrote:
>
> Thanks Ryan, Mike and James for your comments and info.  Ryan I will 
> follow up the links you posted.
>
> In the meantime, a request for some clarification...
>
> I have read / watched clojure stuff along these lines... ie that data 
> hiding (in an immutable data context) is bad.  I thought my approach was 
> taking this into account.  Ie, I am actually using a hash-map for my fruit 
> instance data (rather than say closures for true data hiding) and this is 
> not hidden - it is freely accessible to users of my fruit library.  Users 
> can choose to use getter functions or use more direct map access 
> techniques.  The getter functions sort of provide self documentation about 
> interface intent, without restricting/forcing users to be limited to this 
> if the interface has weaknesses.  I guess I was trying to "take the best 
> from both approaches".  But maybe you are telling me that even this 
> watered-down-encapsulation is not good?
>
> Ryan you are suggesting that maybe defrecord is the way to go.  I haven't 
> read about that yet, so I will look into that.
>
> But just suppose I wanted to stick with using raw hash-maps for my data. 
>  Would you suggest that instead of my current approach, I should...
>
>    - Not implement any getter function when a keyword accessor will do. 
>     Eg don't implement (defn color [fru] (:color fru)), just let library 
> users 
>    do (:color fru) themselves.
>    - Do still implement other getters, eg (defn red? [fru] (= :red fru)) 
>    and eg (defn packingvol [{:keys [size]}] (* size size size)).
>    - What about "make"?  Do I still implement a fruit constructor 
>    function, or do I leave it to users to use usual hash-map constructors? 
>     (And if I should not implement a fruit constructor, how do I indicate to 
>    users the shape that a fruit hash-map should take?  Do I just document 
> this 
>    in comments?)
>    - Was I right to construct a new namespace for my fruit-related data 
>    and functions?
>
> Thanks,
>
> Mark.
>
> On Thursday, 26 June 2014 11:42:01 UTC+9:30, Ryan Schmitt wrote:
>>
>> 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