The example in the article is probably the smallest example I can come up 
with.

http://z.caudate.me/the-abstract-container-pattern

The code for the concrete implementations speaks for itself I think, it is 
about 10 lines to hook in jetty and http-kit to the framework.

if we think about how much code an interface/abstract/concrete design 
pattern can potentially reduce over a strict interface/concrete design 
pattern in the java, then it's exactly the same with clojure.

One particular benefit of this particular pattern that I am exploiting is 
the fact that you can then specify exactly what you want in the config. I'm 
a big fan of making everything explicitly clear within the config itself so 
if we have a system with some a component-style dependency injection model 
(see http://docs.caudate.me/hara/hara-component.html), you can easily do 
something like this to get a jetty server up:

{:server {:type :jetty
               :port 8080}

and if you want a :http-kit server, you just change the config as such:

{:server {:type :http-kit
               :port 8080}

I've done this quite a bit with mocking... for example, here - 
https://github.com/MyPost/cassius/blob/master/src/cassius/component.clj

changing

{:db {:type :database}}

to

{:db {:type :mock}}

will work exactly the same way, irrespective of dependency injection 
framework - in this case, I'm using the stuartsierra/component framework.
....




On Tuesday, July 28, 2015 at 9:34:46 PM UTC+5:30, James Reeves wrote:
>
> What are the benefits of designing an "abstract class" in this way, 
> compared to, say, using a protocol and normal functions? Could you provide 
> a small example?
>
> - James
>
> On 28 July 2015 at 10:09, zcaudate <z...@caudate.me <javascript:>> wrote:
>
>> Hey guys,
>>
>> Thanks for the feedback and your very insightful comments.
>>
>> Yep... this is OO alright =)
>>
>> I realised only after I wrote the article that I was implementing a 
>> Lifecycle clone with IRunnable example. However, the concept I am 
>> mentioning is much more general than components in terms of its scope:
>>
>> A similar `abstract class` for a reflective functional dispatch mechanism 
>> is defined here:
>> https://github.com/zcaudate/iroh/blob/master/src/iroh/types/element.clj
>>
>> and extended by the `concrete classes' here:
>> https://github.com/zcaudate/iroh/tree/master/src/iroh/element
>>
>> In the case of iroh... if I had used strictly multimethods, I would have 
>> been very confused. If I had used strictly protocols... well I couldn't for 
>> a number of reasons.. but if I did, I would have been even more confused 
>> because of the number of subconditions that I had to implement. iroh was 
>> the first library that I had built that used this pattern and it was so 
>> successful that I've been repeating the process over and over again since.
>>
>> What I wanted to achieve was to have the equivalent of an `abstract 
>> class` - the concept of code with abstract functionality that provides a 
>> framework for the heavy lifting to be done. `Concrete classes` can just 
>> extend aforementioned `abstract class` with minimal code and get all of the 
>> benefits. 
>>
>> I've used this pattern with great success in many, many times and it 
>> provides a counter balance to the functional paradigm in terms of packaging 
>> up functionality. Clojure doesn't force us into one paradigm or the other 
>> and sometimes it is just more stylish to use the OO paradigm. The whole 
>> point of OO, multimethods and protocols is to do polymorphic dispatch, 
>> which is just a way to break a large cond statement into pieces that can 
>> then also be further extended. 
>>
>> Please also note that not all OO frameworks are equal. Java uses a class 
>> inheritence approach whereas javascript uses a prototype model. The 
>> `abstract container` pattern that I was describing is probably closer to 
>> the JS model but to be honest, I don't really know what it is. Ultimately, 
>> it adds a middle tier of functionality in systems that have a plugin type 
>> mechanism. I'm sure there are equivalent functional contructs... but that 
>> was not the point of the pattern. This pattern has been very useful for me; 
>> clojure's protocols and multimethods were not enough to do what I needed to 
>> do - but combination of the two works wonders =)
>>
>> Since the article, the pattern has been codified here:
>>
>> https://github.com/zcaudate/hara/blob/master/src/hara/extend/abstract.clj#L196
>>
>> Hope that helps in clarifying the motivation behind the article and the 
>> pattern
>>
>>
>> Chris
>>
>>
>>
>>
>>
>>
>>
>> On Monday, July 27, 2015 at 11:42:21 PM UTC+5:30, Colin Yates wrote:
>>>
>>> I think his last sentence gives you the answer:
>>>
>>> "A warm shoutout to Tushar, Lyndon, Dean, Alan, Hank, Derek, and all 
>>> the guys at clj-melb that gave feedback and helped flesh out this rehash of 
>>> *OO 
>>> design*.” (my emphasis)
>>>
>>> He wanted an OO approach and has implemented one; specifically behaviour 
>>> and state coupled together. I think neither Typed Clojure nor Contracts 
>>> would have achieved this guy’s goal as they are about enforcing a contract 
>>> (either the shape of data or effects of a fn) in the ‘functional’ paradigm; 
>>> this guy clearly wanted something in the OO paradigm. 
>>>
>>> Is there a ‘functional’ implementation which gives the same benefits; 
>>> sure, but that isn’t what he wanted. Are there a bunch of ‘upgrades’ that I 
>>> am sure we could all apply; sure, but again it seems like he was setting 
>>> out with a very specific goal in mind and has achieved that. 
>>>
>>> On 27 Jul 2015, at 18:37, Lawrence Krubner <lawr...@rollioforce.com> 
>>> wrote:
>>>
>>> I have a question about this: 
>>>
>>> "Servers that are running on a particular port can be tracked and 
>>> stopped. I have to say, this was the feature that I wanted the most, which 
>>> motivated the framework's design. The annoying thing about development in 
>>> emacs is that I have to be careful of not losing the reference to the 
>>> server. Since there was no way of stopping it unless the repl is restarted. 
>>> I wanted to implement a registery for references to running servers to be 
>>> saved."
>>>
>>> http://z.caudate.me/the-abstract-container-pattern/
>>>
>>> I have the impression that he's going over the same territory as that 
>>> covered by Stuart Sierra, though Zheng doesn't mention "Component" nor 
>>> "Sierra". But he offers this as an example of what he's after: 
>>>
>>> (defprotocol IRunnable (start! [system]) (stop! [system]) (restart! 
>>> [system]) (started? [system]) (stopped? [system]))
>>>
>>> That much seems similar to Sierra's system. Zheng seems to add an 
>>> additional layer by simulating an abstract class above his protocols. As he 
>>> says: 
>>>
>>>
>>>    - A single deftype acts as the *abstract container*, extending one 
>>>    or more protocols
>>>    - A set of methods defined through defmulti that is used within the 
>>>    deftype form act as *abstract methods*
>>>    - The *abstract methods* all dispatch on map keys (usually :type).
>>>
>>>
>>> I am curious if others have found this useful? 
>>>
>>> Most of the people who work with Clojure have backgrounds with Object 
>>> Oriented Programming, so that paradigm sometimes seems natural, or at least 
>>> familiar. I often think these designs are more verbose than they need to 
>>> be, but I am curious how others feel. 
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>> -- 
>>> 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.
>>>
>>>
>>>  -- 
>> 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.
>>
>
>

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