I agree with the advice you've gotten, but since no one has mentioned it, I
wanted to point out that you can have encapsulation w/o protocols with
something like this.
Assume a queue is your only state and `add` and `clear` are your private
fns that take a queue as first argument.
(defn new-scheduler []
(let [queue (...)]
{:add (partial add queue)
:clear (partial clear queue)}))
There are several disadvantages to this, however. The biggest in my book is
that it achieves your goal, and you're limited in the same way your users
are. You can't add behavior to an already created scheduler (unless it's
built on adding and clearing). Furthermore, if you dynamically recompile
`add` or `clear`, it won't change the behavior of an already created
scheduler, since partial has the fns, not the symbols or vars that point at
them. (These same disadvantages apply to a reified protocol.)
As others have recommended, just return a map. Keep in mind that the
documentation is just a `(doc new-scheduler)` away and that auto-completion
will tend to send people back into your ns's fns rather than into the
internals of a data structure.
On May 10, 2013 5:51 AM, "Colin Yates" <[email protected]> wrote:
> Thanks Korny.
>
> Ok, the over-ridding theme seems to be: expose state, even if it is
> dangerous, but expect consumers to 'do the right thing' and read the
> documentation.
>
> I can see that. I guess I have worked (and to be honest, been guilty
> myself) with too many people who don't read the documentation, use
> auto-complete to find something that looks like it might work and then move
> on to the next chunk of wiring things up in XML :).
>
> I think I also got hung up on the 'data as a contract'. The point here is
> that I am not returning data, rather I am defining a service. A subtle
> difference but an important one I think.
>
> Keep the comments coming!
>
>
> On 10 May 2013 11:37, Korny Sietsma <[email protected]> wrote:
>
>> I would generally handle this sort of encapsulation at the namespace
>> level.
>>
>> Put (create-woobly) and (add-job) and all the other woobly-related
>> functions into a woobly namespace. Also add any functions that access info
>> from a woobly bag-o-state, or mutate a woobly to make a woobly-with-extras.
>>
>> Functions that might dangerously expose internals of a woobly can be made
>> private, or possibly you can just document them in a way to warn folks away
>> from "bad" behaviour.
>>
>> While external users of (woobly/create-woobly) can in theory dig into the
>> internals of the woobly "object", but it should be relatively obvious that
>> this isn't a good idea.
>>
>> I'd defer making protocols until you actually need polymorphism.
>>
>> - Korny
>>
>>
>>
>> On 10 May 2013 03:03, Colin Yates <[email protected]> wrote:
>>
>>> Thanks for all the helpful responses.
>>>
>>> One reason I want to hide the internals is that I don't want people to
>>> add jobs directly to the queue. (add-job) will put a map containing the
>>> provided function onto the queue. Not really relevant, but this is so that
>>> I can track queue timings that I can later on use to determine how much
>>> capacity the system can handle.
>>>
>>> I am nervous as well about "expose internals but trust people to do the
>>> right thing" because in this case, if I was a consumer and saw that queue,
>>> particularly given the emphasis about data being the contract etc. then why
>>> would I think *not* to use it.
>>>
>>> I do appreciate the point about not needlessly obfuscating information -
>>> this is a slightly different case.
>>>
>>> Sounds like in this case, either reify is the way to go or maybe return
>>> a bad of data but have this stuff in an 'internal' map (i.e. {:internal
>>> {:queue...}})
>>>
>>> Thanks a bunch - really helpful.
>>>
>>>
>>> On 9 May 2013 17:30, James Reeves <[email protected]> wrote:
>>>
>>>> On 9 May 2013 17:07, Colin Yates <[email protected]> wrote:
>>>>
>>>>> The part I am struggling with is how to create a Woobly without
>>>>> exposing its internals.
>>>>>
>>>>
>>>> To what end? What's the benefit?
>>>>
>>>> If you take a look at some internal data structures Clojure uses, like
>>>> zippers or protocols, you'll notice that they're just maps. In general
>>>> there's no need to try and obfuscate data to stop people from diving into
>>>> the internals; just don't provide a public API for the internal parts and
>>>> people will get the hint.
>>>>
>>>> - James
>>>>
>>>> --
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "Clojure" group.
>>>> To post to this group, send email to [email protected]
>>>> Note that posts from new members are moderated - please be patient with
>>>> your first post.
>>>> To unsubscribe from this group, send email to
>>>> [email protected]
>>>> For more options, visit this group at
>>>> http://groups.google.com/group/clojure?hl=en
>>>> ---
>>>> You received this message because you are subscribed to a topic in the
>>>> Google Groups "Clojure" group.
>>>> To unsubscribe from this topic, visit
>>>> https://groups.google.com/d/topic/clojure/D2OBBPTxGfY/unsubscribe?hl=en
>>>> .
>>>> To unsubscribe from this group and all its topics, send an email to
>>>> [email protected].
>>>>
>>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>>
>>>>
>>>>
>>>
>>> --
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To post to this group, send email to [email protected]
>>> Note that posts from new members are moderated - please be patient with
>>> your first post.
>>> To unsubscribe from this group, send email to
>>> [email protected]
>>> 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 [email protected].
>>>
>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>
>>>
>>>
>>
>>
>>
>> --
>> Kornelis Sietsma korny at my surname dot com http://korny.info
>> .fnord { display: none !important; }
>>
>> --
>> --
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to [email protected]
>> Note that posts from new members are moderated - please be patient with
>> your first post.
>> To unsubscribe from this group, send email to
>> [email protected]
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> ---
>> You received this message because you are subscribed to a topic in the
>> Google Groups "Clojure" group.
>> To unsubscribe from this topic, visit
>> https://groups.google.com/d/topic/clojure/D2OBBPTxGfY/unsubscribe?hl=en.
>> To unsubscribe from this group and all its topics, send an email to
>> [email protected].
>> For more options, visit https://groups.google.com/groups/opt_out.
>>
>>
>>
>
> --
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to [email protected]
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> [email protected]
> 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 [email protected].
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
>
--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/groups/opt_out.