A Case for Clojure and GraphQL: Replacing Django
ckl.io
ckl.io
The problem with using esoteric languages is multi-fold. First, you have to trust that the original programmers actually know the language enough to not create a massive disaster. Are they comfortable working without a framework, are they knowledgeable about all the issues that arise from building closer to the metal, so to speak? It seems to me that the answer is "no" more often than "yes."
Once this happens, you end up in a read-only code situation, and this is a problem because they leave the project with tons of bugs and downright stupid decisions. You are then left in the position to ask 15 people if they can make dollars or sense of anything written, and if you are fortunate, you will get one "yes." I joke that I know all 50 Clojure programmers in the US, and sadly, that's not much of an overstatement. If you want your code to exist, and you aren't a real somebody, then good luck. If you aren't located in SF, LA, or some other city that attracts talent, definitely do not use Clojure or any other esoteric language!
Of course, I didn't read the article, as it isn't loading at all.
In Java, we have Lambdas and Streams and some concurrency APIs and Clojure only seems to build _on top_ of these, making them much more ergonomic, simpler, AND encouraging immutability, to boot. Novice programmers love mutability, but in Clojure you kind of have to go out of your way to solve something with mutation. So to me (as long as users aren't getting carried away with writing macros) it seems you should land in a better spot with Clojure. If you're not seeing that's the case, then what is it? What are the common mistakes that you see these novices making that make for unmaintainable code---that somehow is not found in the same proportion in something more mainstream? Would seriously love to hear.
lein new luminus myapp +postgres +auth
And you're good to go. Everything is setup, and you just have to add the code relevant to your application.It's also worth noting that the nature of how web apps are built has changed over the years. Everything used to be done server-side, with the client just rendering HTML for the most part. A big framework makes sense in that context.
However, SPA approach is the popular way to build apps today, and all the UI logic lives client-side. The server becomes just a set of service operations, that are ideally stateless for scaling. You really don't need anything too fancy on the backend with that approach.
I guess this is an apples to oranges comparison when you put it that way. Eg, React and Clojurescript are great together; and of course so are many JVM frameworks and Clojure.
It's mostly a language comparison blog post. "These were the good parts of Clojure, these were the bad parts, etc."
The problems you list above are true enough regardless of language choice. I've seen disasters in Clojure as many times as I've seen disasters in Java or Python. Also, why are first-time Clojure programmers code worse than first-time C programmers?
yeah no i'm pretty sure that's a drastic overstatement
> you have to trust that the original programmers actually know the language enough to not create a massive disaster
The same can be said for any programming language, although I think you may find much more disasters in, for instance, PHP and Python projects than in Clojure and Elixir ones...
developers don't need to code a web server from scratch.
I mean, that statement is true. But there is nothing in the Clojure ecosystem anywhere remotely close to the level of functionality contained in a framework like Django - Luminus included. Partially this is cultural: the Clojure party line is that libraries are good and frameworks are baaad.
Rewrites are notoriously risky projects, I'm surprised you suggest this the majority of the time.
> you have to trust that the original programmers actually know the language enough to not create a massive disaster
This is my experience, but I've come across many coding disasters and none have been caused by misunderstanding the programming language. All have been due to poor software design or testing.
> Once this happens, you end up in a read-only code situation, and this is a problem because they leave the project with tons of bugs and downright stupid decisions.
Why have you pinned the blame on Clojure? What are the properties of Clojure that cause programs written in it to have so many bugs? Programming languages don't make decisions, let alone stupid ones.
> I joke that I know all 50 Clojure programmers in the US, and sadly, that's not much of an overstatement
This is a massive overstatement. Netflix, Apple, Soundcloud, and Walmart are all using Clojure. I work on a large team of Clojure developers, many of whom are located in the US. The Clojure community is large, healthy and growing. This is not an "esoteric" language.
> If you aren't located in SF, LA, or some other city that attracts talent
I work with Clojure developers all over the world, many in small towns in their respective country. My address hasn't been a factor for any tooling decision I've been a part of, it's a strange (overlooked?) criteria by which to judge technology.
And clojure isn't even mentioned in zdnet's most popular programming languages: http://www.zdnet.com/article/which-programming-languages-are...
Makes you wonder how indicative those lists are of anything.
The fact that it's already used successfully at large companies shows that it is an effective language. Most companies that try it end up sticking with it. So, I'm not really seeing a problem here to be honest.
There are certainly more than 8 jobs in London for Clojure. JUXT https://juxt.pro/index.html alone hires more people than that. Maybe you're just looking in the wrong places.
https://www.indeed.com/jobtrends/q-java.html
What do you think Clojure's absence from zdnet's list indicates?
Well, I can only speak from my own experience, but twice now I've personally seen enthusiastic talent python programmers create clojure projects which 'did all the things':
- used core-async heavily, including blocking channels that are never resolved in the UI.
- massive 'global application state' top level atoms that are mutated arbitrarily throughout the application
- massive complicated one line reduce/map/whatever where people are trying to be clever and reduce the lines of code, because 'fewer lines of code is better'.
I think it's telling when you get a 'walk through' from the person who wrote the code, and they have to stare at it, trying to figure out why it was they needed 10 different channels as they're explaining it.
After thinking about it quite a lot, my conclusion is that I would recommend against clojure for the same reason I would recommend against C: It's easy to mess it up.
Clojure allows you to create very complex applications; and you have all the tools to shoot yourself in the foot.
I don't think I'd tell people to migrate off clojure, but if the opportunity came to work on a new project, I would run away unless at least 50% of the people had actively used it before.
(and by comparison, my experience with a relatively novice team using elixir has been extremely positive; so yes, I do actually think this is a reflection on a clojure itself, not just 'insert any unknown programming language here').
Every language allows you to write complex applications, and shoot yourself in the foot. If I pick up Python tomorrow, and start writing a large application in it, it's pretty much guaranteed I'll make a mess.
You can build anything with anything. It’s all data manipulation. Some languages have a more fruitful ecosystem of libraries or offer a more efficient syntax for your particular task.
To be honest, the way that graphql is handled by the author in Clojure looks kinda inefficient. You have a language that allows you to create your own dsl with abstractions and macros but you write a massive edn map of your types? What’s the difference between that and using any other language at that point?
Interesting insight but I hope folks don’t read this post and think: “wow we are wasting our lives with Django and REST”. The four technologies here all have value and merit in their own ways.
P.S. I use Clojure and Python on a daily basis at FarmLogs
> Interesting insight but I hope folks don’t read this post and think: “wow we are wasting our lives with Django and REST”.
God no! As the author, I hope to god no one thinks that after reading the article. We're mostly a Python shop and we love it, but sometimes it isn't the best choice.
Today, there are plenty of companies using Clojure and consulting. There are literally thousands of Clojure programmers in the US, and many more around the world.
Meanwhile, Clojure is used by companies such as Amazon, Apple, Boeing, and Walmart. This isn't some obscure language anymore.
In terms of performance, Clojure is well known to be fast, and it runs circles around Python without any optimizations.
A friend of mine offers the somewhat humorous summary of Clojure as "a library that makes concurrency easier in Java." And I suspect that is why so many large companies are moving towards it. These were companies that had a large number of Java programmers. Presumably the programmers often made mistakes regarding concurrency, and they were looking for a way to make it easier to manage concurrency. And so they switched to Clojure.
Interop between Java and Clojure is seemless, so a lot of companies that are already using Java can add in Clojure painlessly. Actually, I should state that more strongly, Clojure removes some of the pain of dealing with concurrency.
Lacinia is new. The first public release was just 6 months ago:
https://github.com/walmartlabs/lacinia/commits/master?after=...
The fact that big companies like WalMart are committing to Clojure, and then releasing their libraries to the community, suggests that Clojure is going mainstream.
I'm sure there are plenty of ways to control it, but I'd wager that most will be ignored outside of basic ACL’s.
Often times certain user types should only have access to certain fields in data or be able to query it in certain ways.
Too often I see apps where the developers just assume they have full control since they're making the interface, while it's trivial to watch the API calls and intercept or modify them.
1. Wrap the entire query execution in an auth check. This is similar to whatever happens in a REST auth flow. Check the caller is legit before moving on. Nothing graphQL specific here.
2. Check auth on fields. This is a neat thing about graphQL. You can statically analyze the fields in the query to make sure the caller is only accessing fields they are supposed to. We do this by adding an `auth` property to the standard graphQL-js field object. When we build the schema we do some fanciness to wrap the resolvers in a new function that checks that field and behaves accordingly[1]
3. Throw errors on unauthorized data. Same as you would in a REST API. If you get back data the caller can't access, check it before replying. Obviously not ideal, but sometimes this is the only option.
At someone on twitter's request I wrote up some more thoughts a while back about running graphQL in production: https://gist.github.com/southpolesteve/08edb6a481c07f66eb71e...
I also gave a talk on this at Node Interactive last week: https://youtu.be/vI9ERvz9WWU
[1] https://gist.github.com/southpolesteve/e190e9572d060b5158366...
You can say they're "the same". GraphQL is an extra layer for developer-overlook (by design) and exploitation.
Also note, we didn't choose Clojure because of GraphQL, it simply came as a bonus in the form of Lacinia.
graphene-django is pretty buggy, mainly because both Graphene and Django have a lot of implicit behaviour that don't play well together - a common theme among popular Python libraries, sadly. A nasty example (that is now fixed) was that connection fields generated from m2m fields would return every single instance of the target model!
I do agree with your sentiment. Django is less and less valuable to me due to the lock-in. The ecosystem is such that lately you can compose your own system (ie, Flask, Flasql and Graphene, and pick your ORM poison of Peewee or SQLAlchemy) and have a much more modular setup where each part can be replaced more easily.
Having read the article, it's actually pretty nuanced, despite the headline. "These are the good parts, these are the bad parts, etc."
lmao