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.

Reply via email to