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.