Fork me on GitHub
#clojure-uk
<
2016-08-02
>
dominicm06:08:06

@paulspencerwilliams: Yeah, a lot of places are connected to the train station there it seems.

agile_geek07:08:06

Bore da. Refreshing to see conversations from people not based in London in this channel. Mind would be nice to see someone not based in England! Any Scotland, Wales or NI based Clojurians out there? I'll even accept Jersey, Guernsey, Alderney or IOM (but not the Isle of Wight!)

glenjamin07:08:53

i’m half scottish

agile_geek07:08:28

I was amused that @jr0cket's Spacemacs demo in 'Church of Emacs' meetup last night turned into a Clojure tutorial half way through! 😀

dasmoth08:08:32

@agile_geek: what do you have against IoW? It's harder to get to from mainland UK than most of the other places you mentioned!

agile_geek08:08:24

I don't have anything against the IoW but if ease of access was the definition of mainland UK my Mum's house would be outside the UK!

dominicm08:08:59

As would most of wales, including my Mum's house

thomas08:08:29

I saw the IoW last week…. isn’t that far away!

otfrom08:08:59

thomas: you do need to go back to the 1950s to get there though

otfrom08:08:08

more design chat today: what do people feel about validation and logging "functions" that pass the arguments passed in through

otfrom08:08:27

this is to make it easy to put them in the middle of a -> or ->>

otfrom08:08:22

the validator would throw and exception or do some sort of error monad or if everything passed just return the object coereced or unchanged, the logger would just log and then return the passed in object

tcoupland08:08:31

throwing an exception and returning an error monad are really different though 🙂

dominicm08:08:02

I like conditional restarts

dasmoth08:08:12

I think that makes sense. The logging version is basically traceId from Haskell, which makes a fair bit of sense.

thomas08:08:40

@otfrom: yes… the ferry does take that long, true

rickmoynihan09:08:44

@agile_geek I Work in Manchester; live in Yorkshire and used to do Clojure in Scotland (Dundee) circa 2008/2009

korny09:08:10

I’m quarter scottish - my main hope for getting a EU passport some day

korny09:08:34

I spent a year doing some levels of clojure in Scotland (Glasgow) at SLC (via ThoughtWorks)

rickmoynihan09:08:01

I'm 1/4 Scottish - and my better half's scottish - so that's 3/4 Scottish, right? 🙂

korny09:08:30

Actually being half Dutch would get the passport too, but I think I have to live in the Netherlands for years, and speak dutch as well. Maybe I can retire to the Netherlands one day...

korny09:08:34

I think I asked something similar here, but can’t remember the results - what are people’s favourite templating approaches, for non-html text file generation? (I’m making bash scripts with embedded config files in heredocs - whee)

korny09:08:34

I think I used Selmer in the past, and it was pretty nice.

rickmoynihan09:08:06

mustache is actually surprisingly nice... though the clojure mustache libraries (clostache & stencil) I've tried have some flaws.... I saw a new one based upon a well used Java mustache library - which might be better

rickmoynihan09:08:42

mustache does a good job of removing almost all of the logic from templates, and putting it where it belongs in clojure

rickmoynihan09:08:00

though it has simple conditionals, based upon the presence/absense of values and iteration, based on a datastructure being a sequence - that's basically all the control flow it gives you.

korny09:08:28

I’ve done a bit of mustache in the past, it is nice, but I always found control logic a bit painful.

rickmoynihan09:08:38

selmer has too much logic for me

korny09:08:44

There are lots of options on clojure-toolkit. Looking at basil now, which embeds clojure logic inside tags - that might actually be OK for me, though normally I’d run screaming...

dominicm09:08:21

@rickmoynihan: The extra logic selmer adds is to help in the 5% cases where mustache doesn't work

dominicm09:08:59

It's based on the work of jinja2/django templates. If you don't have those features, in my experience you end up with rickety templates.

rickmoynihan09:08:16

curious what you found painful about the control logic?

dominicm09:08:20

I also found mustache's syntax to be somewhat ambigous as it treats destructuring the same as a list.

dominicm09:08:30

Long time since I went in deep. But one thing off the top of my head, ability to extend the scripts/css section in extended templates. I don't like the css for one particular page to be in the middle of it, I want access to the top. Or to be able to go back and "turn on" that css.

dominicm09:08:11

I think Mustache encourages doing that logic in the view, but that gives too much knowledge about how the template operates (imo).

rickmoynihan09:08:13

my only painpoint with mustache - has been on validating templates/keys - some items are required others are optional... Ideally the template would communicate that difference in itself (rather than with a bolted on schema/spec)

korny09:08:45

It was a while ago - I honestly can’t remember, but I remember having ugliness trying to do nested loops. The details have gone. Also at that stage, pain with different flavours of mustache - differences between languages, handlebars being slightly different...

dominicm09:08:58

I'm admittedly thinking of my heavy CRUD days back when I used Django a lot. So my use cases are possibly different to those you experienced.

dominicm09:08:45

I think it's difficult to have the perfect balance of logic-less in your templates (or views). I prefer to have power, and use discipline.

rickmoynihan09:08:31

nested iteration is just nested datastructures.... But the differences between mustache flavours is a big problem - and where the clojure implementations haven't really kept up with the javascript ones - the main case for me was with templates calling subtemplates.

korny09:08:36

Hmm … some comparisons:

(render "[% for ele in foo %]{{[{ele}]}}[%endfor%]"
                 {:foo [1 2 3]}
                 {:tag-open \[
                  :tag-close \]})
vs
foo
<% (for-each [a [1 2]
              b names]
     (str ":a=" a
          ", name=" b)) %>
bar
vs
<ul>
{{#people}}
    <li>{{name}}</li>
{{/people}}
</ul>
(selmer, then basil, then clostache)

rickmoynihan09:08:37

but you can work around that

dominicm09:08:02

In fairness, you can do selmer in a file, and without tag changes:

<ul>
{% for person in people %}
  <li>{{person.name}}</li>
{% endfor %}
</ul>

korny09:08:27

I was just copying from their readme 🙂 But yes, that’s better

dominicm09:08:46

Odd, perhaps trying to show all the features at once.

dominicm10:08:03

I recently converted mustache site to selmer. There are 1-to-1 translations of all ideas.

dominicm10:08:29

I was able to do most of it with vim macros.

korny10:08:09

One advantage of handlebars/mustache or something else that is a bit cross-language is most editors/IDEs understand it.

dominicm10:08:33

Yep. Then again, Selmer is based on Django templates, and I've seen those in js as well now. It is spreading

glenjamin10:08:33

selmer is basically jinja/django/twig/swig i think?

rickmoynihan10:08:57

perhaps the main reason we use mustache is because or designer (who's excellent) wireframes the html in it and renders mustache templates with static data... by using mustache we get to reuse his work... We have used enlive in the past for a similar workflow

rickmoynihan10:08:56

probably fair to say that your templating technology is probably one of the least important decisions you're going to make

rickmoynihan10:08:16

so long as it works of course

dominicm10:08:16

I'd say it makes up a yak-shavingly-frustratingly larger amount of importance if you get it wrong

dominicm10:08:59

I suppose, a small/medium sized site can be changed in a day or two though with the right tools. So I guess not.

rickmoynihan10:08:22

yeah - for a big project its more important

dominicm10:08:22

I think that's why I err on the side of "too much" power.

dominicm10:08:33

Because I can always decide a practice is bad for maintenance.

dominicm10:08:11

I'm also an optimist. I believe that code never rots.

dominicm10:08:18

Right guys?

mccraigmccraig10:08:19

@agile_geek: are you casting the IoSc out of the union too ?

rickmoynihan10:08:25

dominicm: not found anything we couldn't do in mustache... sometimes it does involve a little thinking about how to use it... Pretty sure we solved the problem you had by just associng in :head {:csspath "/blah.css"} in wrapping functions that need different sheets. I think we already have a powerful language, clojure... we don't need another 🙂

rickmoynihan10:08:49

but YMMV... and selmers definitely a fine option

korny10:08:03

Which mustache are you using? Clostache, or Stencil, or some other?

rickmoynihan10:08:43

korny: I started with clostache - then switched to stencil because it wasn't complete enough

dominicm10:08:13

@rickmoynihan: I would counter that with: I don't want my controller to care about internal template variables. That's my view on where boundaries lie though. And it's different for everyone.

rickmoynihan10:08:10

stencil has definitely been better than clostache for us... but I think the newer one that wraps java might be better still as clostache still doesn't have parity with some of the js mustache implementations

dominicm10:08:48

https://github.com/eclipsesource/j2v8 someone should use this for total parity 😄

rickmoynihan10:08:44

I think this might be the other clojure mustache templater... not used it or looked at it yet though... so can't recommend it: https://github.com/billrobertson42/mustache.clojure

rickmoynihan10:08:55

@dominicm: that's a fair point... but I don't consider that part of the controller... I consider it part of the view/viewmodel... basically just a function that "renders a datastructure" for the template to display.

dominicm10:08:23

@rickmoynihan: That's an interesting split, it adds an additional layer to the rendering step. Which is fine, I've just chosen to do that in the Selmer template, instead of as an additional step inside Clojure. (or rather Jinja2/python). It's just a different view on where boundaries lie, and what to put inside each of those boundaries.

rickmoynihan10:08:17

agreed... I just don't think the language boundary needs to be the responsibility boundary

glenjamin10:08:27

the nice thing with a viewmodel-type approach is its easier to unit test if you want to

rickmoynihan10:08:12

@glenjamin: +1 testing is easy

rickmoynihan10:08:56

not saying other approaches aren't testable though - just that this one is

dominicm10:08:27

What kind of things go in your viewmodel that you need to test?

rickmoynihan10:08:12

the thing I'd personally like more assurances over with testing is on which keys in a template are required/optional - as our designer can change the template and introduce/remove/rename keys... currently I've not found a way to raise an error when some keys aren't rendered in the template

dominicm10:08:57

I guess you'd need some kind of callbacks, or read status. An interesting feature, you should totally fork something and add it. 😛

dominicm10:08:36

Perhaps returning the keys with metadata attached when they've been read.

rickmoynihan10:08:59

dominicm: yeah it's something I'd like to do... among a million other things

rickmoynihan10:08:17

> What kind of things go in your viewmodel that you need to test? dominicm: well the nice thing about the mustache approach is that its data centric... so you can split the page into various components... e.g. something like (side-bar params) (paginator num-results params).... Each component returns things that are independently testable... Then your render-page-foo function can do (layout/render "foo.mustache" (merge (sidebar ,,,) (paginator ,,,) ,,,) A benefit of doing this in clojure is you have a lot of flexibility to test individual pieces in isolation or composed together

dominicm10:08:02

What sort of tests do you perform against the results of those fns though?

rickmoynihan10:08:19

whatever you need to depending on the granularity.... e.g. you might test that there are 10 results on the page that the page :title is set appropriately whatever... I'd probably want to write clojure.specs for this now

korny10:08:41

We used to test rendered partials using some basic assertions - “there should be N <li> sections” - enough to make sure that the basic logic between the templates and the code worked. (this wasn’t clojure but the same principal applies"

korny10:08:17

The idea being that if someone added a class to a template, it shouldn’t break a test. If someone deleted a % so the template didn’t render properly, it should.

rickmoynihan10:08:20

at the unit level we don't tend to test the rendered output... maybe the odd regex... it's a weakness in what we do right now... though our designer tests the templates themselves with mock data in json/edn... and he's religious about visually verifying they view correctly given the right data... though this is outside of the app. One option we've been thinking about is associating a JSON schema with the mock json data to specify the templates requirements and validating it clojure side... still need to think on it more.

rickmoynihan10:08:55

lots of options...

rickmoynihan10:08:13

this is one reason I'm interested in bridging clojure.spec and json schemas some how...

dominicm10:08:16

Seems like a frustration to have your tests start failing if a template changes.

dominicm10:08:30

@rickmoynihan: I was speaking to @lvh yesterday, he's working on it

rickmoynihan10:08:46

yeah I was speaking to him about that too 🙂

dominicm10:08:13

I'm not paying full attention to spec honestly, because it doesn't suit the domains I'm interested in unfortunately.

rickmoynihan10:08:33

@dominicm: I don't want the tests to fail if a template changes... I don't care about the template... I only want it to fail if a key in my datastructure no longer renders etc...

rickmoynihan10:08:39

those kinda things

korny11:08:07

I do want the tests to fail when a template changes. Why don’t you care about the template? Would you prefer it to fail in production, or trust to manual verification?

dominicm11:08:09

@rickmoynihan: string search for the uniquely random variable you inserted?

korny11:08:33

The people changing the templates should be running tests before checking in anyway, so you shouldn’t see the tests fail.

rickmoynihan11:08:06

sorry - I mean I don't care about the visual rendering of the template... I do want it to fail if it's not rendering what I expect

korny11:08:29

yeah - fair enough, there isn’t a good way to automatically test visual rendering.

dominicm11:08:33

@korny: I trust manual verification more. Especially with something like HTML/CSS where: - Template designer may not know Clojure - It's an extremely iterative process.

korny11:08:22

We had one project that took screenshots of key stages of the build, then made a movie file out of them and got a UX person to review it manually occasionally 🙂

dominicm11:08:24

I've seen something (maybe with Clojurescript) where they would spawn a browser, and blow through a bunch of sample data using React pure templates, to visually check the rendering was good in all scenarios. It was a really interesting idea.

rickmoynihan11:08:38

korny: actually you can; you can do diffs on bitmaps and error if a certain %age of pixels are different... It's not something we do yet - but it can be done

dominicm11:08:43

The human eye is good at catching that.

dominicm11:08:58

Yeah ^^ That is something wix did.

korny11:08:49

@rickmoynihan: true, though that’s only useful for regression testing. Too fragile for my liking, though I guess in a proper CD world, you could use it to make sure no typos slipped through.

rickmoynihan11:08:24

basically - our designer will have checked the visual rendering of the page... and it will work if I feed it the right data... the problem I have is knowing when the requirements for the template change... Right now I just have to check the merge for template tweaks... and then inspect the accompanying test data json file to see what's expected, and then port the changes into my code... It works quite well as a process... but it would be better to use a shared schema/spec.

dominicm11:08:25

I'm personally not sure if checking for visual rendering is really beneficial. I don't think checking html structure is either.

(defn list-item [foo]
   (str "<li>" foo "</li>"))
To me, testing any function like this is a waste of time. When it becomes (str "<div class=\"list-item-because-css\">" foo "</div>"), as long as it looks right, I don't care much about how it renders. Just my take on it though.

dominicm11:08:01

I can see visual rendering being an automatic test if you do a lot of refactoring and regularly though. But not sure how many people do.

glenjamin11:08:12

so generally tests are there to catch unintended changes

glenjamin11:08:27

with well-scoped templates it should be hard to introduce those

glenjamin11:08:44

but small components used in a wide variety of contexts are probably the ones that would benefit from tests

glenjamin11:08:28

I’m running a workshop on testing with React at jsconf columbia - so this topic is very relevant for me right now

dominicm11:08:40

I don't entirely get tests if I am honest. So I say why, and see if someone can challenge me for an alternative view on it, so I do appreciate that kind of information (and all the information you've all provided)

glenjamin11:08:06

For me, tests are about providing confidence in changes

glenjamin11:08:21

a list of expectations that should hold, that will automatically be verified

glenjamin11:08:53

for UI stuff, I ask myself what I really care about

glenjamin11:08:16

the classic example is legally mandated text in the page footer - that’s worth a unit test that fails with the slightest change

glenjamin11:08:24

colour of a button? maybe not

rickmoynihan11:08:56

dominicm: thats precisely the kind of testing we avoid

thomas14:08:45

would it be idiomatic in cljs to put the response from an cljs-ajax call in an atom for later use?

dominicm14:08:20

I'd like to know this also

thomas14:08:53

feels like I am writing a setter though….

glenjamin14:08:16

elm-style architecture is quite common afaik

glenjamin14:08:45

the api response would be stored in a portion of the global state atom and the UI reads from that

glenjamin14:08:52

depends what sort of cljs thing you’re making

thomas14:08:59

that sounds about what I was thinking about doing… response handler store received data in my global state atom. some other code will use that is and when needed

mccraigmccraig14:08:38

@thomas global-state-atom good, many independent state-atoms bad

thomas14:08:23

@mccraigmccraig: I only have a single atom with a map in it 😉

mccraigmccraig14:08:12

@thomas and if you are using reagent then you might as well use re-frame too, since that's mostly what it manages (global state, subscriptions to things derived from the state, and event-based mutations of the state)

thomas14:08:37

I am using reagent… and liking it...

thomas14:08:51

let me have a look at re-frame (again)

agile_geek14:08:00

When I start to think about that pattern I do wonder if I should look at Om.Next to allow querying over the state?

mccraigmccraig15:08:52

@agile_geek: i've not yet understood the om.next proposition - so far it seems to me like several things (state management, query-optimisation, rendering) tangled together, and that makes me a little wary

thomas15:08:46

I think that Om.Next is for very big projects… NY Times type scale 😉