This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-08-19
Channels
- # aws (2)
- # babashka (4)
- # babashka-sci-dev (7)
- # beginners (92)
- # biff (7)
- # calva (64)
- # cider (2)
- # cljsrn (14)
- # clojure (8)
- # clojure-australia (5)
- # clojure-europe (14)
- # clojure-norway (8)
- # clojure-spec (36)
- # clojurescript (19)
- # component (15)
- # cursive (1)
- # data-science (6)
- # girouette (5)
- # hyperfiddle (3)
- # juxt (5)
- # leiningen (10)
- # lsp (7)
- # malli (12)
- # nbb (90)
- # polylith (1)
- # portal (11)
- # rdf (7)
- # reagent (6)
- # reitit (40)
- # remote-jobs (1)
- # shadow-cljs (21)
- # specter (5)
- # squint (83)
- # tools-deps (17)
- # vim (7)
Hi all, happy Friday!
Am I expected to implement Lifecycle
in all of my components, even ones for which I have no state nor anything to setup and teardown?
Was just about to say I've reread the readme and saw the following:
The default implementation of Lifecycle is a no-op. If you omit the Lifecycle protocol from a component, it can still participate in the dependency injection process.
Thanks for confirming. I do have a follow-up question though:The readme also mentions:
Components which do not need a lifecycle can be ordinary Clojure maps.
In my case, say I have a component SomeThirdPartyApi
,
I've made it a defrecord
which implements a custom protocol, for example:
(defprotocol SomeThirdPartyProtocol
(get-info-from-third-party [this email] "Get info for user with email"))
Is this 'overkill' at all? How do I reconcile what I'm trying to do with the message above about components with no need for a lifecycle potentially working as a map?but in order to depend on anything else in the system map, because of the way component injects dependencies, it has to be map like
Awesome, thanks for explaining that
I suppose a related question is that the docs mention:
Define the functions implementing the behavior of the component to take an instance of the component as an argument.
In my case I've opted to do that via a protocol definition that the defrecord implements. When would you opt for a good old function vs one defined in a protocol and implemented in a record?an extremely useful feature of clojure protocols when combined with component is the ability to make protocols extendable via metadata
protocol vs. just a function is going to depend on if I have more than one implementation (often the second implementation is a kind of mocked version of the component for tests)
Thank you so much for all of this. So it may make sense for me to default towards 'just a function' and only go down the protocol route either if I find myself needing to mock behaviour for tests, or make use of protocol extensions. Thank you also for the links on protocol extensions. I think I will need to do some reading and look at examples to wrap my head around when I might find that useful.
@UVD9WKYDQ https://github.com/seancorfield/next-jdbc/blob/develop/src/next/jdbc/connection.clj#L320-L328 -- uses an empty hash map with start
attached via metadata and it returns a function with stop
attached via metadata. Since there are no dependencies, any Clojure "object" can be used (as long as it can carry metadata).