Coast on Clojure
coast.swlkr.comI always struggle with the idea that "frameworks are bad, combine libraries instead," it makes sense and makes orthogonal libraries not step on each other or make things more complicated. The thing lost is having an easy time getting up and running quickly. I was always a big Liminus champion fir this reason, they tried really hard to group a good set of libraries and document it all well. Bur this work is also fantastic. Sometimes, you really just want to get something done, and the batteries included solution might be the thing that gets your project done. I came from Ruby on Rails and will always miss that ability to get a DB connected, Javascript enabled, dynamic website onto something like Heroku from 0 to production in like... 20 minutes. So thanks for Coast, looks like it will help fill in an important part of the tooling spectrum.
Agree. There is a lot of value in the "easy, batteries included" solution which is why Rails gets so much love from the start-up community. The problem always seems to be that the same things that makes Rails easy to get started with (cough ActiveRecord cough) also make it easy to create foot-guns in the future (provided your start-up lasts long enough to get to that point).
Combining a Rails like framework that makes things easy with a language who's idioms prioritize simplicity seems like a great combination.
I am going to butcher this, but my sense is this counter culture against the big heavy opinionated frameworks arose from that generation of programmers who in a sense "grew up" (career wise) on things like Rails. Like others have said, there eventually comes a time where you are fighting the framework more than the framework is providing value, and having learned the value of the abstractions and functionality through multiple applications, they then became able to pick and choose a finer subset for a particular problem or domain.
The best of both worlds, in my opinion, is a loosely coupled set of opinionated tools and libraries, but that also has a tool that provides a unifying interface into the "golden path" for using those together to provide some functionality.
> The best of both worlds, in my opinion, is a loosely coupled set of opinionated tools and libraries, but that also has a tool that provides a unifying interface into the "golden path" for using those together to provide some functionality.
This is almost it. A few more things I think one wants:
- Do most of the coupling and plumbing yourself, IoC is evil when applied to things that do too much.
- Control the application state - see above.
- Be free to substitute any major part, be able to compose them freely.
- Re-use and extracting libraries from past work to be convenient, robust and affect past / maintenance-mode projects positively too.
- Be able to defer extracting libraries and generalizing up to the time you actually need to.
- Decouple code organization from artifact deployment.
- Be absolutely free in how you design and write domain logic and information processing - this is the brain of an application.
- Be absolutely free in how you design and write the UI - this is the body of an application.
- Have the tooling/utilities around code that fit your workflows and business needs.
I've come to the conclusion that full-stack frameworks in the style of Rails/Laravel/Django get in the way of some of the above and don't provide enough to make the above possible by themselves. I think the answer is not "use this framework" or even "build this framework".
It starts with your business/domain needs and builds from there - custom and simple. It builds up slowly and steadily like a garden that reflects your team's personality. It takes a careful, comprehensive, holistic approach. There are angles from version control, to project management to deployment that are all incorporated.
Sounds like “create-react-app”. A bunch of libraries and configurations wrapped up in a “golden-path”.
Provides the “easy” for 95% of usecases and an “eject” button that unwraps everything and puts it under you control for the last 5%.
Create react app was one example I had in mind, I think Redwoodjs is another one that recently popped up.
> Combining a Rails like framework that makes things easy with a language who's idioms prioritize simplicity seems like a great combination.
I think that's what makes Phoenix and Elixir so nice to use. The primitives Phoenix uses aren't too far from the surface, and the default setup is fairly batteries included without ruling out future growth.
To quote Rich Hickey: "gem install hairball"
I like that quote, but it's the Rails idioms and conventions that make hairballs, not the fact that it includes a bunch of batteries.
Adopting any framework is quite literally adopting the framework's idioms and conventions so not sure how that is different.
It was a general comment about frameworks. It’s possible to have a framework that includes all the “batteries” but has idioms and conventions that promote simplicity and maintenance.
Rails chose idioms and conventions that prioritize speed at the cost of complexity. The “included batteries” are not the problem.
The good 'ole days.
You're paying the tax at some point, but if that's at the start of the project it might be high enough to stop it in its tracks. A mature Rails or Django project require abstracting configuration later on in development which is a different sort of tax.
Convention over configuration absolutely has it's perils. I've unfortunately (fortunately?) hit this enough times with Clojure, I know the ecosystem well-enough I'd personally pick composition for a personal project. In a team project where composition makes collaboration difficult (generally a communication and experience problem) I'd probably choose another language with an opinionated framework.
Agreed, that's why I find it so difficult to leave rails/ruby. I really like Clojure+Datomic+Clojurescript but I can't justify the extra work needed compared to the extensive tooling and library support that rails has since it's mature and widely used.
I loved Coast and wrote at least one production app with it (and very quickly and pleasantly at that), but it needs to be said that swlkr is the only developer, and he seems to have mostly moved on to Janet (https://janet-lang.org/). Case in point, the last real updates to Coast were 2 years ago, and - unlike other Clojure libraries - not because this project was /finished/.
Yeah, I did move on, but if someone were to pick up the torch, I would help out any way I can!
Id actually love to hear what made you move on, if you have a few minutes to spare!
He wrote a blog post about it https://swlkr.com/posts/clojure-isnt-for-me/
TLDR: He hated the Java part of Clojure
Yeah that’s the long and short of it.
I spent a lot of time in jvm land though, a few years of nights and weekends, but I finally learned that it wasn’t for me.
I’m a C (or rust or llvm or what have you, wasm?) person, not a jvm person.
Tried GraalVM?
I’ve tried graal and native-image, both are awesome.
clojure still relies on the jvm though, for repl things.
sci and babashka were interesting, but at that point I had already moved on to janet
Ja that is always like a little splinter in my brain as well. I hope I don't bring out the language-wars but I always wanted a Clojure-Like but with Golang. :) I just love the go ecosystem and statistically compiled binary ! You shipping one binary ! :) No need to edit XML files and "tune java servers"
Again, this is just my preference. YMMYV
There are a few projects that try todo this like this one: https://github.com/mattn/golisp
But it seems abandoned.
I keep staring projects like this, but I haven't found the right level to put a lisp in the Go stack.
I've done a runtime lisp, but it felt like programming a lisp isolated from everything that made Go, well, Go. I've done a simple lisp to generate Go AST to do codegen pre-1.18, but that's not a complete program.
I haven't found the place yet that feels quite like Clojure.
there is joker https://github.com/candid82/joker but you may as well use the small clojure interpreter instead
The x86 monoculture has shaken around a bit. But surprisingly it seems there has been friction even on the JVM side, partly because of Docker style nonportable containers had time to cement in the x86 monoculture period.
janet looks really really good ! I like the use of channels for m.t
Any good HTTP/JSON/Crawler examples or libraries ?
libcurl wrapper - https://github.com/sepisoad/jurl
json encoder/decoder - https://github.com/janet-lang/json
Not aware of any HTML parsers/traverses (if that's what you mean with "Crawler") but interfacing with C libraries is easy so grab any C library you'd like for that task.
biff (https://biffweb.com/) is a little more batteries-included but seems like a nice successor in this space
Its default stack includes an AppleScript-like language that compiles to JS (Hyperscript) and a “feature” that automatically deploys to production every time you save… Doesn’t exactly inspire confidence.
He made a similar framework for Janet lang in Joy Framework[1] and it's unironically a joy to work with. Joy is one of those tools that is almost enough to make you use a different language imo. Got it where it counts, but still minimal and low mental overhead.
I'm surprised to hear that Janet is still alive and kicking!
Always nice when one of my projects makes it to the front page!
I haven’t worked on this one much lately, but I’m happy to answer any questions!
This is cool, but, aside from error messages, it resembles Clojure's biggest problem right now: Everyone keeps trying to re-invent the wheel with respect to creating the "Rails" for Clojure.
We have several production grade libraries and frameworks for serving webpages. Reitit(router), yada(http standards), bidi(router), aleph (netty wrapper), ring (jetty wrapper), pedestal (bundle of libraries), luminus (self described micro-framework), the list goes on, yet Clojure's biggest pain point is the lack of other production grade libraries for other/mundane things.
If the libraries do exist, they can barely cut a stable release (like 2.0.0-alpha24) or keep up with changes to prevent software rot.
Looks like this is mostly Ring + Hiccup (<https://github.com/coast-framework/coast/blob/master/deps.ed...>) with a DB connection pool.
Hmm. Can you give some examples of those missing libraries? I've been developing and running a large SaaS for the last several years and never found lack of libraries to be a problem.
Well, the biggest glaring thing is Clojure.spec. It's quite literally still in alpha (clojure.spec.alpha), and is a core part of Clojure, but everyone uses it in production anyways. (I might be biased here, I have opinions on whether or not clojure.spec should even be part of Clojure)
For example, things like clj-stripe, Matchbox(firebase lib) Onyx(MapReduce lib), and Cortex(ML lib) are all out of date.
One thing I see a lot from companies using Clojure(script) is they fork open source projects, extend them for their needs, and never contribute back.
Clojurescript libraries in particular are extremely bad for this. For example, re-frame-firebase has suffered some serious bit rot lately, the core repo uses firebase sdk 5.7, and hasn't ever really been used in a production setting!
Anyways, not trying to call out these library maintainers because I do understand maintaining libraries is time consuming. I'm trying to call out companies taking from the community and not giving back.
Hmm, interesting. As for spec, I use it in production, despite its shortcomings. And I think some of the shortcomings require very careful thinking and design, so I guess I'm fine with the authors taking their time.
The libraries you mentioned are something I never needed, but I understand what you mean now.
Slightly OT, but whenever I see Clojure projects I think: "I'd love to write something bigger in Clojure one day, experience it, and see if it's all it was promised to be."
That said, I don't really have any good use case for it right now, whether at work, or among my side projects.
I'm a year and change into my job at metabase (metabase.com) writing clojure all day every day and I am still terribly surprised that basically it is all that it's promised to be.
That said, you do need to actually use the repl and be repling all the time because the startup times suck and the stack traces are gigantic all the time. That's pretty much it for complaints. You would expect things that aren't apparent in 30 minutes looking at the language to come up after an entire year, but nothing so far.
Oh wow yeah I forgot about the stack traces. Clojure was the second programming language I ever learned, after self-teaching ruby. lmao ruby does not prepare you for a 700-line stack trace full of java classes you've never even heard of because they're deep in the implementation.
Does it still do that? I remember "better error messages" being a supposedly-coming-soon thing for the couple years I was using it. I eventually got used to it but damn what a hostile experience. In retrospect I'm pretty surprised I stuck with it. For better or worse I don't have that same tolerance & resilience now.
Error messages are much easier to parse now!
(Seems your comment was dead, but I vouched for it as it's contributing to the discussion)
Yeah, with the arrival of clojure.spec, some error messages has indeed gotten easier to both read and parse (for humans and machines alike), although when you use Clojure JVM so still come across the odd huge Java stack-trace (or with ClojureScript, a pretty sizable JavaScript stack-trace).
I did clojure as a hobbyist for years and have only recently taken a job where I'm working full time in Clojure on a large codebase (i.e., first time having to maintain somebody else's Clojure code). It's not a golden hammer by any means, but I'd definitely take it over Java (or Scala) any day.
any experience with rails or django to compare with?
Not to be pedantic but you’re asking for a comparison of language vs. frameworks. Not sure if you’ll get a good answer to that.
That said, I’ve actually used Rails and Django in the past and written a small project in Clojure so I can try.
I actually really love Clojure and had really positive experiences wit Django though I’ve come to favor lighter frameworks like Starlette. Programming in Clojure is quite interesting because it’s functional programming so all the information you need to reason about the function is generally passed in as parameters. It made code comparatively easy to reason about simply by reading the code for the specific function. Clojure also has good support for REPL. I don’t have to do a lot of hunting around for “outside” code to understand what’s going on inside a function. This is the polar opposite of Java, especially when dealing with giant frameworks like Spring, where there is a lot of layers being combined just to do one thing. Coding in Java/Spring, Rails, and even Django can feel a lot like dealing with those nesting dolls.
Like the grandparent, I wish to do more with Clojure some day.
Correct. I like ruby the language. Rails, not so much.
sorry, i also use clojure for hobby projects and am familiar with clojure/repl/etc.
i guess i assumed that since this thread was about web frameworks that their large clojure code base was also a web application. though i see that isn't necessarily implied.
React and ReactNative in Clojure(Script) are amazing if you work in that area. Honestly, I'd never go back to a JS implementation. Reagent [1] provides a seamless interface for components, classes, hooks, etc. and ShadowCljs [2] is a fantastic build tool for the ecosystem. Re-frame [3] is a popular framework in this space.
[1] https://reagent-project.github.io/
This is exactly what I just set up! Super cool - coming from doing Redux sagas and hooks and redux and all that stuff on RN it's been really interesting. Would you recommend Shadow vs Krell? I have tried both and so far Shadow was the most seamless, but Krell seems the most lightweight.
If you care to share, i'd love to learn what you are building with it.
I haven't used Krell, but Shadow has been great for me. Been on it a couple years now.
My company is in the smarthome/IOT space and we use React(Native) + Clojure and ClojureScript for all our apps, dashboards, servers, etc.
Same here! I wanted to learn it and Overtone years ago, tried to, realised my brain was just not prepared ;p.
I have a bit of time now and I am diving in again and am more determined this time!
I got clojurescript going with react native, and having fun so far. If you need inspiration check out Rich Hickleys talks. He keeps me going through the hard times!
I definitely recommend messing around with it, even just for a toy, but yeah I'm in a pretty similar boat. Can't think of any specific use case that I don't prefer another language for. On the lookout though!
Love to see Coast getting some attention again! I got my start into Clojure with it working with Sean on small web apps written in Coast. I even gave a talk about it at the Berlin Clojure conference
The first project we built together with it was called magehash, and it was an app to monitor websites for Magecart attacks (code injection stealing credit card data).
That project ended up not working out, but I’m using a lot of the lessons I learned with Sean at my new project (https://www.june.so) which is ironically a Rails app and we keep in touch on Twitter regularly
So much fun working on that project!
Turns out it's really hard to beat the productivity of rails
This looks very nice! Happy to see something batteries-included for the Clojure crowd. How does this compare to Luminus?
Unless I missed something in the doc, it seems like it's the "Fullest full stack framework" as long as you're only interested in the "handling web server request and reply with html" part of the full stack.
Any reason why this should be used instead of cooking up ring / hickup / whatever ?
Someone elsewhere mentioned that this seems to be ring, hiccup, and a DB connection packaged as one. Pinch of salt needed, I’ve not used it :)
This is mostly ring / hiccup, just a layer on top to make it easier for beginners.
I would say if you’re not new to clojure, roll your own.
Thanks for posting this. I might want to give it a try with my very old 'smart' nutrition and cooking website [1] that I wrote in Clojure about 10 years ago and have not touched it in years. I wanted to update it a few years ago but the Clojure web libraries/frameworks I used are no longer supported.
Looks great! I also like the informal, conversational tone of the documentation. :)
Perhaps I'm being too quick to judge, but it appears to basically be ring/compojure.