Thanks Tim for reading down till the last line!
> On 5 Apr 2016, at 19:09, Timothy Baldridge <
tbald...@gmail.com> wrote:
>
> The thing that this doc also advocates (and I am against) is manual dependency management, your app start function must call start on its dependencies. This not only hardcodes the dependency, but also requires the user to think about the startup order of components on every usage.
This “every usage” is roughly every time a new component is added (in my experience). Of the total number of components, around 80% is added at the very beginning and a few more during the lifetime of the app. Last time I had the ordering problem with one component I fixed it in the app start function and never touched it again. So I’m not sure if the user is required any special effort after the very first setup.
> In addition this approach doesn't support substituting alternate implementations. During testing I often want to use a in-memory queue vs RabbitMQ. Or perhaps I want to wire an entire system up with in-memory queues to perform limited integration testing. Hardcoding dependencies limits the flexibility of the app.
Good point about stubbing out sometimes. But shouldn’t something like (with-redefs [bootstrap/system {:rabbit “my stub”}] <test-here>) solve the problem easily? As of running the app with a different configuration, you could get away by “TESTING=true java -jar target/uberapp.jar” and put a conditional in system.clj to wire-up the app with in-memory queues.
> And this part of the doc:
>
> "A: You see, this all idea of reusable libraries of components never worked and it gets complicated pretty fast. See the past 20 years of OO frameworks. Do you really want a Spring/J2EE in your beautiful Clojure app?"
>
> Is just wrong. Perhaps across multiple projects and multiple companies component re-use isn't as common as some would think. but within the same company/project components are re-used a lot. Not only does this quote it present a false dichotomy (either you have a nice Clojure app or you have reusable components). But it is also little more than an ad-homiem attack: "This looks like OOP, OOP is bad, therefore doing this is bad!”
You are right, I’ll re-phrase that to be more precise: "This looks like Java, Java is bad, therefore doing this is bad!”
What I’m trying to say is that I’m not big fan of libraries of components for clojure:
https://github.com/danielsz/system or
https://modularity.org/ comes to mind. Those are meant to be cross-organization. Even internally tho, I don’t like to build and grow our own library of components. At the beginning it sounds like a good idea, in the long term it doesn’t scale. There are several reasons that doesn’t work well:
1. one project need component #1 of X in the library and suddenly you find yourself with ActiveMQ client (and many others) in your classpath when you don’t use them. You can deal with it at the cost of an increase of the complexity of the library of components.
2. if internal library, it requires additional release cycle effort: an internal repo to host the lib, a snapshot/concrete builds management, in general doing changes in two projects at once.
3. if a project requires the component to act differently (say I need elasticsearch native client but all the rest can stay on the REST client) I bump the component library version +1 and add some config. Now on, I need to remember why there is a version difference and to pay attention when I update other projects. Still something you can handle with some additional effort.
So I noticed that if I just copy paste what I need in each project, it works as intended and scales just fine.
Now more on the Java bashing. My thinking is the following: if a language ecosystem constantly pushes you to depend on frameworks to maintain sanity developing an app there is something wrong. I would have some hard time convincing a Java team to just use JDBC and a db driver to connect to a DB. So we’ll use Spring and whatnot. In Clojure we have the luxury that the language doesn’t need framework patching. So I think I shouldn’t have said OOP, but more precisely Java.
Thanks
Renzo