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?
no, Lifecycle has a no-op extension to Object
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?there are several different constraints depending on what you are doing
you can put anything at all in the system 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
(a defrecord is 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
https://clojure.org/reference/protocols#_extend_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.
@ziad_salah 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).