A few bits of feedback after seeing these examples.

Firstly, I'd like to see a more fleshed-out rationale. Currently it sounds
a bit like cargo-culting, e.g. "Spring is bad, Component reminds people of
Spring, therefore Component is bad". I'd challenge several parts of that
rationale, but the first is that "spring is bad". Why is that so? Is it the
XML configuration? Because Component doesn't have that. Is it the
mutability? Because Component doesn't have that either. Sadly I'm afraid
some people seem to see polymorphic functions (protocols) and think "AAAHHH
OOP! OOP IS BAD!!". When that's not really the case. The worst parts of OOP
are mutability and encapsulation of state inside opaque objects. Component
(and clojure for that matter) discourages both of these, so I'm not sure I
see the problem.

Secondly, I'm a bit leery of using anonymous functions instead of records.
I once worked on a system with a co-worker, and I asked him "why are you
using a record here...why not a closure?". He replied: "Because I can't see
what's inside a closure...it's opaque". That bit of advice has stuck with
me for some time. With something like component, if I have a function that
takes a component, I can look at that argument and see something like this:

=> #db.DBClient {:server "127.0.0.1" :port 4242 :schema "my-schema"}

With Closures I get something like this:

=> <fn foo.bar.baz >

That doesn't help much with debugging.

With Records I get immutability plus a type I can extend to any protocols.
Also, since my protocol is clearly defined, it's simple to extend. I don't
have to worry about hidden functions some inner function may call on my
client. Protocols provide abstraction.

So I guess that's my critique of Yo-Yo. I'd love to see a more in-depth
rationale, and I get nervous when people replace protocols with plain
functions, because normally I loose some expressiveness in the process.

Timothy

On Sun, Jun 28, 2015 at 8:03 AM, James Henderson <ja...@jarohen.me.uk>
wrote:

> As promised, have blogged: 'Yo-yo & Component - Side by Side
> <https://github.com/james-henderson/yoyo/blob/master/articles/side-by-side.org>
> '
>
> Contents:
>
>
>    - Making components
>    
> <https://github.com/james-henderson/yoyo/blob/master/articles/side-by-side.org#making-components>
>    - Using a component as a dependency
>    
> <https://github.com/james-henderson/yoyo/blob/master/articles/side-by-side.org#using-a-component-as-a-dependency>
>    - Serving a REST API
>    
> <https://github.com/james-henderson/yoyo/blob/master/articles/side-by-side.org#serving-a-rest-api>
>    - Wiring it all up
>    
> <https://github.com/james-henderson/yoyo/blob/master/articles/side-by-side.org#wiring-it-all-up>
>    - Yo-yo / Component Interoperability
>    
> <https://github.com/james-henderson/yoyo/blob/master/articles/side-by-side.org#yo-yocomponent-interoperability>
>    - Mockable Services
>    
> <https://github.com/james-henderson/yoyo/blob/master/articles/side-by-side.org#mockable-services>
>    - ‘Mocking out’ dependencies
>    
> <https://github.com/james-henderson/yoyo/blob/master/articles/mocking-out-dependencies>
>
> Let me know what you think!
>
> Cheers,
>
> James
>
> On Thursday, 25 June 2015 09:25:56 UTC+1, James Henderson wrote:
>>
>> Seems like the next step for this would be for me to put together a blog
>> with an example Component system, and its equivalent Yoyo system?! :)
>> Should have time for that over the weekend.
>>
>> James
>>
>> On Thursday, 25 June 2015 09:05:39 UTC+1, James Henderson wrote:
>>>
>>>
>>>
>>> On Wednesday, 24 June 2015 11:17:41 UTC+1, Atamert Ölçgen wrote:
>>>>
>>>>
>>>>
>>>> On Tue, Jun 23, 2015 at 11:47 PM, James Henderson <ja...@jarohen.me.uk>
>>>> wrote:
>>>>
>>>>> Hi Atamert - thanks :)
>>>>>
>>>>> I thought it might be preferable to keep the call to (latch)explicit
>>>>> - it means that ylet can be used in nested calls, too - for example,
>>>>> to set up and compose groups of components/sub-systems: (contrived 
>>>>> example,
>>>>> though!)
>>>>>
>>>>> ;; (docs for ylet at 
>>>>> https://github.com/james-henderson/yoyo#introducing-ylet )
>>>>>
>>>>> (require '[yoyo :refer [ylet]])
>>>>>
>>>>> (defn with-connections [config f]
>>>>>   (ylet [db-pool (with-db-pool (:db config))
>>>>>          es-conn (with-es-connection (:elasticsearch config))]
>>>>>
>>>>>     (f {:db-pool db-pool
>>>>>         :es-conn es-conn})))
>>>>>
>>>>> (defn make-system [latch]
>>>>>   (let [config ...]
>>>>>     (ylet [connections (with-connections system)
>>>>>            _ (with-webserver {:handler (make-handler (merge connections
>>>>>                                                             {:config 
>>>>> config}))
>>>>>                               :port 3000})]
>>>>>       (latch))))
>>>>>
>>>>>
>>>>> How would you see the with-* functions working, btw?
>>>>>
>>>>
>>>> I think the general idea should be to provide a clean API to the
>>>> consumer (of your lib). Perhaps something that accepts a start function, a
>>>> stop function and some sort of main loop (f in your example).
>>>>
>>>
>>> Not sure I understand what you mean here? Tbh, I was trying to get away
>>> from the idea of separate start & stop functions - it seems 'cleaner' to me
>>> without them! (although of course that's subjective).
>>>
>>> Also, the 'with-*' functions here are consumer code - the only Yo-yo
>>> functions/macros in this example are 'run-system!' and 'ylet'. Yo-yo itself
>>> is *tiny* (<100 LoC) - my aim was for a library that solely dealt with
>>> starting/stopping a provided system, and *no more* :)
>>>
>>> Maybe it'd be worth fleshing out an example of what you were looking for?
>>>
>>> Cheers,
>>>
>>> James
>>>
>>>
>>>>
>>>>>
>>>>> Cheers,
>>>>>
>>>>> James
>>>>>
>>>>> On Tuesday, 23 June 2015 09:57:16 UTC+1, Atamert Ölçgen wrote:
>>>>>>
>>>>>> Hi James,
>>>>>>
>>>>>> Interesting idea. Thanks for sharing.
>>>>>>
>>>>>> I think you can simplify this:
>>>>>>
>>>>>> (yoyo/run-system!
>>>>>>  (fn [latch]
>>>>>>    (ylet [db-pool (with-db-pool {...})
>>>>>>           :let [server-opts {:handler (make-handler {:db-pool
>>>>>> db-pool})
>>>>>>                              :port 3000}]
>>>>>>           web-server (with-web-server server-opts)]
>>>>>>      (do-this web-server)
>>>>>>      (do-that db-pool web-server)
>>>>>>      (latch))))
>>>>>>
>>>>>>
>>>>>> to:
>>>>>>
>>>>>> (yoyo/foo! [db-pool (with-db-pool {...})
>>>>>>             :let [server-opts {:handler (make-handler {:db-pool
>>>>>> db-pool})
>>>>>>                                :port 3000}]
>>>>>>             web-server (with-web-server server-opts)]
>>>>>>   (do-this web-server)
>>>>>>   (do-that db-pool web-server))
>>>>>>
>>>>>>
>>>>>> I believe with-* function can also be simplified further.
>>>>>>
>>>>>>
>>>>>> On Tue, Jun 23, 2015 at 1:18 AM, James Henderson <ja...@jarohen.me.uk
>>>>>> > wrote:
>>>>>>
>>>>>>> Hi all,
>>>>>>>
>>>>>>> I've just released an early version of 'Yo-yo', a protocol-less,
>>>>>>> function composition-based alternative to Component. It's still in its
>>>>>>> early stages, so feedback would be very much appreciated!
>>>>>>>
>>>>>>> https://github.com/james-henderson/yoyo
>>>>>>>
>>>>>>> Yo-yo was also an experiment to see what could be de-coupled from
>>>>>>> the concept of 'reloadable systems', so you won't find any 
>>>>>>> configuration,
>>>>>>> dependency injection, etc - just a way to write a system that can be 
>>>>>>> easily
>>>>>>> started, stopped, and reloaded.
>>>>>>>
>>>>>>> Fundamentally, we start by assuming there's a function available
>>>>>>> that only returns 'when the system stops' - a 'latch', say. If we had 
>>>>>>> such
>>>>>>> a function, we could start our system, call that function, then stop the
>>>>>>> system (closing any necessary resources). A database pool, for example,
>>>>>>> might look like this:
>>>>>>>
>>>>>>> (defn with-db-pool [db-config f]
>>>>>>>   (let [db-pool (start-pool! db-config)]
>>>>>>>     (try
>>>>>>>       (f db-pool)
>>>>>>>
>>>>>>>       (finally
>>>>>>>         (stop-pool! db-pool)))))
>>>>>>>
>>>>>>> Here, we're assuming that we'll be passed 'f', the 'latch'
>>>>>>> function. A web server would be similar, and, because they're both
>>>>>>> functions, they're very simple to compose:
>>>>>>>
>>>>>>> (with-db-pool {...}
>>>>>>>   (fn [db-pool]
>>>>>>>     (with-web-server {:handler (make-handler {:db-pool db-pool})
>>>>>>>                       :port ...}
>>>>>>>       (fn [web-server]
>>>>>>>         ;; TODO: Ah. We've run out of turtles. :(
>>>>>>>         ))))
>>>>>>>
>>>>>>> This is where Yo-yo comes in - there’s a function called run-system!,
>>>>>>> which takes a function that accepts a latch:
>>>>>>>
>>>>>>> (:require [yoyo])
>>>>>>>
>>>>>>> (yoyo/run-system!
>>>>>>>   (fn [latch]
>>>>>>>     (with-db-pool {...}
>>>>>>>       (fn [db-pool]
>>>>>>>         (with-web-server {:handler (make-handler {:db-pool db-pool}) ; 
>>>>>>> n.b. we have access to the db-pool here - no need for global state!
>>>>>>>                           :port ...}
>>>>>>>           (fn [web-server]
>>>>>>>             (latch))))))) ; Aha!
>>>>>>>
>>>>>>> run-system! then returns a promise - deliver any value to it, and
>>>>>>> it'll stop the system.
>>>>>>>
>>>>>>> And that's pretty much it! There are a few more functions - mostly
>>>>>>> to do with easily starting/stopping/reloading a system through the REPL,
>>>>>>> and a macro to simplify the 'function staircase' - these are covered in
>>>>>>> more detail in the README. There are some also common components - a
>>>>>>> database pool, a web server, and a simple integration for existing
>>>>>>> Component systems.
>>>>>>>
>>>>>>> It'd be great to hear your thoughts/ideas, whatever they may be -
>>>>>>> either through here, e-mail, Github, or Twitter - thanks!
>>>>>>>
>>>>>>> James
>>>>>>>
>>>>>>>  --
>>>>>>> You received this message because you are subscribed to the Google
>>>>>>> Groups "Clojure" group.
>>>>>>> To post to this group, send email to clo...@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+u...@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+u...@googlegroups.com.
>>>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> Kind Regards,
>>>>>> Atamert Ölçgen
>>>>>>
>>>>>> ◻◼◻
>>>>>> ◻◻◼
>>>>>> ◼◼◼
>>>>>>
>>>>>> www.muhuk.com
>>>>>>
>>>>>  --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "Clojure" group.
>>>>> To post to this group, send email to clo...@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+u...@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+u...@googlegroups.com.
>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> Kind Regards,
>>>> Atamert Ölçgen
>>>>
>>>> ◻◼◻
>>>> ◻◻◼
>>>> ◼◼◼
>>>>
>>>> www.muhuk.com
>>>>
>>>  --
> 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.
>



-- 
“One of the main causes of the fall of the Roman Empire was that–lacking
zero–they had no way to indicate successful termination of their C
programs.”
(Robert Firth)

-- 
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