Fork me on GitHub

Hi, I'm a little confused about component. How do you actually write business logic with this? I mean functions that are not start or stop. I can see two ways, one is requiring the global system god map from every place that does business logic and then deconstructing the map so you can access the components. The other way to access a component is to put it into a protocol and implement that in the record. But is there no way to do it via a simple defn that you export from your file? Yet in the [documentation]( there is this (defn get-user [database username] ...) example, as if you just had access to database. What am I missing?


Component lives in the edges, it is basically a wrapper for your … well…. components


everything else should be normal clojure functions


so, your business logic, should not be in a component’s function


In that documentation example, database is an instance of a component.


Thanks @roberto and @sveri. I appreciate the examples especially, that is what I need to study.


Components are just there to help you set up and tear down stateful things. After that, you're just passing arguments to functions.


Typically there's an "entry point" somewhere — a main or a request handler — that kicks off your business logic with a function call, passing it a component that has dependencies on the things it needs.


@stuartsierra: I understand that database is a component, but after you put everything together in your system map, how do you get things out again? I mean the references to the various components are only accessible from the system map (where they were created), so if you want to call e.g. get-user, you have to do (get-user (:db my-system-map) username) and you have to pass the system-map around from your core file where you created it correct?


The 'component' library doesn't dictate how you store or access the system. This is a common point of confusion, I've found.


Typically, I have a main function that creates the system, starts it, then hands off control to one or more components, like a web server or an input loop.


For interactive development using the REPL, I store the system map in a Var in a dev namespace so I can examine it.


I never pass the entire system map as an argument to any function (except for debugging at the REPL).


Ok, thanks for all the suggestions, and it's good to know I'm not the only one, I'm starting to feel a little embarrassed. It's getting late here now, so that's probably not helping. I hope to get the hang of it tomorrow. Thanks again!


Don’t feel too bad. I personally had to carve out an afternoon to sit down and grasp it. I’m glad I took the time to do that.


I've seen a lot of people struggle with this. Is there something fundamental missing from the documentation?


Thanks @roberto! Umm... see you probably tomorrow. 😉


It is hard to articulate once I’ve grasped it. simple_smile


I think one of the issues I had was that I tried to learn it early on, while I was still learning clojure, and a bunch of libraries like ring


@stuartsierra: I really don't know, tomorrow once I understand it I think I should draw up a map of my (non-)understanding before and after.


I have to say, that just by looking at the vide from Clojure West 2014, and following the readme, I was able to understand it. (With a scrapbook at hand and a repl)


Something I’ve been thinking about that might help to onboard newcomers to a library is to do some node school type tutorials.


I’ve been thinking about doing something like this for keechma, but again, I’m that situation where I’m learning the framework and trying to write a tool for learning it …… at some point one of those takes a backseat


Most Ring tutorials make it very hard, by assuming that the main "handler" is statically defined.


yeah, I remember struggling with that