Hi Timothy - firstly, thank you for taking the time to read through and 
reply. I understand it would have been very easy to read them and move on 
thinking 'just a nutter on the mailing list who doesn't really understand 
what he's talking about', but I do really appreciate your feedback - thanks 
:)

You're right - openly, I think it took not only hammocking about Yo-yo, but 
also sitting down over the weekend writing up the side-by-side to really 
realise what Component and Yo-yo both provide. (I don't regret doing 
either, of course - without doing so I wouldn't have got close to thinking 
about it in this way!) I do agree that not everything about Spring/OOP is 
bad, and certainly that Clojure/Component has taken the good parts. What 
I've seen so far, though, is some people (me included, probably) seeing 
Component, thinking 'that's nice, a pattern I'm familiar with', and 
reverting to writing Clojure apps like they used to write Spring apps - 
with components for *everything*, components for wiring up other 
components, etc, giving them all sorts of names (a la 'the Kingdom of 
Nouns'). It's also Phoenix, in particular, that reminded people of Spring - 
I've tried to ensure I always make that distinction, apologies if that 
didn't come across.

Incidentally, I wrote a first iteration of the side-by-side blog with the 
Component side written in this style, and then realised there was nothing 
in Component that mandated writing in that way; just that I and others had 
interpreted it that way - it was quite an 'aha' moment! I'd also not heard 
that advice about anonymous functions either - thanks! Thinking about it, 
I've come up with all sorts of workarounds to get closed-over variables out 
of closures.

Having said that, I think there's still some legs in Yo-yo - given that it 
doesn't mandate writing apps in any style (only that the one top level 
function accepts a system latch) it's possible to write Yo-yo apps as you 
would a Component system, or using functional composition, or anywhere in 
between. At the very least, Yo-yo would help with managing Component's 
system at the REPL - the top-level function becomes:

(defn make-system [f]
  (let [started-system (-> (c/system-map ...)
                           c/start-system)]
    (try
      (f started-system)
      
      (finally
        (c/stop-system started-system)))))

(defn -main [& args]
  (yoyo/set-system-fn! 'myapp.main/make-system)
  (yoyo/start!))

with the ability to then run (yoyo/reload!) etc from the REPL (without 
everyone having to write their own user namespace start/stop functions)

I do also like the way that there aren't separate start/stop functions - 
maybe there's scope for a Lifecycle protocol that only involves one 
function instead? Maybe that's not even a good idea either, I don't know. 
I'll keep on experimenting, that's for sure :)

Thanks again,

James

On Monday, 29 June 2015 02:49:43 UTC+1, tbc++ wrote:
>
> 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 
> <javascript:>> 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 clo...@googlegroups.com 
>> <javascript:>
>> 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 <javascript:>
>> 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 <javascript:>.
>> 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