component icon indicating copy to clipboard operation
component copied to clipboard

Provide an example explaining the ?essence? of the components idea

Open fhalde opened this issue 3 years ago • 0 comments

Almost every usage of component in projects I've inherited got one important detail wrong about its usage

e.g.

Here's a trivial database component that usually gets created

(defrecord Database [host port connection]
  component/Lifecycle

  (start [component]
    (println ";; Starting database")
    (let [conn (connect-to-database host port)]
      (assoc component :connection conn)))

  (stop [component]
    (println ";; Stopping database")
    (.close connection)
    (assoc component :connection nil)))

And then, the entire codebase is littered with getting the :connection key out of the Database component

e.g.

(some-database-library/query (:connection db-comp) query)

This feels wrong. You can never mock components this way

IMO the intention of the component library was to do the following

(defrecord Database [host port connection]
  component/Lifecycle

  (start [component]
    (println ";; Starting database")
    (let [conn (connect-to-database host port)]
      (assoc component :connection conn)))

  (stop [component]
    (println ";; Stopping database")
    (.close connection)
    (assoc component :connection nil))

  proto/IDatabase

  (query [this] ...))

Now the rest of the code does the following

(db/query db-comp)

The approach I mentioned can be an extreme one too i.e. now, I have to provide the same interface/api in proto/IDatabase as the library/database that I'm building a component for

fhalde avatar Dec 30 '21 11:12 fhalde