The add method that you partially apply in new-scheduler should be private,
because a user can't supply the first argument it expects. You might do
something like this.

(defn- add* [queue item] (...))

(defn add [scheduler item]
  ((scheduler :add) item))

(defn new-scheduler []
  (let [queue (...)]
    {:add (partial add* queue)}))

But again, I am not recommending this. I just wanted to point out that a
closure gives you encapsulation w/o extra language features.
On May 10, 2013 6:56 AM, "Colin Yates" <colin.ya...@gmail.com> wrote:

> Thanks John.  To be explicit - the add method shouldn't be private - it is
> the only way users should add to the queue.  I think this is what you meant
> but you wrote "..and `add` and `clear` are your private fns..".
>
> Again, this paradigm shift of 'trust your users' is unfortunately alien to
> me based on my experience with most of the Java devs I have come across :).
>  I say that not be snarky, but to highlight how much it really does change
> things.  The open-closed principle now becomes much simpler to realise for
> example.
>
> Thanks again.
>
>
> On 10 May 2013 12:44, John D. Hume <duelin.mark...@gmail.com> wrote:
>
>> 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" <colin.ya...@gmail.com> 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 <ko...@sietsma.com> 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 <colin.ya...@gmail.com> 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 <ja...@booleanknot.com> wrote:
>>>>>
>>>>>> On 9 May 2013 17:07, Colin Yates <colin.ya...@gmail.com> 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 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 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
>>>>>> clojure+unsubscr...@googlegroups.com.
>>>>>>
>>>>>> 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 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/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 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 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
>>>> clojure+unsubscr...@googlegroups.com.
>>>> 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 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/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 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 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
>> clojure+unsubscr...@googlegroups.com.
>> 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 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/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 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/groups/opt_out.


Reply via email to