Good morning
π
We've not had the best of experiences with java/spring boot for creating graphql apis. Are things better in clojure land?
Hey Everyone! π
Oh, my comment may be misleading. Backend is just REST, it's the frontend, that is React and Apollo. I have heard a few good things about <https://lacinia.readthedocs.io/en/latest/>
however.
I was expressing how easy it was to change the javascript, have it hot reloaded and at the same time also eval my clojure buffers (a much better experience as we know) without having to stop/recompile/start again π
Since on the other backend I look after, all done in Kotlin, I've got this library <https://github.com/ExpediaGroup/graphql-kotlin>
down to explore, which also works with Spring(boot)
Do you use that library?
(or, the graphql-java version)
We did one thing using the graphql-java spring boot starter, and that's basically fine, but doesn't support batch loading (a fix for that was merged well over a year ago, but they haven't done a release since, because there's a serious problem with it).
Then for another project we tried to use the grahql kickstart library instead (which is built on top of graphql-java), but we had to abandon it, because it was taking several seconds to construct the json response
I'm guessing that the expedia one is this best choice
Kotlin is a bit of a sensitive subject, because at some point our architect (and others) were keen on doing things with Kotlin, so I was pushing for it, but then he backtracked on that because he decided we had too many (new) technologies being used. (We do have some tests written in Kotlin, though!)
It's ironic, but when I joined my current company, I was the one who introduced Kotlin. We abandoned writing Java +3 years ago. Everything is written now in Kotlin or Clojure (which I advocated too).
Everyone at work is very very happy with Kotlin (and I'm very very happy with Clojure)
I do still write Kotlin too, for other projects I look after.
mΓ₯nΒ‘ng
I don't think anyone at our work would like to go back to writing vanilla Java again. We don't disallow it, we don't discourage it, but we don't promote it either π
It's an option - a few "blessed" languages on the JVM - Java, Kotlin, Clojure.
Pick your poison! π
We have a few people who are keen on Kotlin
I think at least one person who looked at it and said "That's different, I don't like it"
And some who seem interested to learn it, but haven't
morning
i seem to have implemented clojure's case
and cond
forms, complete with square bracket list syntax in my current TS project lol
the typescript switch bulls--t was so verbose for what we needed (predicate matching for querystrings) so started writing a data oriented thing and then eventually realised it was just a mini lisp DSL
except lazy like haskell, thunks everywhere carrying around little happy monads
like Bob Ross' little happy trees
No mistakes, just happy little accidents.
He's great Bob
morning
Morn'
Morning
Morning
@arohner whenever i see your handle, my brain somehow reads it as the title of this perfect circle song (renholdΓ«r) https://youtu.be/KayJYjg1vbI
Coffee time!
Here's a question. You know in architecture, you would traditionally have a 3-tier layer, i.e., Presentation/API, Service/Application, Repository/Data, would there be a similar setup in Clojure, i.e., an API layer, then an intermediate layer that may do some data translations before hitting the data layer? What do people do in Clojureland?
bbiab.
i quite like vertical slices where each vertical slice has a transformations namespace and a db namespace so similar to what you're describing
would you call that foo.bar.transformations
?
probably yers
db.clj
transformations.clj
utils.clj
format.clj
are very common namespaces in my subfolders lol
in current typescript project very similar too (typed functional typescript)
db.ts
transformations.ts
schemas.ts
types.ts
and then the api layer is all in a totally separate folder - oriented into REST entity subfolders with stuff grouped into files there
ha, like me!
except for the transformations thingie π
i tend to try and get any data -> data functions for a given entity away from the side effecting ones if possible cos you very quickly see then what the general case is & then can lift them up and out to more general helper namespaces or whatever
in our current project that's led us to a monadic approach
cos generalising the transformation functions leads you to pipelines of composed monads which you can then safely chain in your side effecting functions (i.e. the outer handlers -> equivalent to the main
fn essentially)
π·
i wouldn't worry @dharrigan - i think R
is far below 1 for this particular pathogen
it's really noticeable how the railway style we are using Eithers how composable they become
the general case for a problem becomes ludicrously general
hence why i was essentially reimplementing clojure's case
and cond
yesterday so we could chain thunks of compatible monads
just partial application innit :D
or, at least, just syntactic sugar for what we could accomplish with partial application :)
yeah, i've been working on my monad lib a bit recently and it's really interesting how some very generic concepts are emerging, which can be uniformly applied across very different types of contexts
i'm definitely beginning to see how combinators become increasingly useful
cos the general case of a cond
where the dispatch of each pair is a thunk is that the predicate should be a thunk too, which is a combinator i think... it's thoughts like these that reveal some of this stuff is above my brainpower level lol
yeah, general cond
sounds like a list of [pred-thunk match-thunk]
pairs
xactly, but then you go "is this too general to be useful"
i mean the answer is no, but it's like an alien language to anybody that's not done much fp i guess
becoming increasingly aware of the fact this code base is going to need handing over in 3 mths or so
it's the abstraction dilemma - do you build new abstractions to make more robust software re-using fewer, more fundamental, better tested, components, or do you use familiar generic components more verbosely and repetitively because new developers will find it easier to grok ?
see also: monads
see also: fp in general
haha
but yeah exactly
i suppose it's a different tradeoff calculation when you're a contractor who knows you've gotta hand over software on paper - but in reality all developers come and go on a project so maybe it's more about pragmatism in the face of that
what would you do if onboarding wasn't an issue / what is the most robust general case solution sui generis
i'll probably always favour a better abstraction π¬, although i've not gotten around to rewriting everything in haskell yet, so maybe not
lol
If I'm playing around at the repl, can I "inject" a var in #'user
to another namespace, i.e., #'user/foo
injected into my.namespace/foo
so that if I was to then do my.namespace/foo
it would be the same as the value of #'user/foo
?
inject is probably a bad word, but I hope I convey what I mean
intern
(intern (find-ns 'my.namespace) 'foo foo)
will stick foo
in my.namespace
with the current value of foo
from the current ns.
dev=> (ns foo.bar)
nil
foo.bar=> (in-ns 'dev)
#object[clojure.lang.Namespace 0x7bdf8c92 "dev"]
dev=> (defn foo [x] (* x x ))
#'dev/foo
dev=> (intern (find-ns 'foo.bar) 'quux foo)
#'foo.bar/quux
dev=> (in-ns 'foo.bar)
#object[clojure.lang.Namespace 0x2bfa5678 "foo.bar"]
foo.bar=> (quux 12)
144
foo.bar=>
@dharriganI don't know if that's the best way but...
perfecto
it's only for playing around π
thanks
works a treat