Fork me on GitHub
#component
<
2020-06-09
>
ho0man15:06:00

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]

  im.access/Access

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

(defmethod im.access/create
  Type-ID
  [config]
  (-> {:config config}
      (map->IM-Proto-0)))
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
           om-config
           state-config]
    :as   master-config}]
  (component/system-map
    :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

seancorfield17:06:35

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

ho0man03:06:59

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 .

ho0man03:06:52

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

seancorfield03:06:53

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

ho0man04:06:31

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.

seancorfield04:06:04

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

ho0man04:06:28

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)

seancorfield04:06:57

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.

seancorfield04:06:01

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

👍 4
seancorfield04:06:50

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

ho0man04:06:32

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

seancorfield04:06:48

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.

seancorfield04:06:03

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
ho0man04:06:27

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

seancorfield17:06:57

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...

ho0man03:06:40

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