Fork me on GitHub

Hi everyone, I wanted to find out what's the most idiomatic way to use component library. I have defined one component in a namespace

(defrecord IM-Proto-0
    [status config state-component]


  (start [component]
    (-> component
        (assoc :status :active)))
  (stop  [component]
    (-> component
        (assoc :status :deactive))))

(defmethod im.access/create
  (-> {:config config}
And then in another where I am constructing the system I use the component this way - the im.access for example is the namespace of the component record :
(defn create-system'
  [{:keys [im-config
    :as   master-config}]
    :im    (-> (im.access/create im-config)
               (component/using  {:state-component :state}))
    :om    (-> (om.access/create om-config)
               (component/using  {:state-component :state}))
    :state (-> (state.access/create state-config))))
I don't know if I am being too picky about this but the problem is this way it is not clear form where I want to construct the system that which components use which dependencies - let alone the fact that we actually might import this whole artifact somewhere else and allow for systems to be composed this way. Is there a more idiomatic way to write components ? or am I being too picky about this ? Thanks in advance


@ho0man I'm not really sure what you're asking here...?


The thing is that the dependency on state-component is specified in the defrecord for IM-Proto-0 and then everywhere else - specially where this code is included as a library- I’m creating a system that has a IM-Proto-0 component I should supply the dependency using component/using .


How could I make it easier for clients of this library to use and maintain their code using my components?


But every use could be injecting a different thing for the state-component


Yeah you’re right but the thing is how should they know that there is a state-component dependency at all? I think I didn’t explain the problem well. We wanted the im.access/create multimethod to hide implementation details of a component whose different versions may have different component dependencies. For instance one implementation uses only a Hazelcast client component and another uses Redis in conjuction with a Postgres. Which is determined dynamically by their configurations.


The dependencies have to be computed before you start the overall system.


In some of our projects we used to construct a system map at each component level and put the component/using there and merge these subsystem at top level (we followed an article on best practices of using component library) but that also made the code not exportable as a library since we were limiting the users of the components in their injection (they had to name the dependency exactly what we had set for the component)


If the dependencies are derived from the configuration, then you need to load the configuration first, then use it to build the using dependency map.


Or you need to abstract over the things that can vary.

👍 4

Do you have the exact same API over Hazelcast that you have over the Redis/PostgreSQL combo?


Hmm no they’re different There are two separate very different implementations for those


Either way, you're going to need to process the configuration first, use that to drive the construction of the components and/or the using dependency map, and then start it.


So it might be that you need a component, based on configuration, that when it start's up produces your actual system component with all its dependencies, and then you start that?

👏 4

Yeah you’re totally right That seems a lot better Thanks a lot @U04V70XH6


I'm also a bit confused about your IM-Proto-0 component since it has status and state-component fields but in your create "constructor" function, you're passing in config which isn't mentioned in IM-Proto-0...


Yeah you’re right sorry It git removed when I was trying to remove unnecessary code