5 ms·
> Also, be prepared to deal with the cultish obsession of the community. They have very strong opinions but will never elaborate. I'm curious to know what "cul
by nocman 6y ago
> Also, be prepared to deal with the cultish obsession of the community. They have very strong opinions but will never elaborate.
I'm curious to know what "cultish obsession" you are referring to. Also, what strong opinions have you been unable to get elaboration on?
- Kalium 6y agoWhen working with Clojure teams, I personally ran into "libraries, not frameworks!". Interesting maxim, but I never found any kind of satisfactory explanation. There was a general deep-seated belief that Clojure was the right solution for every problem, with a similar amount of elaboration.
- lostcolony 6y agoI have that maxim for...basically every language I use, though, despite never using Clojure. There's a little wiggle room; I think it's largely dependent on what you define each by, but basically anything that forces me to write my app in a certain way, and limits how easily I can slip in things that are clearly libraries, become liabilities, and I would prefer to avoid. Obviously that's hand-wavey; there are plenty of things that people will call frameworks that nevertheless dictate very little, if anything, about the structure of your code, and which are easy to get to play nicely with other libraries. But there are also plenty that...don't. But to play it safe, I look at things that described to me as frameworks with far more suspicion than I do things described as libraries.
- Kalium 6y agoIt's definitely a wonderful goal to aspire to, and ideal for small or personal projects. In my experience, I've found this particular approach to be, at times, of unfortunately limited value in developing and maintaining enterprise systems. A previous employer of mine was a Clojure-heavy shop. There were multiple teams. A Clojure dev going from one team to another could expect to find themselves in a very different stack with very different conventions to do very similar-looking web service tasks. In essence, each team had composed their own under-documented framework.
- lostcolony 6y agoI've had no issues with it in enterprise systems. Note that it doesn't mean you can't use a framework...it just means prioritizing ones that feel more like libraries, and minimize their surface area. I've worked in a shop that had 8 dev teams, all working on different systems, all in Node, using Express. We favored standardizing, but standardizing on something easily extensible. The middleware approach made including non-standard things really easy; if I needed to include some custom authentication library that wasn't written for Express, it was trivial to do it; a couple lines of glue was all it would take, even if it included some initialization. Compare that to a Spring, say. I have to know about the framework's authentication interfaces, implement a comparatively large amount of glue in terms of those interfaces and configuration, and even more hoops to jump through if there's state I need to initialize first for the underlying library. That's what I mean. I'm not arguing for or against standardization, but extensibility and minimal cognitive overhead in extending it.
- Kalium 6y agoYou're absolutely right. Extensibility and minimizing cognitive overhead are imperative. What I found through my experience is that offering many hooks for extensibility sometimes increased cognitive overhead for the team. With so many ways to accomplish a given task, no agreement on how to do it, and no guiding conventions, moving from one part of a repo to another can entail nontrivial cognitive overhead. Moving to a different project with a different collection of extensibility approaches employed for the minimal cognitive overhead of those authors sometimes compounds the problems. I've seen developers do things that were easy, obvious, and extensible to them but utterly incomprehensible for everyone else. Having the freedom to compose libraries as they saw fit may have made it more likely. Compare to Rails. For all its many, many warts and often exceptionally opinionated quirks, it's often relatively easy to move a junior or mid-level dev from one part of the codebase to another. Or one team to another. Or even one company to another. Many of the conventions are the same and the standards largely match, making onboarding easier. This can also make it easier for a random dev to predict how the system might be extended for a given task, easing maintenance over time. I think the core tradeoff here is between what minimizes overhead and cognitive costs for an individual and what is optimal for an organization. Also, I ran into issues with Clojure teams composing their own stacks and forgetting things like basic security measures of the sort that mature, pre-fab frameworks like Rails build in by default. They minimized the surface area so hard that they maximized the ignorance they exposed, producing services that couldn't be bothered use CSRF tokens because the developers had never heard of them. Again, I think you're right. It's about extensibility and cognitive overhead. I've just found there to be some nuance to what approach provides the best outcomes. I don't particularly enjoy being bossed around by a bucket of bits that tells me how I'm allowed to express my wishes, but I've found that my emotional experience of it isn't the important thing.
- slifin 6y agoClojure is a good solution for many problems (obviously not all) mostly because it reaches many capable runtimes, java, js, python and interop is first class What you might be encountering is after a few years of Clojure becomes such that you'd rather not be writing anything else and that is semi-practical as opposed to many other niche specialised languages where it's not so realistic Libraries, not frameworks is a point of contention even within the Clojure community, libraries tend to compose and upgrade better over time but there are also frameworks in Clojure Luckily we don't have one that dominates the language so totally that it cannot be ignored despite what inevitable deficiencies it has Keep in mind most Clojure developers came from other languages and have Vietnam flash-backs to many frameworks
- Kalium 6y agoAt this point I have Vietnam flash-backs to dealing with the hand-rolled, ad-hoc, half-built, undocumented frameworks that Clojure teams I worked with produced. Seems like a weird form of therapy to me, but what do I know? I also found the points about interop to be nearly academic. The teams I worked with went to significant amounts of trouble to avoid using it whenever they could.
- ithrow 6y agointerop is first class That's hardly true, not even clojure.org claims that. Interop is far from seamless.
- slifin 6y agoMy reference point for my comment is ReasonML which on its homepage claims "Easy JavaScript interop" In comparison, I didn't find that to be the case
- daveliepmann 6y agoI would say that "first class" is a perfectly reasonable way to phrase it. While clojure.org doesn't use that exact phrase, host interop has always been a central pillar of the language: >Clojure is designed to be a hosted language, sharing the JVM type system, GC, threads etc. All functions are compiled to JVM bytecode. Clojure is a great Java library consumer, offering the dot-target-member notation for calls to Java. Clojure supports the dynamic implementation of Java interfaces and classes. What do you mean by "far from seamless"?
- elwell 6y ago> libraries, not frameworks I think this originated in a conj talk several years ago. However, the speaker mentioned that it was simply too early to have Clojure frameworks, but that in a few years they will be helpful. Can't find the talk at the moment unfortunately, may have been by Alex Miller maybe in 2011 - 2013.
- deleted 6y ago[deleted]
- derefr 6y ago> "libraries, not frameworks!". Interesting maxim, but I never found any kind of satisfactory explanation. I mean, that's more widespread than just Clojure; it's a generally-held belief in most of the functional programming world. A library is just a bag of functions you can reuse at your leisure, hooking them up as you wish, calling the ones you like, passing references to the ones you like, and replacing or dropping the rest. It's a box of LEGOs. You can mix it into a big box with your own bricks and other libraries' bricks, passing the closure from X to the HOF from Y, and it all just works together, because nothing's expecting anything more specific than "data of the right type" or "a function of the right type", where the types are all basic core-language data types. A framework already plugs some parts together for you, in a way that means you can't just replace some of those components with something better or more suited to your use-case. It's more like a molded plastic figurine that happens to have some explicit LEGO attachment points on it. I personally know which one I'd prefer to find, upon opening up the docs for a new library. Every framework I've ever used, I've eventually had to fork in order to have an app inject some bit of customization into its behavior in a place it wasn't expecting such customization would be needed. Libraries don't have this problem. Libraries-over-frameworks is also a bit of old-school Lisp-ism poking through. Regular programming languages tend to do things like web apps or games in terms of an opaque framework driver piece, that gets configuration handed to it in some descriptive format. To someone coming from a Lisp, that's silly: what better configuration format is there, than a programming language? Especially one tuned for expressing the app's domain? What a Lisper would expect a Lisp web-app library or game engine to do, is to build up and up from functional primitives into a high-level DSL, and then have the user write the final driver code in terms of the library's DSL. Then, the "configuration" is just the logic of that driver program—which can also drop out and replace any part of the library it wants, just by calling/passing a different function than the one you'd expect. You can see this contrast in Emacs vs. vi: • vi is a native program, that upon startup, parses a bunch of files in a custom configuration language, where each directive triggers its own special change to vi's internal state. • Emacs is a Lisp runtime, where all the stuff that makes Emacs Emacs, is implemented as a set of ELisp libraries which call into said runtime. Each Emacs "major mode" is just an ELisp program that calls into those libraries. And your toplevel global configuration is just an ELisp program that defines the functions that are hooked to call into the major modes.
- ithrow 6y agoOne of many: https://twitter.com/KirinDave/status/1234685098600960000 https://twitter.com/KirinDave/status/1234685098600960000 Laughed at the "How to refactor? Just don't write code that needs refactoring, simple made easy!"