In OO we tend to solve the 'copy and paste' problem with abstract classes. In Clojure we also have macros, easily overused, sure, but worth knowing about. They turn the problem on its head and allow truly composable functionality. I am not stating they _are_ appropriate here, only that you might want to think about them; whenever I have a 'I want this pattern enforced, but it is really just an implementation detail', a macro is sometimes the answer.
On 15 March 2015 at 15:58, Andrew Oberstar <ajobers...@gmail.com> wrote: > I'm fairly new to Clojure, so I'm still struggling to unlearn the habits of > OO-programming. While using Stuart Sierra's component library, I've found > the recommendation in the docs of using idempotent lifecycles very helpful. > The unfortunate result is that every component then has the same pattern in > its start and stop methods: > > (defrecord SillyExample [...] > component/Lifecycle > (start [this] > (if (custom-started-check? this) > this > (custom-start-logic this))) > (stop [this] > (if (custom-started-check? this) > (custom-stop-logic this) > this))) > > It adds some extra nesting and, potentially, duplication of the started > check's logic. In hopes of making idempotent lifecycles easier to implement, > I made the following protocol, which seems to violate the implementation > inheritance philosophy of Clojure. > > (defprotocol IdempotentLifecycle > (started? [this]) > (safe-start [this]) > (safe-stop [this])) > > (extend-protocol component/Lifecycle > my.ns.IdempotentLifecycle > (start [this] > (if (started? this) > this > (safe-start this))) > (stop [this] > (if (started? this) > (safe-stop this) > this))) > > So then a use case would like more like: > > (defrecord SillyExample [...] > IdempotentLifecycle > (started? [this] > (custom-started-check this)) > (safe-start [this] > (custom-start-logic this)) > (safe-stop [this] > (custom-stop-logic this))) > > This seems like an easier end-user experience, but it feels wrong to > implement a protocol with another protocol. A more "Clojurey" feeling option > would require changes to the component library itself: > > (defprotocol LifecycleStatus > (started? [this])) > > (extend-protocol LifecycleStatus > java.lang.Object > (started? [_] false)) > > ;; Lifecycle protocol stays as-is > > (defn safe-start [component] > (if (started? component) > this > (start component))) > > (defn safe-stop [component] > (if (started? component) > (stop component) > this)) > > Then component would need to use safe-start/safe-stop in place of regular > start/stop in the start-system/stop-system functions. > > Maybe this is better suited to an issue/pr on his repository, but I wanted > to see if there were any comments from the community. Is there a better way > to do this? > > Andrew Oberstar > > -- > 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. -- 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.