4 ms·
Solid advice (I've been writing Clojure for the last 6 years or so and I agree with pretty much everything). I would like to add, however: * before you decide
by jwr 11y ago
Solid advice (I've been writing Clojure for the last 6 years or so and I agree with pretty much everything). I would like to add, however:
* before you decide to use Component, take a look at Mount and see which one suits you better (I settled on mount for both Clojure and ClojureScript and I'm happy so far),
* use Timbre: yes. Definitely. In fact, pretty much anything by Peter Taoussanis will be a good choice (for example, Sente is a wonderful tool for writing client+server apps). If you use Timbre in a mixed Clojure+ClojureScript application, consider sending logging from client-side to server side via Sente. I did and it's fantastic to be able to log something in ClojureScript code and have it appear in your server logs. Just don't overdo it, or you'll be flooded with logs.
* avoid lein plugins: yes, in general. But I still use one, lein-git-version, which names output artifacts using `git describe --tags` and places a version.txt file in resources/. This is difficult to do in any other way.
- sdegutis 11y agoWe don't use Component in production, because it's way too heavy for us. Our web store uses Datomic, PayPal and Stripe, and a few AWS services, and none of these need to be started or stopped. But we do take a tip or two from stuartsierra's "Reloadable" work flow (which he based Component on), specifically that there should be no global state, and all dependencies should be passed into functions that need them as a parameter. In our case, we call it `env` since it's the "environment" that a function runs in or can affect, and contains things like the database connection, email service, etc. Some of these are records which implement a protocol, so that you can have e.g. LiveEmailService in production and MemoryEmailService in development or while running tests. All in all, I like and have used some of Stuart's ideas, but not necessarily Component itself. There's strong mindshare for it in the Clojure community right now, and it's tempting to look at it as The Solution™ for almost everyone's use-cases because of that. And the ideas it has are good, but that doesn't always mean it's the best solution for each person.
- DigitalJack 11y agoIsn't your use of an env as a parameter just another form of global state? If not, can you elaborate?
- raould42 11y agoConsider unit testing. With global state, it gets harder to keep things clean; requires more "resetting" type code.
- VogonWorkEthic 11y agono, they're just data being passed in. at least thats what it sounds like to me. obviously this data has ways to manipulate the world, because an app that did nothing would be pointless. but it's no different than any other param. what would be bad, which is pretty much the opposite of this situation, is if you had global resources that werent passed in as params and caused side affects and you had to access a global variable to get to it (because it wasn't passed in).
- aosullivan 11y agoYou are right. Params can be references to state, either as an atom or ref, or to a function which accesses external state (e.g. a database). The idea that params somehow obviate the need for state overlooks that.
- emidln 11y agoDifficult? I have a few lines in a namespace that grabs `git describe --tags` and a few other things and places them in a json file. This is served up internally by all http-speaking applications as `GET /_internal/build-info`. https://gist.github.com/emidln/8f5993a37ff300e36897debe9c5bf558 https://gist.github.com/emidln/8f5993a37ff300e36897debe9c5bf...
- jwr 11y agoDo those lines also name your jars as "project-2.7.11-g03d04c5a.jar" or similar?
- emidln 11y agoNo, but only because load-file doesn't play well with all of my dependencies. However, that still doesn't seem like job for a plugin, given that this works out of the box with leniningen: :uberjar-name ~(str "foobar-%s-" (-> (clojure.java.shell/sh "git" "rev-parse" "--short" "HEAD") :out .trim) ".uber.jar")