Erik Assum2021-11-17T08:28:53+00:00http://slipset.github.ioErik AssumOn steamed milk2021-10-13T00:00:00+00:00http://slipset.github.io/posts/on-steamed-milk<p><img src="https://user-images.githubusercontent.com/5894926/137165284-05a9ea04-b5e4-438b-b48b-b40a8a43e85b.JPG" alt="IMG_0369" /></p>
<p>Coffee is a big part of my life. And not just any coffee, I prefer espresso based drinks with steamed milk.
So when <a href="https://twitter.com/einarwh">Einar</a> <a href="https://twitter.com/einarwh/status/1448292083647893523?s=20">challenged</a> me to write a blog post on milk in coffee, how could I possibly not do that?</p>
<p>Milk in espresso based drinks is a facinating topic. The first part of it, which I’m not even up for discussing is the type of milk. IMNSHO opinion the best milk to have in your coffe is the fattest milk. So for me, <a href="https://rorosmeieriet.no/produkter/okologisk-helmjolk/">Røros Økologisk Helmjølk</a> is the way to go. 4% fat, ecological, what more could you ever desire? Why you might ask? Simple. The fatter the milk, the easier it is to acheive the correct texture, and the fat in the milk also brings the coffee taste to life.</p>
<p>The second part is the texture, or foaminess. To me this is on a scale from a <a href="https://en.wikipedia.org/wiki/Cortado">cortado</a> where the milk is hardly frothed at all, just barely heated, and, in mhy parlance, thin. On the other end of the scale, you have the <a href="https://en.wikipedia.org/wiki/Cappuccino">cappuccino</a> where the milk is very frothed, almost to the point of foamy.</p>
<p>The third part is the amount of milk. Everything from an <a href="https://en.wikipedia.org/wiki/Caffè_macchiato">caffè macchiato</a> to a <a href="https://en.wikipedia.org/wiki/Latte_macchiato">latte macchiato</a>, one might argue that they’re basically the inverse of each other. The former is an espresso with a splash of milk, whereas the latter is a warm milk with a splash of espresso. This cup, from Starbucks in Barcelona, obviously has too much milk
<img src="https://user-images.githubusercontent.com/5894926/137164837-ae528fdd-dc10-45e8-b8c7-995a783533bc.JPG" alt="IMG_1942" /></p>
<p>So, what do I prefer? I really like the taste of the espresso, so I’m partial to less milk, and more coffee, and as such, a cortado is preferable. But I also prefer the foaminess more on the side of a cappuccino, but not so much that it doesn’t mix with the coffee. This leads to me often ordering something like “a cortado, but the milk being steamed like a cappuccino, full fat of course”. Oh, and it needs to be served in a cup, not a glass, but preferably in a bowl.
Which should look something like this:
<img src="https://user-images.githubusercontent.com/5894926/137164571-eae3424e-2029-46fe-901c-cba633685071.jpg" alt="IMG_0446" />
Note, that the leaf is not strictly neccessary, but to me, it’s only when the milk is perfectly steamed that you’re able to make them.</p>
<p>At <a href="https://www.kaffebrenneriet.no">Kaffebrenneriet</a> this would be a triple-au-lait.</p>
<p>And this is why I end up <a href="https://twitter.com/einarwh/status/1448180802550910997?s=20">discussing milk with the barrista</a>, even if there is a line behind me.</p>
The Idealcast2021-10-10T00:00:00+00:00http://slipset.github.io/posts/The-idealcast<p>Some things fit into a tweet, some things don’t. This doesn’t</p>
<p>A topic for another day could be what my hobbies are, and how I
approach them, but for the sake of this post, I’ll say that one of
them is windsurfing. Living in Oslo, Norway, which is at the end of
the Oslo fjord, it means that a bit of driving is required to get
favourable conditions. And what I tend to do when I drive is to listen
to podcasts. And it’s one of those podcasts I’d like to write about
today.</p>
<p>But there’s still a couple of things I want to mention before I dive
into this particular podcast. A peculiar thing that tends to happen
whenever I read or listen a good non-fiction book or when listening to
a podcast, is that my brain starts racing. I hear something that
relates to work, and my brain starts to connect some dots that it
hasn’t previously been able to connect. The downside to this is that I
can’t really focus on what I’m listening to anymore, the upside is
this enormous feeling of creativity and joy of having new insights,
but it’s also somewhat frustrating, because more often than not, I’m
in a situation (like driving a car) where I can’t immediately make use
of it.</p>
<p>The other thing that needs to be mentioned is that although I
desperately try to avoid getting “promoted” to anything but a
programmer, I tend to be very interested in the intersection between
programming and the rest of the business, because what the rest of the
business does has great impact on what I do as a programmer, and my
happiness as an employee. And I really want to understand what affects
my happiness.</p>
<p>One podcast in particular that is very interesting in this effect is
<a href="https://itrevolution.com/the-idealcast-podcast/">The Idealcast</a>. You
might recognize the host, Gene Kim, as the co-author of <a href="https://www.amazon.com/Phoenix-Project-DevOps-Helping-Business/dp/0988262592">The Phoenix
Project</a>
and the author of <a href="https://www.amazon.com/Unicorn-Project-Developers-Disruption-Thriving/dp/1942788762/ref=tmm_hrd_swatch_0?_encoding=UTF8&qid=1633852108&sr=8-1">The Unicorn
Project</a>,
both seminal books which I’d argue are equally valuable to developers
and business people alike.</p>
<p>There are so many of the episodes of this podcast that I could write
about, but I’ll limit myself to the <a href="https://itrevolution.com/the-idealcast-episode-23/">lastest
one</a> (at the time
of writing). In this episode <a href="https://twitter.com/scotthavens?lang=en">Scott
Havens</a> describes the work
he’s done for jet.com, Walmart, and now at Wayfair. What I find
extremely interesting about this episode is how Scott manages to
explain how he has used principles of functional programming, which I
have previously thought only were applicable to code, to solve
architectural problems, which again solves business problems. The way
Scott explains how he has leveraged the duality between code and data,
which is only possible when you deal with pure functions and how you can
use <a href="https://en.wikipedia.org/wiki/Currying">currying</a> at an
architectural level is quite mind blowing. I won’t go into detail, but
will just leave these examples here as teasers.</p>
<p>So. Do yourself a favour. The next time you’re set for a long drive,
put the Idealcast on and let your brain race. It’s quite an experience.</p>
Deploying to Clojars2021-09-26T00:00:00+00:00http://slipset.github.io/posts/deploying-to-clojars<p>As one of the maintainers of the various repos over at <a href="https://github.com/clj-commons">clj-commons</a>, it’s often on me to deploy new versions of the libraries to <a href="https://www.clojars.org">clojars</a>. This used to be a pain, as deploying libs tended to include a bunch of manual steps. Also, even though almost nobody cares, I tend to sign the artefacts, which meant (since gpg has a rather unique user experience) that I only had one computer I could do the deployment from. Also, as time has progressed, my computers don’t neccesarily have jdk-8 installed, but it’s nice to build and test the libs against that version, since it’s what Clojure runs on. So the pain-points were many, but there is also something very unhygenic about this process. It’s manual, it’s hard for other maintainers to deploy libs, and most of all, the artefacts were built on <em>my compouter</em>, in a somewhat unrepeatable process. Also, it meant that each maintainer who wanted to deploy to Clojars needed to be a member of the clj-commons clojars org, and had set up gpg for signing artefacts. Also, I tended to forget to tag releases.</p>
<h1 id="an-ideal-build-process">An ideal build process</h1>
<p>What I wanted to achieve was to remove all of my personal pain points, I wanted to make it easy for other maintainters to deploy to Clojars, and I wanted to make sure we had repeatable and transparent builds.</p>
<p>To me this would be a process that did the following:</p>
<ol>
<li>Ensure that the artefact was built with the correct jdk</li>
<li>Ensure that what was built on Circle was what was deployed to Clojars</li>
<li>Ensure that every release was tagged appropriatly</li>
<li>Ensure that every release was signed</li>
<li>Ensure that a release could be done from wherever on whatever machine</li>
</ol>
<p>Ideally, what would happen is that when you’re ready to do a release, you do <em>something</em>, and Circle takes care of the rest.</p>
<p>What I ended up with was that <em>something</em> was pushing a tag with a specific format, the format being <code class="language-plaintext highlighter-rouge">Release-.*</code></p>
<h1 id="the-implementation">The implementation</h1>
<p>First of all, I’ve only done this for leiningen projects, as most of the projects in clj-commons are build using lein.</p>
<h2 id="making-project-version-runtime-configurable">Making project-version runtime configurable</h2>
<p>So, the first thing that was needed was to ensure that we could force lein to build a specific version <em>without</em> having to make changes to the <code class="language-plaintext highlighter-rouge">project.clj</code>. Normally, one specifies the version of a project directly in the <code class="language-plaintext highlighter-rouge">project.clj</code> as so:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">defproject</span><span class="w"> </span><span class="n">manifold</span><span class="w"> </span><span class="s">"0.2.0-SNAPSHOT"</span><span class="w">
</span><span class="no">:description</span><span class="w"> </span><span class="s">"A compatibility layer for event-driven abstractions"</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>But, since this is actually code that gets run, we can do this:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">defproject</span><span class="w"> </span><span class="n">clj-commons/clj-yaml</span><span class="w"> </span><span class="p">(</span><span class="nb">or</span><span class="w"> </span><span class="p">(</span><span class="nf">System/getenv</span><span class="w"> </span><span class="s">"PROJECT_VERSION"</span><span class="p">)</span><span class="w"> </span><span class="s">"0.7.3
:description "</span><span class="n">YAML</span><span class="w"> </span><span class="n">encoding</span><span class="w"> </span><span class="nb">and</span><span class="w"> </span><span class="n">decoding</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">Clojure</span><span class="w"> </span><span class="n">using</span><span class="w"> </span><span class="n">SnakeYAML</span><span class="err">"</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>So now, we’re able to specify the version of the project by specifying the <code class="language-plaintext highlighter-rouge">PROJECT_VERSION</code> environment variable.
Once we have this in place, the rest is basically just tweaking our <a href="https://circleci.com">CircleCI</a> config to make this work</p>
<h2 id="the-circleci-setup">The CircleCI setup</h2>
<p>I need to start off with how much I dislike YAML. I <em>really, really</em> dislike it, and I’ve spent too much time trying to get my whitespace correct, but exactly not enough time to bother installing a YAML-mode for Emacs. I can’t even begin to understand why someone would come up with YAML and believe it was a good idea.</p>
<p>Anyways. CircleCI has a concept of workflows, which has jobs, and the jobs can have filters. Now, what I want to have is that we only deploy when there is a tag which matches <code class="language-plaintext highlighter-rouge">Release-.*</code>, which is done like so:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">workflows</span><span class="pi">:</span>
<span class="na">build-deploy</span><span class="pi">:</span>
<span class="na">jobs</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">build</span><span class="pi">:</span>
<span class="na">filters</span><span class="pi">:</span>
<span class="na">tags</span><span class="pi">:</span>
<span class="na">only</span><span class="pi">:</span> <span class="s">/.*/</span>
<span class="pi">-</span> <span class="na">deploy</span><span class="pi">:</span>
<span class="na">requires</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">build</span>
<span class="na">filters</span><span class="pi">:</span>
<span class="na">tags</span><span class="pi">:</span>
<span class="na">only</span><span class="pi">:</span> <span class="s">/Release-.*/</span>
<span class="na">context</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">CLOJARS_DEPLOY</span>
</code></pre></div></div>
<p>Three things to notice:</p>
<ol>
<li>I think, but could be wrong, that we need to have filters on all jobs if we have it on one job. and so for our <code class="language-plaintext highlighter-rouge">build</code> job, we have a very permissive filter</li>
<li>On the <code class="language-plaintext highlighter-rouge">deploy</code> job, we have a filter which says that it’s only to be run when we have a tag that matches our release-tag.</li>
<li>The <a href="https://circleci.com/docs/2.0/contexts/"><code class="language-plaintext highlighter-rouge">context</code></a> This is where we store the secrets we need to be able to deploy to Clojars.</li>
</ol>
<p>Now for the actual deploy-job, I won’t go through the whole <a href="https://github.com/clj-commons/clj-yaml/blob/master/.circleci/config.yml">thing</a>, but I’ll run through the most important bits. I have a <a href="https://github.com/babashka/babashka">babashka</a> script over <a href="https://github.com/clj-commons/infra/blob/main/deployment/circle-maybe-deploy.bb">here</a> which takes a tag on the form <code class="language-plaintext highlighter-rouge">Release-1.2.3</code> and simply strips it to <code class="language-plaintext highlighter-rouge">1.2.3</code> and injects that into the environment under <code class="language-plaintext highlighter-rouge">PROJECT_VERSION</code> before running a command.</p>
<p>We see this being run <a href="https://github.com/clj-commons/clj-yaml/blob/master/.circleci/config.yml#L127">here</a> with some GPG stuff removed for clarity:</p>
<pre><code class="language-YAML"> - run:
name: Deploy
command: ./circle-maybe-deploy.bb lein deploy clojars
</code></pre>
<h2 id="authentication-with-clojars">Authentication with clojars</h2>
<p>So the final thing that we need to do is to ensure that we’re authorized to deploy to Clojars, and that’s where the <code class="language-plaintext highlighter-rouge">CLOJARS_CONTEXT</code> comes in. In that context we have a <code class="language-plaintext highlighter-rouge">CLOJARS_USERNAME</code> and a <code class="language-plaintext highlighter-rouge">CLOJARS_PASSWORD</code> (amongst other things)</p>
<p><img src="https://user-images.githubusercontent.com/5894926/134803309-2a1c6280-c9b3-468b-87ee-387ade05ed9d.png" alt="Screenshot 2021-09-26 at 12 03 45" /></p>
<p>Now we need to ensure that <code class="language-plaintext highlighter-rouge">lein</code> will accept those, and we do that by adding some stuff to the <code class="language-plaintext highlighter-rouge">deploy-repositories</code> <a href="https://github.com/clj-commons/clj-yaml/blob/master/project.clj#L9">key</a>:</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w"> </span><span class="no">:deploy-repositories</span><span class="w"> </span><span class="p">[[</span><span class="s">"clojars"</span><span class="w"> </span><span class="p">{</span><span class="no">:url</span><span class="w"> </span><span class="s">"https://repo.clojars.org"</span><span class="w">
</span><span class="no">:username</span><span class="w"> </span><span class="no">:env/clojars_username</span><span class="w">
</span><span class="no">:password</span><span class="w"> </span><span class="no">:env/clojars_password</span><span class="p">}]]</span><span class="w">
</span></code></pre></div></div>
<p>In the linked code, I have <code class="language-plaintext highlighter-rouge">sign-releases true</code> but that needs to be discussed in another post.</p>
<h1 id="final-words">Final words</h1>
<p>With the above setup, anyone who is allowed to push to <code class="language-plaintext highlighter-rouge">master</code> on the project and is member of the clj-commons organization (only org-members have access to the <code class="language-plaintext highlighter-rouge">CONTEXT</code>) is also allowed to deploy a new version to clojars. The artefact will be built on CircleCI, and we have full transparency of who did it, when they did it and on what commit it was done. Further more, we ensure that we always have a release-commit, which is important for some people, especially maintainers of linux-distros which use the <a href="https://github.com/clj-commons/clj-yaml/releases">tar-balls</a> that Github create automagically for us.</p>
Dependency injection, perhaps? Part 32021-09-11T00:00:00+00:00http://slipset.github.io/posts/all-your-base<p>Ardoq is a multi-tenant SaaS application. This means that we have, well, multiple tenants (organizations in Ardoq parlance) to which users are connected. The important bit here is that we need to guarantee data isolation between our organizations. This has been solved by having in MongoDb terms, a <em>database</em> pr organization. So when we get a request from a browser, we figure out which user this request belongs to, what her organization is, and then we make the corresponding database available to the code that handles the request.</p>
<p>So, in this series on dependency injection, the interesting question how do we make the database available to the code that handles the request.</p>
<p>When I arrived at Ardoq, the communication with the database was organized around the <a href="https://en.wikipedia.org/wiki/Data_access_object">DAO</a> pattern. The dao was implemented as such:</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">ns</span><span class="w"> </span><span class="n">ardoq.persistence.foo-store</span><span class="w"> </span><span class="n">...</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">find-by-id</span><span class="w"> </span><span class="p">[</span><span class="n">system</span><span class="w"> </span><span class="n">id</span><span class="p">]</span><span class="w">
</span><span class="n">...</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>Each entity in the system had its corresponding ns, and its corresponding Component. We will get back to why this was a Component when we look at how mutating the database was being done.</p>
<p>Which to some extent is great, because, say you wanted to swap database, you only need to change your DAO layer, at least in theory. But that’s a digression we might get back to in some other post.</p>
<p>It’s also not so great because this creates a proliferation of Components which serve no other purpose than to convey the organization database. And it makes it harder to reason about the code, because, in order to understand what <code class="language-plaintext highlighter-rouge">(find-by-id system id)</code> is <em>capable</em> of doing, you need to read the code of <code class="language-plaintext highlighter-rouge">find-by-id</code></p>
<p>If we examine closer what these dao-functions looked like, they were all quite similar (focussing on query here):</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">find-by-id</span><span class="w"> </span><span class="p">[</span><span class="n">system</span><span class="w"> </span><span class="n">id</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nf">mc/find-one-as-map</span><span class="w"> </span><span class="p">(</span><span class="no">:org-db</span><span class="w"> </span><span class="n">system</span><span class="p">)</span><span class="w"> </span><span class="s">"foo"</span><span class="w"> </span><span class="p">{</span><span class="no">:_id</span><span class="w"> </span><span class="p">(</span><span class="nf">ObjectId.</span><span class="w"> </span><span class="n">id</span><span class="p">)}))</span><span class="w">
</span><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">find-by-name</span><span class="w"> </span><span class="p">[</span><span class="n">system</span><span class="w"> </span><span class="nb">name</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nf">mc/find-maps</span><span class="w"> </span><span class="p">(</span><span class="no">:org-db</span><span class="w"> </span><span class="n">system</span><span class="p">)</span><span class="w"> </span><span class="s">"foo"</span><span class="w"> </span><span class="p">{</span><span class="no">:name</span><span class="w"> </span><span class="s">"name"</span><span class="p">}))</span><span class="w">
</span></code></pre></div></div>
<p>I’m digression (again), but as the observant reader will already have seen, there are two interesting bits that vary between these two fns</p>
<ol>
<li>How many things you expect to get back (one vs many)</li>
<li>The query</li>
</ol>
<p>So if you can handle the isolation of the database impl in other ways, you can separate these things:</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">by-id</span><span class="w"> </span><span class="p">[</span><span class="n">id</span><span class="p">]</span><span class="w">
</span><span class="p">{</span><span class="no">:_id</span><span class="w"> </span><span class="p">(</span><span class="nf">ObjectId.</span><span class="w"> </span><span class="n">id</span><span class="p">)})</span><span class="w">
</span><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">by-name</span><span class="w"> </span><span class="p">[</span><span class="nb">name</span><span class="p">]</span><span class="w">
</span><span class="p">{</span><span class="no">:name</span><span class="w"> </span><span class="nb">name</span><span class="p">})</span><span class="w">
</span></code></pre></div></div>
<p>Now, there are several upsides to doing it this way</p>
<ol>
<li>Your queries, which is the stuff that tends to grow in complexity, become pure functions which return data, so they’re actually unit-testable.</li>
<li>You can now <em>combine</em> queries, in our case with <code class="language-plaintext highlighter-rouge">merge</code>:
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">by-id-and-name</span><span class="w"> </span><span class="p">[</span><span class="n">id</span><span class="w"> </span><span class="nb">name</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nb">merge</span><span class="w"> </span><span class="p">(</span><span class="nf">by-id</span><span class="w"> </span><span class="n">id</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nf">by-name</span><span class="w"> </span><span class="nb">name</span><span class="p">)))</span><span class="w">
</span></code></pre></div> </div>
</li>
<li>You can reduce the number of side-effecting datababase-hiding query-functions in your code base to two:
<ol>
<li><code class="language-plaintext highlighter-rouge">query-one!</code></li>
<li><code class="language-plaintext highlighter-rouge">query!</code></li>
</ol>
<p>while still hiding the implementation details of your chosen database.</p>
</li>
</ol>
<p>But, this series is not about hiding implementation details about your database, it’s about how to reduce Components in your system.</p>
<p>So, no matter how you choose to do this, you need to at some point give the function which interacts with the database a handle to that database. Previously we did it by <code class="language-plaintext highlighter-rouge">assoc</code>ing the org-database to the <code class="language-plaintext highlighter-rouge">system</code>, what are we doing now?</p>
<p>The insight, which of course is not very novel, is that every request runs in some sort of <em>context</em>. In our case, it’s in the context of a user and an org, so we have this simple function which is <code class="language-plaintext highlighter-rouge">req->context</code> which takes a request and returns us a context containing the org-db and the running user.</p>
<p>Now, <em>context</em> being such a <a href="https://en.wikipedia.org/wiki/Weasel_word">weasel word</a> it means all and nothing, and is suceptible to grow over time to something at least as unweildly as the System itself. So, this is a constant concern we have, is that just because it’s convenient, we try to limit the amount of new stuff we stick in the context. We’ve been fairly successful at that.</p>
<p>So what does our code look like now?</p>
<p>For querying functions our code follows this pattern:</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">repo/query!</span><span class="w"> </span><span class="n">foo-repo/config</span><span class="w"> </span><span class="n">ctx</span><span class="w"> </span><span class="p">(</span><span class="nf">foo-repo/by-name</span><span class="w"> </span><span class="s">"a name"</span><span class="p">))</span><span class="w">
</span></code></pre></div></div>
<p>the <code class="language-plaintext highlighter-rouge">foo-repo/config</code> holds some data which are important for us, such as collection-names (table-names in sql), the <code class="language-plaintext highlighter-rouge">ctx</code> holds the handle to the organization-db and the running user, and we’ve chosen to organize the queries in ns’s pr entity-type, with some common queries like <code class="language-plaintext highlighter-rouge">by-id</code> and <code class="language-plaintext highlighter-rouge">by-ids</code> in a common ns.</p>
<p>So, what does this give us?</p>
<ol>
<li>I know at a glance that a fn that only calls <code class="language-plaintext highlighter-rouge">repo/query!</code> does not mutate data, nor does it send out emails or launch missiles, whereas a function which called <code class="language-plaintext highlighter-rouge">(foo-store/find-by-name! system "a name")</code> could do whatever, I’d have to read the source of <code class="language-plaintext highlighter-rouge">find-by-id</code> to figure out exactly what it does. In most cases it would do what you’d expect, in rare cases, it might launch missiles.</li>
<li>By convention I know that any fn that only takes a <code class="language-plaintext highlighter-rouge">ctx</code> and some other <em>non scary</em> parameters, only reads the database:
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">some-ns/do-whatever</span><span class="w"> </span><span class="n">ctx</span><span class="w"> </span><span class="n">arg1</span><span class="w"> </span><span class="n">arg2</span><span class="p">)</span><span class="w">
</span></code></pre></div> </div>
<p>is a read only fn and doesn’t perform other sideffects than reading from the database</p>
</li>
<li>We still have isolated the implementation detail that is our database vendor.</li>
</ol>
<p>What has not been mentioned here is how we mutate the database. I guess that will be the next post.</p>
Dependency injection, perhaps? Part 22021-08-27T00:00:00+00:00http://slipset.github.io/posts/config<p>In the <a href="https://slipset.github.io/posts/dependency-injection-perhaps">previous</a> post in this series, I tried to outline some of the problems I see when using Component based libs in Clojure. In this post, I’ll look at a couple of problematic areas I discovered in our codebase related to how we do configuration in conjunction with Component. In this post I’ll use external config to mean configuration which is provided from the running environment, and internal config to mean configuration which is like global constants and which are not changed between environments.</p>
<p>It is <a href="https://12factor.net/config">generally accepted</a> that externalizing configuration is a Good Thing(TM). And I’m not going to argue against that, but I will like to add that the more configurable an app is, the harder it is to work with as a dev, since you don’t necessarily know what value a certain thing will have during runtime. For some values, like passwords, that’s great. For other values, not so great.</p>
<p>At Ardoq, we’ve used a library for handling our “configuration”, <a href="https://github.com/unrelentingtech/clj-configurator">clj-configurator</a>. This lets you have a map of default configuration, which you then pass to the library which then, according to rules, goes into the environment to look for values to overrride the default values. This is almost all good. Apart from the fact that now suddenly, your whole config, ie both your internal config (stuff that is basically just global variables) and your external config (stuff that should be configured from the outside) is configurable from the outside, and you need to mentally keep track (or read your infrastructure as code code to figure out what are constants, and are things that are in fact configurable from the outside.</p>
<p>Another question one might ask oneself regarding the internal config, ie values which are constants and are not injected from the runtime environment, is <em>where</em> those values should be stored. It’s tempting to stick this in a config-like map, but IMO this is not really a great solution. Consider the two fns:</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">do-something</span><span class="w"> </span><span class="p">[</span><span class="n">config</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="n">args</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">let</span><span class="w"> </span><span class="p">[</span><span class="n">global-value</span><span class="w"> </span><span class="p">(</span><span class="nf">get-in</span><span class="w"> </span><span class="n">config</span><span class="w"> </span><span class="p">[</span><span class="no">:foo</span><span class="w"> </span><span class="no">:bar</span><span class="w"> </span><span class="no">:baz</span><span class="p">])]</span><span class="w">
</span><span class="p">(</span><span class="nf">whatever</span><span class="w"> </span><span class="n">global-value</span><span class="w"> </span><span class="n">args</span><span class="p">)))</span><span class="w">
</span><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">do-something</span><span class="w"> </span><span class="p">[</span><span class="n">some-value</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="n">args</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nf">whatever</span><span class="w"> </span><span class="n">some-value</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="n">args</span><span class="p">))</span><span class="w">
</span></code></pre></div></div>
<p>The first <code class="language-plaintext highlighter-rouge">do-something</code> needs to have a (potentially) nested map passed as the first parameter, whereas the second just receives some value. In the second case, if <code class="language-plaintext highlighter-rouge">some-value</code> is a true constant, you could even omit the parameter all together and reference a var directly from inside the fn. Beware, there are trade-offs here.</p>
<h2 id="should-we-use-components-to-hold-internal-config">Should we use Components to hold internal config?</h2>
<p>Again, at Ardoq, we’ve used our Components for also holding config, no matter if that config is external or internal. So typically, you’d have something like:</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">defrecord</span><span class="w"> </span><span class="n">MyService</span><span class="w"> </span><span class="p">[</span><span class="n">config</span><span class="p">])</span><span class="w">
</span><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">do-something</span><span class="w"> </span><span class="p">[{</span><span class="no">:keys</span><span class="w"> </span><span class="p">[</span><span class="n">config</span><span class="p">]}</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="n">args</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">let</span><span class="w"> </span><span class="p">[</span><span class="n">some-value</span><span class="w"> </span><span class="p">(</span><span class="nf">get-in</span><span class="w"> </span><span class="n">config</span><span class="w"> </span><span class="n">some-path</span><span class="p">)]</span><span class="w">
</span><span class="n">...</span><span class="p">))</span><span class="w">
</span></code></pre></div></div>
<p>and you’d call a fn in this way:</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">do-something</span><span class="w"> </span><span class="n">my-service</span><span class="w"> </span><span class="nb">some</span><span class="w"> </span><span class="n">other</span><span class="w"> </span><span class="n">params</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>Somewhat nice, but it’s not really great from a maintenance point of view, especially if the value you’re pulling from the config is an internal configuration. The reason for this is that in our case, you really have to do quite a bit of digging to understand what the value of <code class="language-plaintext highlighter-rouge">some-value</code> is. Is it internal or is it external, does it vary between environments, what are the potential values etc.</p>
<p>I’d argue that iff this is an internal configuration, you’d be better off with something like this:</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">my-service-config</span><span class="w"> </span><span class="p">{</span><span class="no">:foo</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="no">:bar</span><span class="w"> </span><span class="mi">2</span><span class="p">})</span><span class="w">
</span><span class="p">(</span><span class="nf">do-something</span><span class="w"> </span><span class="n">my-service-config</span><span class="w"> </span><span class="nb">some</span><span class="w"> </span><span class="n">other</span><span class="w"> </span><span class="n">params</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>This way, it’s much easier to reason about the code, since you don’t have to run around chasing what the runtime values really are.</p>
<h2 id="reloadable-config">Reloadable config</h2>
<p>An argument to keep (external) config in the Components is that this makes for reloadable config, ie you can restart your System, and you can inject new config into your running app. Back in the day when we deployed our apps once every quarter, this might have made sense, but today, where many of us deploy several times a day with zero downtime, it doesn’t really makes sense to introduce extra complexity to avoid restarting/redeploying a new version.</p>
<h2 id="a-parting-example">A parting example</h2>
<p>We have some code to encrypt and sign stuff. This is dependent on our private key, which is part of our external configuration. Which makes sense. The functionality was implemented as a Component:</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">defrecord</span><span class="w"> </span><span class="n">CryptoService</span><span class="w"> </span><span class="p">[</span><span class="n">rsa-private-key</span><span class="p">])</span><span class="w">
</span><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">encrypt</span><span class="w"> </span><span class="p">[</span><span class="n">crypto-service</span><span class="w"> </span><span class="n">s</span><span class="p">]</span><span class="w">
</span><span class="n">...</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>So now, in order to encrypt something, you’d need a <code class="language-plaintext highlighter-rouge">crypto-service</code> which is something you’d get from your System:</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">crypto-service/encrypt</span><span class="w"> </span><span class="p">(</span><span class="no">:crypto-service</span><span class="w"> </span><span class="o">@</span><span class="n">system</span><span class="p">)</span><span class="w"> </span><span class="s">"sikr1t"</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>In a recent rewrite, I changed this into the following:</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">rsa-private-key</span><span class="w"> </span><span class="p">[</span><span class="n">config</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="no">:rsa-private-key</span><span class="w"> </span><span class="n">config</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">encrypt</span><span class="w"> </span><span class="p">[</span><span class="n">rsa-private-key</span><span class="w"> </span><span class="n">s</span><span class="p">]</span><span class="w">
</span><span class="n">...</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>so you’re able to encrypt something without the System, you only need a private key, and we’ve added a way to obtain that key if you happen to have a config, but you’re still able to invoke this fn even if you don’t have a config. The bigger upside to this is that <code class="language-plaintext highlighter-rouge">crypto-service</code> no longer need to be a Component, and our System has one less Component in it, and as such, has become a bit less complicated.</p>
Dependency injection, perhaps? Part 12021-08-20T00:00:00+00:00http://slipset.github.io/posts/dependency-injection-perhaps<p>This is, what I hope, the first of a series of blog posts where I explore the design of the <a href="https://www.ardoq.com">Ardoq</a> in terms of its use of <a href="https://github.com/stuartsierra/component">Stuart Sierras Component System</a>. It’s important to me to stress that this series is not a critique of Stuarts fine library, nor is it going to propose some alternative, as there are several, like <a href="https://github.com/tolitius/mount">Mount</a> and <a href="https://github.com/weavejester/integrant">Integrant</a>. It is simply a series where I explore how our codebase has evolved over time, and where I might see it going.</p>
<h1 id="what-is-component">What is Component</h1>
<p>From the github repo, we can read that</p>
<blockquote>
<p>‘Component’ is a tiny Clojure framework for managing the lifecycle and dependencies of software components which have runtime state.</p>
</blockquote>
<p>To me, the keywords here are lifecycle, dependencies, and runtime state. So a Component is a thing that has runtime state, an example of this would be a database-connection, it has a need for lifecycle managament, ie it needs to be started (eg open a connection to the database), and it needs to be stopped (eg close the connection to the database. It might also be dependent on other services being started, so Component makes sure your components are started in the correct order, and also stopped in the correct order. All this is good.</p>
<h1 id="component-at-ardoq">Component at Ardoq</h1>
<p>So when I started working at Ardoq, our codebase comprised 43 such components in a codebase of some 20KLOC. So in a codebase of 20KLOC, we had 43 components which were carrying runtime state, were in need of lifecycle management, and had intricate dependency management? Today, we’re at 116 Components at 58KLOC. One could argue that that’s a bit too much.</p>
<h1 id="another-use-of-component">Another use of Component</h1>
<p>There is another problem that could be solved with Component, and I think this is a clue to why we have so many of them. It’s hinted at above, but let’s spell it out. It’s about dependencies, and more specifically, about hiding implementation details and building bigger building blocs. So, let’s look at some code:</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">handle-some-request</span><span class="w"> </span><span class="p">[{</span><span class="no">:keys</span><span class="w"> </span><span class="p">[</span><span class="n">system</span><span class="w"> </span><span class="n">params</span><span class="p">]</span><span class="w"> </span><span class="no">:as</span><span class="w"> </span><span class="n">req</span><span class="p">}]</span><span class="w">
</span><span class="p">(</span><span class="nf">some-service/do-whatever</span><span class="w"> </span><span class="n">system</span><span class="w"> </span><span class="n">params</span><span class="p">))</span><span class="w">
</span></code></pre></div></div>
<p>The above code is great, and teribble, both because we don’t know what sideffects <code class="language-plaintext highlighter-rouge">some-service/do-whatever</code> is going to execute. It’s good, because we don’t have to enumerate all (and thus know, and remember to add a new one when <code class="language-plaintext highlighter-rouge">do-whatever</code> needs to do more) of the services <code class="language-plaintext highlighter-rouge">do-whatever</code> need to have available to do it’s job. One could even imagine that <code class="language-plaintext highlighter-rouge">do-whatever</code> called into other services which then called into yet other services. It’s also terrible, because <code class="language-plaintext highlighter-rouge">do-whatever</code> can do everything our system has to offer, so it’s hard to reason about our code. Would the above code send emails? Possibly. Launch missiles? Also possible.</p>
<p>Basically what this offers us is some sort of encapsulation. When Ardoq was initially developed, this was more or less how the code looked, but at the time of my arrival, the code base had changed into this pattern:</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">handle-some-request</span><span class="w"> </span><span class="p">[{</span><span class="no">:keys</span><span class="w"> </span><span class="p">[</span><span class="n">system</span><span class="w"> </span><span class="n">params</span><span class="p">]</span><span class="w"> </span><span class="no">:as</span><span class="w"> </span><span class="n">req</span><span class="p">}]</span><span class="w">
</span><span class="p">(</span><span class="nf">some-service/do-whatever</span><span class="w"> </span><span class="p">(</span><span class="no">:some-service</span><span class="w"> </span><span class="n">system</span><span class="p">)</span><span class="w"> </span><span class="n">params</span><span class="p">))</span><span class="w">
</span></code></pre></div></div>
<p>Which meant that <code class="language-plaintext highlighter-rouge">do-whatever</code> only had access to a subset of the system, so it would be easier to reason about what <code class="language-plaintext highlighter-rouge">do-whatever</code> was doing, or at least what it was not capable of doing. In a way this is nice, because, we now have restricted what <code class="language-plaintext highlighter-rouge">do-whatever</code> can do, while we still don’t have to know or care about (at this call site) what it or its dependencies need to have available to them in order to to their job. Encapsulation is achieved.</p>
<h1 id="the-problem">The problem</h1>
<p>The problem with this approach, however, is that very few of our (at this time of writing 116 Components) actually hold any state of their own. They only hold their dependencies (which I guess you could argue is state). So rather than using Component as a state management tool, we use it as an encapsulalation tool, and I think that is problematic.</p>
<h1 id="up-next">Up next</h1>
<p>In the next post in this series, I’ll make a small digression, and write about the use of configurations in a web app, ie, the difference between config and constants.</p>
On oauth and design2020-12-06T00:00:00+00:00http://slipset.github.io/posts/On-oauth-and-design<p>When you write applications, and in my situation, multitenant SaaS applications, both authentication and authorization are important parts of the system.
Authentication, which will carry the story in this blog post, is about establishing who someone is, authorization is about what that person is allowed to do.
We’ll leave authorization behind for now, and focus on authentication in a multitenant SaaS world.</p>
<p>On the web you have quite a few protocols for doing authentication, for this blog post, I’ll focus on <a href="https://oauth.net/2/">OAuth</a>. It’s important to note
that I’m not at all an expert on this subject, so expect imprecision here.</p>
<p>Because, what I really want to talk about is software design. I’ve been through a rather long and involved refactor of our oauth code, and I would like to share
my findings, because they highlight some things that are easy to do when designing software, but which are not always so smart.</p>
<p>Back to OAuth. The protocol is basically that when a user wants to log in to your application, you redirect the users browser over to an identity provider (IDP), such as
google, facebook, or github. The IDP handles the username/password challenge, and when the user has identified itself over at the IDP, the IDP instructs the users browser to
call you back with a token, which your application then can use to call the IDP to get more information about the user. This is called an OAuth workflow.</p>
<p>So, as an OO programmer, you know what to do now:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="kd">public</span> <span class="kd">interface</span> <span class="nc">OauthWorkflow</span> <span class="o">{</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Yay, without really understanding anything, we’ve created our first abstraction. Now, you could argue that this doesn’t do anything, and that’s correct.
I guess we’d need to be able to <code class="language-plaintext highlighter-rouge">run</code> the workflow, and to be skipping ahead, I happen to know that we need a <code class="language-plaintext highlighter-rouge">HttpRequest</code> to run the workflow:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">interface</span> <span class="nc">OauthWorkflow</span> <span class="o">{</span>
<span class="nc">OAuthResult</span> <span class="nf">run</span><span class="o">(</span><span class="nc">HttpServletRequest</span> <span class="n">request</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>
<p>So, let’s concretize this for a moment, let’s imagine we have an IDP, Foo, which we want to use as our IDP:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">FooIDP</span> <span class="kd">implements</span> <span class="nc">OauthWorkflow</span> <span class="o">{</span>
<span class="nc">OAuthResult</span> <span class="nf">run</span><span class="o">(</span><span class="nc">HttpServletRequest</span> <span class="n">request</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// user wants to log in, we redirect to the IDP for auth</span>
<span class="k">if</span> <span class="o">(</span><span class="n">request</span><span class="o">.</span><span class="na">getUri</span><span class="o">().</span><span class="na">equals</span><span class="o">(</span><span class="s">"/api/oauth/foo/login"</span><span class="o">))</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nf">RedirectToFooIDPForAuthentication</span><span class="o">();</span> <span class="c1">// this obviously implements OAuthResult and redirects the browser to the IDP for auth</span>
<span class="o">}</span>
<span class="c1">// user has successfully authenticated with the IDP, the IDP calls us back with a token</span>
<span class="k">if</span> <span class="o">(</span><span class="n">request</span><span class="o">.</span><span class="na">getUri</span><span class="o">().</span><span class="na">equals</span><span class="o">(</span><span class="s">"/api/oauth/foo/callback"</span><span class="o">))</span> <span class="o">{</span>
<span class="nc">UserInfo</span> <span class="n">userInfo</span> <span class="o">=</span> <span class="n">getUserInfo</span><span class="o">(</span><span class="n">request</span><span class="o">.</span><span class="na">getParameter</span><span class="o">(</span><span class="s">"code"</span><span class="o">));</span> <span class="c1">// we'll leave this as an excercise for the reader</span>
<span class="k">return</span> <span class="k">new</span> <span class="nf">Authenticated</span><span class="o">(</span><span class="n">userInfo</span><span class="o">);</span> <span class="c1">// Authenticated also implements OAuthResult</span>
<span class="o">}</span>
<span class="k">return</span> <span class="kc">null</span><span class="o">;</span> <span class="c1">// this request was not for us.</span>
<span class="o">}</span>
</code></pre></div></div>
<p>There is also some config that needs to be handled, which in <code class="language-plaintext highlighter-rouge">FooIDP</code> can be hard coded, but, if we pass it in as a config object, we can make a totally
generic IDP implementation:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">GenericIDP</span> <span class="kd">implements</span> <span class="nc">OauthWorkflow</span> <span class="o">{</span>
<span class="kd">public</span> <span class="nf">GenericIDP</span><span class="o">(</span><span class="nc">Config</span> <span class="n">config</span><span class="o">)</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">config</span> <span class="o">=</span> <span class="n">config</span><span class="o">;</span>
<span class="o">}</span>
<span class="nc">OAuthResult</span> <span class="nf">run</span><span class="o">(</span><span class="nc">HttpServletRequest</span> <span class="n">request</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// user wants to log in, we redirect to the IDP for auth</span>
<span class="k">if</span> <span class="o">(</span><span class="n">request</span><span class="o">.</span><span class="na">getUri</span><span class="o">().</span><span class="na">equals</span><span class="o">(</span><span class="n">config</span><span class="o">.</span><span class="na">getLoginURL</span><span class="o">()))</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nf">RedirectToGenericIDPForAuthentication</span><span class="o">(</span><span class="n">config</span><span class="o">);</span> <span class="c1">// this obviously implements OAuthResult and redirects the browser to the IDP for auth</span>
<span class="o">}</span>
<span class="c1">// user has successfully authenticated with the IDP, the IDP calls us back with a token</span>
<span class="k">if</span> <span class="o">(</span><span class="n">request</span><span class="o">.</span><span class="na">getUri</span><span class="o">().</span><span class="na">equals</span><span class="o">(</span><span class="n">config</span><span class="o">.</span><span class="na">getCallbackURL</span><span class="o">()))</span> <span class="o">{</span>
<span class="nc">UserInfo</span> <span class="n">userInfo</span> <span class="o">=</span> <span class="n">getUserInfo</span><span class="o">(</span><span class="n">config</span><span class="o">,</span> <span class="n">request</span><span class="o">.</span><span class="na">getParameter</span><span class="o">(</span><span class="s">"code"</span><span class="o">));</span> <span class="c1">// we'll leave this as an excercise for the reader</span>
<span class="k">return</span> <span class="k">new</span> <span class="nf">Authenticated</span><span class="o">(</span><span class="n">userInfo</span><span class="o">);</span> <span class="c1">// Authenticated also implements OAuthResult</span>
<span class="o">}</span>
<span class="k">return</span> <span class="kc">null</span><span class="o">;</span> <span class="c1">// this request was not for us.</span>
<span class="o">}</span>
</code></pre></div></div>
<p>And this looks really nice, implemented in Clojure, it would be something like:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">workflow</span><span class="w"> </span><span class="p">[</span><span class="n">config</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="p">[</span><span class="n">request</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">cond</span><span class="w"> </span><span class="p">(</span><span class="nb">=</span><span class="w"> </span><span class="p">(</span><span class="no">:uri</span><span class="w"> </span><span class="n">request</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">:login-url</span><span class="w"> </span><span class="n">config</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nf">redirect-to-idp</span><span class="w"> </span><span class="n">config</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nb">=</span><span class="w"> </span><span class="p">(</span><span class="no">:uri</span><span class="w"> </span><span class="n">request</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">:call-back-url</span><span class="w"> </span><span class="n">config</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nf">authenticated-user</span><span class="w"> </span><span class="p">(</span><span class="nf">user-info</span><span class="w"> </span><span class="n">config</span><span class="w"> </span><span class="p">(</span><span class="nf">get-in</span><span class="w"> </span><span class="n">request</span><span class="w"> </span><span class="p">[</span><span class="no">:params</span><span class="w"> </span><span class="no">:code</span><span class="p">])))</span><span class="w">
</span><span class="no">:else</span><span class="w">
</span><span class="n">nil</span><span class="p">)))</span><span class="w">
</span></code></pre></div></div>
<p>So, now that we’ve set the stage, let’s see what happens when we bring this into the real world, where we live.
Of course, there isn’t only one IDP, and even though OAuth is a standard, each IDP might interpret the standard in different ways.
One way the IDPs tend to differ is how we get information about the user. Some send all the information we need through the JWT-token, others require us to call
them back at a given url. So how do we shoehorn this into our neat little workflow abstraction? We need to do some polymorphism.
Clojure has several mechanisms for polymorphism. The simplest one, is the one that exists in all programming languages, basically a switch statement, like <code class="language-plaintext highlighter-rouge">cond</code> or <code class="language-plaintext highlighter-rouge">case</code></p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">user-info</span><span class="w"> </span><span class="p">[</span><span class="n">config</span><span class="w"> </span><span class="n">jwt-token</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nf">case</span><span class="w"> </span><span class="p">(</span><span class="no">:user-lookup-type</span><span class="w"> </span><span class="n">config</span><span class="p">)</span><span class="w">
</span><span class="no">:id-token-payload</span><span class="w"> </span><span class="p">(</span><span class="nf">parse-id-token</span><span class="w"> </span><span class="n">jwt-token</span><span class="p">)</span><span class="w">
</span><span class="no">:callback-url</span><span class="w"> </span><span class="p">(</span><span class="nf">call-back</span><span class="w"> </span><span class="n">config</span><span class="w"> </span><span class="n">jwt-token</span><span class="p">)))</span><span class="w">
</span></code></pre></div></div>
<p>You can also do this with protocols and multimethods, which are nice and handy tools if you know them. But as an inexperienced Clojure programmer, you might just reach for
a way which mimicks what you’d do in object-oriented code, you can pass functions in the config map!</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">foo-idp-config</span><span class="w"> </span><span class="p">{</span><span class="n">...</span><span class="w">
</span><span class="no">:user-lookup-fn</span><span class="w"> </span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="p">[</span><span class="n">config</span><span class="w"> </span><span class="n">jwt-token</span><span class="p">]</span><span class="w"> </span><span class="n">...</span><span class="p">)</span><span class="w">
</span><span class="n">...</span><span class="p">})</span><span class="w">
</span></code></pre></div></div>
<p>and now, user-lookup can be done like this</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">user-lookup</span><span class="w"> </span><span class="p">[</span><span class="n">config</span><span class="w"> </span><span class="n">jwt-token</span><span class="p">]</span><span class="w">
</span><span class="p">((</span><span class="no">:user-lookup-fn</span><span class="w"> </span><span class="n">config</span><span class="p">)</span><span class="w"> </span><span class="n">config</span><span class="w"> </span><span class="n">jwt-token</span><span class="p">))</span><span class="w">
</span></code></pre></div></div>
<p>Now, over time, you might find that it’s not just the <code class="language-plaintext highlighter-rouge">user-lookup</code> that varies between IDPs, but a host of other things as well, so basically you end up with something like:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">make-config</span><span class="w"> </span><span class="p">[</span><span class="n">initial-config</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nb">merge</span><span class="w"> </span><span class="n">initial-config</span><span class="w">
</span><span class="p">{</span><span class="no">:user-lookup-fn</span><span class="w"> </span><span class="n">...</span><span class="w">
</span><span class="no">:authorization-url-fn</span><span class="w"> </span><span class="n">...</span><span class="w">
</span><span class="no">:token-url-fn</span><span class="w"> </span><span class="n">...</span><span class="p">})</span><span class="w">
</span></code></pre></div></div>
<p>So suddenly, your code is littered with stuff like:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w"> </span><span class="p">((</span><span class="no">:some-key</span><span class="w"> </span><span class="n">config</span><span class="p">)</span><span class="w"> </span><span class="n">param1</span><span class="w"> </span><span class="n">param2</span><span class="w"> </span><span class="n">param3</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>And you have to remember which keys exists and which parameters that fn expects. Trust me, it becomes nasty quite fast. But the upside is that you can write code like:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">run-workflows</span><span class="w"> </span><span class="p">[(</span><span class="nf">workflow</span><span class="w"> </span><span class="p">(</span><span class="nf">make-config</span><span class="w"> </span><span class="n">github-config</span><span class="p">))</span><span class="w"> </span><span class="p">(</span><span class="nf">workflow</span><span class="w"> </span><span class="p">(</span><span class="nf">make-config</span><span class="w"> </span><span class="n">google-config</span><span class="p">))</span><span class="w"> </span><span class="p">(</span><span class="nf">workflow</span><span class="w"> </span><span class="p">(</span><span class="nf">make-config</span><span class="w"> </span><span class="n">okta-config</span><span class="p">))]</span><span class="w">
</span></code></pre></div></div>
<p>But the crux here is that, you don’t really need the polymorphism, because, you know when you create the workflow what exactly what kind of behaviour you’ll need from the workflow
So the above code should look like:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">run-workflows</span><span class="w"> </span><span class="p">[(</span><span class="nf">github-workflow</span><span class="w"> </span><span class="n">github-config</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nf">google-workflow</span><span class="w"> </span><span class="n">google-config</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nf">okta-workflow</span><span class="w"> </span><span class="n">octa-config</span><span class="p">)])</span><span class="w">
</span></code></pre></div></div>
<p>And, if you’ve broken up your code into small composable pieces, you’ll quickly see that the code duplication is not a problem, and that it’s so much easier to read the code:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">github-workflow</span><span class="w"> </span><span class="p">[</span><span class="n">config</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="p">[</span><span class="n">request</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">cond</span><span class="w"> </span><span class="p">(</span><span class="nb">=</span><span class="w"> </span><span class="p">(</span><span class="no">:uri</span><span class="w"> </span><span class="n">request</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">:login-url</span><span class="w"> </span><span class="n">config</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nf">redirect-to-idp</span><span class="w"> </span><span class="n">config</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nb">=</span><span class="w"> </span><span class="p">(</span><span class="no">:uri</span><span class="w"> </span><span class="n">request</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">:call-back-url</span><span class="w"> </span><span class="n">config</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nf">authenticated-user</span><span class="w"> </span><span class="p">(</span><span class="nf">user-from-id-token</span><span class="w"> </span><span class="n">config</span><span class="w"> </span><span class="p">(</span><span class="nf">get-in</span><span class="w"> </span><span class="n">request</span><span class="w"> </span><span class="p">[</span><span class="no">:params</span><span class="w"> </span><span class="no">:code</span><span class="p">])))</span><span class="w">
</span><span class="no">:else</span><span class="w">
</span><span class="n">nil</span><span class="p">)))</span><span class="w">
</span></code></pre></div></div>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">google-workflow</span><span class="w"> </span><span class="p">[</span><span class="n">config</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="p">[</span><span class="n">request</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">cond</span><span class="w"> </span><span class="p">(</span><span class="nb">=</span><span class="w"> </span><span class="p">(</span><span class="no">:uri</span><span class="w"> </span><span class="n">request</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">:login-url</span><span class="w"> </span><span class="n">config</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nf">redirect-to-idp</span><span class="w"> </span><span class="n">config</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nb">=</span><span class="w"> </span><span class="p">(</span><span class="no">:uri</span><span class="w"> </span><span class="n">request</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">:call-back-url</span><span class="w"> </span><span class="n">config</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nf">authenticated-user</span><span class="w"> </span><span class="p">(</span><span class="nf">user-from-callback</span><span class="w"> </span><span class="n">config</span><span class="w"> </span><span class="p">(</span><span class="nf">get-in</span><span class="w"> </span><span class="n">request</span><span class="w"> </span><span class="p">[</span><span class="no">:params</span><span class="w"> </span><span class="no">:code</span><span class="p">])))</span><span class="w">
</span><span class="no">:else</span><span class="w">
</span><span class="n">nil</span><span class="p">)))</span><span class="w">
</span></code></pre></div></div>
<p>In our case, there was a bit more functionality that was different between our supported IDPs, but the main point is still valid I think:
When the “concretization” of an operation is known at compiletime, don’t use polymorphism, just make sure you have small enough building blocks so you can easily compose
the functionality you need.</p>
On Design Choices2020-05-17T00:00:00+00:00http://slipset.github.io/posts/On-design-choices<p>In my <a href="https://slipset.github.io/posts/the-problem-i-dont-have">previous</a> post I contrasted two different ways of approaching
JSON (de)serialization. In <a href="https://purelyfunctional.tv/issues/purelyfunctional-tv-newsletter-364-tip-seek-the-model-and-enshrine-it-in-code/">this</a> post <a href="https://twitter.com/ericnormand">Eric Normand</a>
discusses different ways of doing CSV parsers. Basically, these are two posts are about the same thing. It’s about where you draw the line.
I think that in <a href="https://twitter.com/einarwh">Einars</a> words, you’d say that it’s about drawing the line between the bounded and the unbounded problem.</p>
<p>So listening to David Nolen on the <a href="https://soundcloud.com/defn-771544745/60-4th-anniversary-episode-return-of-david-nolen-aka-swannodette">Defn podcast</a>, I think
David puts it rather nicely. You want to design your libraries in such a way that they can be done. You do this by enforcing as few
assumptions as possible on the downstream consumer.</p>
<p>So to bring us back to the beginning. For JSON (de)serialization, it means you take a string of JSON and you produce data and attach no meaning to that data.
Attaching meaning to the data is the job of the consumer. Your responsability as a library author is to make it simple and possible
for your consumers to do so. For parsing CSV it’s exactly the same thing. you take a string of CSV and you produce data without meaning.
The consumer gets to decide if the first row is a header-row or not.</p>
<p>Basically. It boils down to designing simple things which do one thing well and which compose nicely with other things.</p>
<p>I think there is another post brewing on why configurable and general are not the same thing…</p>
The Problem I Dont Have2020-05-14T00:00:00+00:00http://slipset.github.io/posts/the-problem-i-dont-have<p>So, <a href="https://twitter.com/einarwh">Einar Høst</a> has been a bit <a href="https://einarwh.wordpress.com/2020/05/08/on-the-complexity-of-json-serialization/">frustrated</a>
about JSON serialization lately. In fact, he’s been <a href="https://einarwh.wordpress.com/2020/05/13/proper-json-and-property-bags/">more</a> than a bit frustrated.</p>
<p><a href="https://twitter.com/slipset/status/1258827099860860928?s=20">I’ve</a> made some fun of these problems, because they seem like problems I haven’t had since the last time I programmed in Java.</p>
<p>But instead of just making fun of this on twitter, how about looking at how we deal with the problem of JSON serialization
in the Clojure app we have at work.</p>
<p>As Einar states in his posts, the Clojure community has understood that JSON (de)serialization is a bounded problem, which is a nice way
to say that it’s an understood problem with an understood complexity, and you should be able to solve the problem one and for all.</p>
<p>Another example of a bounded, solved problem would be <a href="http://www.netlib.org/lapack/">lapack</a>. Anyways.</p>
<p>In the Clojure universe, we have, I’d say three contenders for JSON (de)serialization:</p>
<h3 id="clojuredatajson"><a href="https://github.com/clojure/data.json">clojure.data.json</a>.</h3>
<p>It offers exactly two functions:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">json/write-str</span><span class="w"> </span><span class="p">{</span><span class="no">:a</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="no">:b</span><span class="w"> </span><span class="mi">2</span><span class="p">})</span><span class="w">
</span><span class="c1">;;=> "{\"a\":1,\"b\":2}"</span><span class="w">
</span><span class="p">(</span><span class="nf">json/read-str</span><span class="w"> </span><span class="s">"{\"a\":1,\"b\":2}"</span><span class="p">)</span><span class="w">
</span><span class="c1">;;=> {"a" 1, "b" 2}</span><span class="w">
</span></code></pre></div></div>
<p>At first glance, there is no way to let the daemon that Einar talks about free, but if we read further we see that we can pass both a
<code class="language-plaintext highlighter-rouge">:value-fn</code> and a <code class="language-plaintext highlighter-rouge">:key-fn</code> to do transformation on the data as it is worked on. So, the configuration of this JSON library would be to
write these two functions. In clojure-land, we tend to like <code class="language-plaintext highlighter-rouge">keywords</code> for keys, so it’s normal to call <code class="language-plaintext highlighter-rouge">json/read-str</code> like this:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">my-value-reader</span><span class="w"> </span><span class="p">[</span><span class="nb">key</span><span class="w"> </span><span class="n">value</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nb">=</span><span class="w"> </span><span class="nb">key</span><span class="w"> </span><span class="no">:date</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nf">java.sql.Date/valueOf</span><span class="w"> </span><span class="n">value</span><span class="p">)</span><span class="w">
</span><span class="n">value</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nf">json/read-str</span><span class="w"> </span><span class="s">"{\"number\":42,\"date\":\"2012-06-02\"}"</span><span class="w">
</span><span class="no">:value-fn</span><span class="w"> </span><span class="n">my-value-reader</span><span class="w">
</span><span class="no">:key-fn</span><span class="w"> </span><span class="nb">keyword</span><span class="p">)</span><span class="w">
</span><span class="c1">;;=> {:number 42, :date #inst "2012-06-02T04:00:00.000-00:00"}</span><span class="w">
</span></code></pre></div></div>
<p>Note that in these examples, we’re only letting the daemon do simple type coercions. It is not allowed to transform the data. We’ll get to that later.</p>
<h3 id="cheshire"><a href="https://github.com/dakrone/cheshire">cheshire</a></h3>
<p>Basically, the top-level interface is the same, but with some more bells and whistles (and it’s apparently faster, since it’s built on <a href="https://github.com/FasterXML/jackson">Jackson</a>)
This is what we use at work.</p>
<h3 id="jsonista"><a href="https://github.com/metosin/jsonista">jsonista</a></h3>
<p>jsonista is the new kid on the block written for speed by <a href="https://www.metosin.fi">Metosin</a>
Again, we see the same toplevel interface, as <code class="language-plaintext highlighter-rouge">clojure.data.json</code>.</p>
<p>So I’d like to argue that in Clojure land, the JSON libs don’t care too much about your domain model, they care about
taking a string of JSON data and transforming it (fast) to a Clojure data-structure, possibly with some coercions.</p>
<h1 id="a-shopping-cart">A shopping cart</h1>
<p>So in <a href="https://einarwh.wordpress.com/2020/05/13/proper-json-and-property-bags/">his second post</a> has an example going with a shopping cart.
He models a shopping cart in JSON the following way:</p>
<p>1) The empty cart:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="nl">"_state"</span><span class="p">:</span><span class="w"> </span><span class="s2">"empty"</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>2) The active cart:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="nl">"_state"</span><span class="p">:</span><span class="w"> </span><span class="s2">"active"</span><span class="p">,</span><span class="w">
</span><span class="nl">"unpaidItems"</span><span class="p">:</span><span class="w"> </span><span class="p">[{</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1bcd"</span><span class="p">,</span><span class="w">
</span><span class="nl">"title"</span><span class="p">:</span><span class="w"> </span><span class="s2">"gizmo"</span><span class="p">},</span><span class="w">
</span><span class="p">{</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"3cdf"</span><span class="p">,</span><span class="w">
</span><span class="nl">"title"</span><span class="p">:</span><span class="w"> </span><span class="s2">"widget"</span><span class="p">}]}</span><span class="w">
</span></code></pre></div></div>
<p>3) The paid cart</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="nl">"_state"</span><span class="p">:</span><span class="w"> </span><span class="s2">"paid"</span><span class="p">,</span><span class="w">
</span><span class="nl">"paidItems"</span><span class="p">:</span><span class="w"> </span><span class="p">[{</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1bcd"</span><span class="p">,</span><span class="w">
</span><span class="nl">"title"</span><span class="p">:</span><span class="w"> </span><span class="s2">"gizmo"</span><span class="p">},</span><span class="w">
</span><span class="p">{</span><span class="nl">"id"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"3cdf"</span><span class="p">,</span><span class="w">
</span><span class="nl">"title"</span><span class="p">:</span><span class="w"> </span><span class="s2">"widget"</span><span class="p">,</span><span class="w">
</span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"A very useful item"</span><span class="p">}],</span><span class="w">
</span><span class="nl">"payment"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="nl">"amount"</span><span class="p">:</span><span class="w"> </span><span class="mf">123.5</span><span class="p">,</span><span class="w">
</span><span class="nl">"currency"</span><span class="p">:</span><span class="w"> </span><span class="s2">"USD"</span><span class="p">},</span><span class="w">
</span><span class="nl">"timestamp"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2020-04-11T10:11:33.514+02:00"</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>This looks reasonable to me, it’s all just data. Then there’s the “Explicit JSON model” chapter where things fall apart for me,
because, in order to produce this json, we’re forced to jump through a whole bunch of boiler plate. Let’s see how we’d do this in Clojure:
Firstly, we have data literals, so the above json is almost valid Clojure, we just need to remove the colons:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">paid-cart</span><span class="w"> </span><span class="p">{</span><span class="s">"_state"</span><span class="w"> </span><span class="s">"paid"</span><span class="n">,</span><span class="w">
</span><span class="s">"paidItems"</span><span class="w"> </span><span class="p">[{</span><span class="s">"id"</span><span class="w"> </span><span class="s">"1bcd"</span><span class="n">,</span><span class="w">
</span><span class="s">"title"</span><span class="w"> </span><span class="s">"gizmo"</span><span class="p">}</span><span class="n">,</span><span class="w">
</span><span class="p">{</span><span class="s">"id"</span><span class="w"> </span><span class="s">"3cdf"</span><span class="n">,</span><span class="w">
</span><span class="s">"title"</span><span class="w"> </span><span class="s">"widget"</span><span class="n">,</span><span class="w">
</span><span class="s">"description"</span><span class="w"> </span><span class="s">"A very useful item"</span><span class="p">}]</span><span class="n">,</span><span class="w">
</span><span class="s">"payment"</span><span class="w"> </span><span class="p">{</span><span class="s">"amount"</span><span class="w"> </span><span class="mf">123.5</span><span class="n">,</span><span class="w">
</span><span class="s">"currency"</span><span class="w"> </span><span class="s">"USD"</span><span class="p">}</span><span class="n">,</span><span class="w">
</span><span class="s">"timestamp"</span><span class="w"> </span><span class="s">"2020-04-11T10:11:33.514+02:00"</span><span class="p">})</span><span class="w">
</span></code></pre></div></div>
<p>Now, as mentioned above, we tend to prefer <code class="language-plaintext highlighter-rouge">keywords</code> over <code class="language-plaintext highlighter-rouge">strings</code> for keys, also we don’t need the pesky commas:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">paid-cart</span><span class="w"> </span><span class="p">{</span><span class="no">:_state</span><span class="w"> </span><span class="s">"paid"</span><span class="w">
</span><span class="no">:paidItems</span><span class="w"> </span><span class="p">[{</span><span class="no">:id</span><span class="w"> </span><span class="s">"1bcd"</span><span class="w">
</span><span class="no">:title</span><span class="w"> </span><span class="s">"gizmo"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:id</span><span class="w"> </span><span class="s">"3cdf"</span><span class="w">
</span><span class="no">:title</span><span class="w"> </span><span class="s">"widget"</span><span class="w">
</span><span class="no">:description</span><span class="w"> </span><span class="s">"A very useful item"</span><span class="p">}]</span><span class="w">
</span><span class="no">:payment</span><span class="w"> </span><span class="p">{</span><span class="no">:amount</span><span class="w"> </span><span class="mf">123.5</span><span class="w">
</span><span class="no">:currency</span><span class="w"> </span><span class="s">"USD"</span><span class="p">}</span><span class="w">
</span><span class="no">:timestamp</span><span class="w"> </span><span class="s">"2020-04-11T10:11:33.514+02:00"</span><span class="p">})</span><span class="w">
</span></code></pre></div></div>
<p>So serialization (I’ll be using Cheshire), becomes</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">json/encode</span><span class="w"> </span><span class="n">paid-cart</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>Deserialization, you ask?</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">json</span><span class="w"> </span><span class="s">"{\"_state\":\"paid\",\"paidItems\":[{\"id\":\"1bcd\",\"title\":\"gizmo\"},{\"id\":\"3cdf\",\"title\":\"widget\",\"description\":\"A very useful item\"}],\"payment\":{\"amount\":123.5,\"currency\":\"USD\"},\"timestamp\":\"2020-04-11T10:11:33.514+02:00\"}"</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">paid-cart</span><span class="w"> </span><span class="p">(</span><span class="nf">json/decode</span><span class="w"> </span><span class="n">json</span><span class="w"> </span><span class="n">true</span><span class="p">))</span><span class="w"> </span><span class="c1">; I'll let the daemon know I want to keywordize keys.</span><span class="w">
</span><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">first-item-title</span><span class="w"> </span><span class="p">(</span><span class="nf">get-in</span><span class="w"> </span><span class="n">paid-cart</span><span class="w"> </span><span class="p">[</span><span class="no">:paidItems</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="no">:title</span><span class="p">]))</span><span class="w">
</span><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">payment-currency</span><span class="w"> </span><span class="p">(</span><span class="nf">get-in</span><span class="w"> </span><span class="n">paid-cart</span><span class="w"> </span><span class="p">[</span><span class="no">:payment</span><span class="w"> </span><span class="no">:currency</span><span class="p">]))</span><span class="w">
</span></code></pre></div></div>
<p>So as in Einars example, our deserialization of json got us data back, but unlike Einars example, Clojure is made for working with
data, so there is no pesky</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">firstItemTitleToken</span> <span class="p">=</span> <span class="n">paidCartDeserialized</span><span class="p">[</span><span class="s">"paidItems"</span><span class="p">][</span><span class="m">0</span><span class="p">][</span><span class="s">"title"</span><span class="p">];</span>
<span class="kt">var</span> <span class="n">firstItemTitle</span> <span class="p">=</span> <span class="p">((</span><span class="n">JValue</span><span class="p">)</span> <span class="n">firstItemTitleToken</span><span class="p">).</span><span class="n">Value</span><span class="p">;</span>
</code></pre></div></div>
<p>to get the stuff we’re interested in.</p>
<p>So this is what Einar called a explicit json model. Thing is that we got the next thing basically for free, as we now also have the
explicit DTO model, since we just work with data, we don’t need DTOs. There is so much bloat and boilerplate in the explicit DTO model section
that I cannot even bother to see if there is any value there.</p>
<p>The last part is what Einar has called “Dictionary”, it’s basically what we have above, again without a bunch of boilerplate.</p>
<h1 id="validation">Validation</h1>
<p>One thing that I didn’t see in Einars post is any kind of validation (apart maybe from some stuff that blows up at runtime even though he uses static types).
Let’s have a look at how we would make some validation for this in Clojure. For this, we’ll use <a href="https://clojure.org/guides/spec">clojure.spec</a>:</p>
<p>I won’t go into spec here, but I’ll just spec the data-model that we’re working with:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">s/def</span><span class="w"> </span><span class="no">::_state</span><span class="w"> </span><span class="o">#</span><span class="p">{</span><span class="s">"empty"</span><span class="n">,</span><span class="w"> </span><span class="s">"active"</span><span class="n">,</span><span class="w"> </span><span class="s">"paid"</span><span class="p">})</span><span class="w"> </span><span class="c1">;; We model the descriminator as a set of values</span><span class="w">
</span><span class="p">(</span><span class="nf">s/def</span><span class="w"> </span><span class="no">::id</span><span class="w"> </span><span class="nb">string?</span><span class="p">)</span><span class="w"> </span><span class="c1">;; this could be further tightened by a stronger predicate, we don't allow the complete works of</span><span class="w">
</span><span class="c1">;; Shakespear as an id.</span><span class="w">
</span><span class="p">(</span><span class="nf">s/def</span><span class="w"> </span><span class="no">::title</span><span class="w"> </span><span class="nb">string?</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nf">s/def</span><span class="w"> </span><span class="no">::description</span><span class="w"> </span><span class="nb">string?</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nf">s/def</span><span class="w"> </span><span class="no">::item</span><span class="w"> </span><span class="p">(</span><span class="nf">s/keys</span><span class="w"> </span><span class="no">:req-un</span><span class="w"> </span><span class="p">[</span><span class="no">::id</span><span class="w"> </span><span class="no">::title</span><span class="p">]</span><span class="w"> </span><span class="c1">;; id and title are required keys</span><span class="w">
</span><span class="no">:opt-un</span><span class="w"> </span><span class="p">[</span><span class="no">::description</span><span class="p">]))</span><span class="w"> </span><span class="c1">;; description is optional</span><span class="w">
</span><span class="p">(</span><span class="nf">s/def</span><span class="w"> </span><span class="no">::items</span><span class="w"> </span><span class="p">(</span><span class="nf">s/coll-of</span><span class="w"> </span><span class="no">::item</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nf">s/def</span><span class="w"> </span><span class="no">::paidItems</span><span class="w"> </span><span class="p">(</span><span class="nf">s/coll-of</span><span class="w"> </span><span class="no">::item</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nf">s/def</span><span class="w"> </span><span class="no">::amount</span><span class="w"> </span><span class="p">(</span><span class="nf">s/or</span><span class="w"> </span><span class="no">:zero</span><span class="w"> </span><span class="nb">zero?</span><span class="w"> </span><span class="no">:positive</span><span class="w"> </span><span class="nb">pos?</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nf">s/def</span><span class="w"> </span><span class="no">::currency</span><span class="w"> </span><span class="o">#</span><span class="p">{</span><span class="s">"USD"</span><span class="p">})</span><span class="w">
</span><span class="p">(</span><span class="nf">s/def</span><span class="w"> </span><span class="no">::payment</span><span class="w"> </span><span class="p">(</span><span class="nf">s/keys</span><span class="w"> </span><span class="no">:req-un</span><span class="w"> </span><span class="p">[</span><span class="no">::amount</span><span class="w"> </span><span class="no">::currency</span><span class="p">]))</span><span class="w">
</span><span class="p">(</span><span class="nf">s/def</span><span class="w"> </span><span class="no">::timestamp</span><span class="w"> </span><span class="n">inst?</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nf">s/def</span><span class="w"> </span><span class="no">::empty-cart</span><span class="w"> </span><span class="p">(</span><span class="nf">s/keys</span><span class="w"> </span><span class="no">:req-un</span><span class="w"> </span><span class="p">[</span><span class="no">::_state</span><span class="p">]))</span><span class="w">
</span><span class="p">(</span><span class="nf">s/def</span><span class="w"> </span><span class="no">::active-cart</span><span class="w"> </span><span class="p">(</span><span class="nf">s/keys</span><span class="w"> </span><span class="no">:req-un</span><span class="w"> </span><span class="p">[</span><span class="no">::_state</span><span class="w"> </span><span class="no">::items</span><span class="p">]))</span><span class="w">
</span><span class="p">(</span><span class="nf">s/def</span><span class="w"> </span><span class="no">::paid-cart</span><span class="w"> </span><span class="p">(</span><span class="nf">s/keys</span><span class="w"> </span><span class="no">:req-un</span><span class="w"> </span><span class="p">[</span><span class="no">::_state</span><span class="w"> </span><span class="no">::paidItems</span><span class="w"> </span><span class="no">::payment</span><span class="w"> </span><span class="no">::timestamp</span><span class="p">]))</span><span class="w">
</span><span class="p">(</span><span class="nf">s/def</span><span class="w"> </span><span class="no">::shopping-cart</span><span class="w"> </span><span class="p">(</span><span class="nf">s/or</span><span class="w"> </span><span class="no">:empty</span><span class="w"> </span><span class="no">::empty-cart</span><span class="w"> </span><span class="no">:active</span><span class="w"> </span><span class="no">::active-cart</span><span class="w"> </span><span class="no">:paid</span><span class="w"> </span><span class="no">::paid-cart</span><span class="p">))</span><span class="w">
</span></code></pre></div></div>
<p>This is a simplified validation, since I’m not checking that the state is correct for the various types of carts, also, we have another problem,
the paid cart won’t validate, sine we’ve said that the timestamp has to be an <code class="language-plaintext highlighter-rouge">inst?</code>, ie a real timestamp, not just a string.
We could wake the daemon and do that as part of the json-parsing, but I generally prefer to take the speed-hit and do it manually:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">coerce-shopping-cart</span><span class="w"> </span><span class="p">[</span><span class="n">cart</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nf">my-util/update-some</span><span class="w"> </span><span class="n">cart</span><span class="w"> </span><span class="no">:timestamp</span><span class="w"> </span><span class="n">to-inst</span><span class="p">))</span><span class="w">
</span></code></pre></div></div>
<p>Spec gives us some nice tools:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">s/valid?</span><span class="w"> </span><span class="no">::shopping-cart</span><span class="w"> </span><span class="p">{</span><span class="no">:_state</span><span class="w"> </span><span class="s">"empty"</span><span class="p">})</span><span class="w">
</span><span class="c1">;; => true</span><span class="w">
</span></code></pre></div></div>
<p>What kind of cart is it?</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">s/conform</span><span class="w"> </span><span class="no">::shopping-cart</span><span class="w"> </span><span class="p">{</span><span class="no">:_state</span><span class="w"> </span><span class="s">"empty"</span><span class="p">})</span><span class="w">
</span><span class="c1">;; => [:empty {:_state "empty"}]</span><span class="w">
</span></code></pre></div></div>
<p>Clojure never had a good story on error messages, but still:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">user></span><span class="w"> </span><span class="p">(</span><span class="nf">s/explain</span><span class="w"> </span><span class="no">::shopping-cart</span><span class="w"> </span><span class="p">{</span><span class="no">:_state</span><span class="w"> </span><span class="s">"lol"</span><span class="p">})</span><span class="w">
</span><span class="s">"lol"</span><span class="w"> </span><span class="nb">-</span><span class="w"> </span><span class="n">failed</span><span class="err">:</span><span class="w"> </span><span class="o">#</span><span class="p">{</span><span class="s">"paid"</span><span class="w"> </span><span class="s">"empty"</span><span class="w"> </span><span class="s">"active"</span><span class="p">}</span><span class="w"> </span><span class="n">in</span><span class="err">:</span><span class="w"> </span><span class="p">[</span><span class="no">:_state</span><span class="p">]</span><span class="w"> </span><span class="n">at</span><span class="err">:</span><span class="w"> </span><span class="p">[</span><span class="no">:empty</span><span class="w"> </span><span class="no">:_state</span><span class="p">]</span><span class="w"> </span><span class="n">spec</span><span class="err">:</span><span class="w"> </span><span class="no">:user/_state</span><span class="w">
</span><span class="s">"lol"</span><span class="w"> </span><span class="nb">-</span><span class="w"> </span><span class="n">failed</span><span class="err">:</span><span class="w"> </span><span class="o">#</span><span class="p">{</span><span class="s">"paid"</span><span class="w"> </span><span class="s">"empty"</span><span class="w"> </span><span class="s">"active"</span><span class="p">}</span><span class="w"> </span><span class="n">in</span><span class="err">:</span><span class="w"> </span><span class="p">[</span><span class="no">:_state</span><span class="p">]</span><span class="w"> </span><span class="n">at</span><span class="err">:</span><span class="w"> </span><span class="p">[</span><span class="no">:active</span><span class="w"> </span><span class="no">:_state</span><span class="p">]</span><span class="w"> </span><span class="n">spec</span><span class="err">:</span><span class="w"> </span><span class="no">:user/_state</span><span class="w">
</span><span class="s">"lol"</span><span class="w"> </span><span class="nb">-</span><span class="w"> </span><span class="n">failed</span><span class="err">:</span><span class="w"> </span><span class="o">#</span><span class="p">{</span><span class="s">"paid"</span><span class="w"> </span><span class="s">"empty"</span><span class="w"> </span><span class="s">"active"</span><span class="p">}</span><span class="w"> </span><span class="n">in</span><span class="err">:</span><span class="w"> </span><span class="p">[</span><span class="no">:_state</span><span class="p">]</span><span class="w"> </span><span class="n">at</span><span class="err">:</span><span class="w"> </span><span class="p">[</span><span class="no">:paid</span><span class="w"> </span><span class="no">:_state</span><span class="p">]</span><span class="w"> </span><span class="n">spec</span><span class="err">:</span><span class="w"> </span><span class="no">:user/_state</span><span class="w">
</span><span class="p">{</span><span class="no">:_state</span><span class="w"> </span><span class="s">"lol"</span><span class="p">}</span><span class="w"> </span><span class="nb">-</span><span class="w"> </span><span class="n">failed</span><span class="err">:</span><span class="w"> </span><span class="p">(</span><span class="nb">contains?</span><span class="w"> </span><span class="n">%</span><span class="w"> </span><span class="no">:items</span><span class="p">)</span><span class="w"> </span><span class="n">at</span><span class="err">:</span><span class="w"> </span><span class="p">[</span><span class="no">:active</span><span class="p">]</span><span class="w"> </span><span class="n">spec</span><span class="err">:</span><span class="w"> </span><span class="no">:user/active-cart</span><span class="w">
</span><span class="p">{</span><span class="no">:_state</span><span class="w"> </span><span class="s">"lol"</span><span class="p">}</span><span class="w"> </span><span class="nb">-</span><span class="w"> </span><span class="n">failed</span><span class="err">:</span><span class="w"> </span><span class="p">(</span><span class="nb">contains?</span><span class="w"> </span><span class="n">%</span><span class="w"> </span><span class="no">:paidItems</span><span class="p">)</span><span class="w"> </span><span class="n">at</span><span class="err">:</span><span class="w"> </span><span class="p">[</span><span class="no">:paid</span><span class="p">]</span><span class="w"> </span><span class="n">spec</span><span class="err">:</span><span class="w"> </span><span class="no">:user/paid-cart</span><span class="w">
</span><span class="p">{</span><span class="no">:_state</span><span class="w"> </span><span class="s">"lol"</span><span class="p">}</span><span class="w"> </span><span class="nb">-</span><span class="w"> </span><span class="n">failed</span><span class="err">:</span><span class="w"> </span><span class="p">(</span><span class="nb">contains?</span><span class="w"> </span><span class="n">%</span><span class="w"> </span><span class="no">:payment</span><span class="p">)</span><span class="w"> </span><span class="n">at</span><span class="err">:</span><span class="w"> </span><span class="p">[</span><span class="no">:paid</span><span class="p">]</span><span class="w"> </span><span class="n">spec</span><span class="err">:</span><span class="w"> </span><span class="no">:user/paid-cart</span><span class="w">
</span><span class="p">{</span><span class="no">:_state</span><span class="w"> </span><span class="s">"lol"</span><span class="p">}</span><span class="w"> </span><span class="nb">-</span><span class="w"> </span><span class="n">failed</span><span class="err">:</span><span class="w"> </span><span class="p">(</span><span class="nb">contains?</span><span class="w"> </span><span class="n">%</span><span class="w"> </span><span class="no">:timestamp</span><span class="p">)</span><span class="w"> </span><span class="n">at</span><span class="err">:</span><span class="w"> </span><span class="p">[</span><span class="no">:paid</span><span class="p">]</span><span class="w"> </span><span class="n">spec</span><span class="err">:</span><span class="w"> </span><span class="no">:user/paid-cart</span><span class="w">
</span><span class="c1">;; => nil</span><span class="w">
</span></code></pre></div></div>
<p>It would be great to have a cart:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w"> </span><span class="p">(</span><span class="nf">gen/generate</span><span class="w"> </span><span class="p">(</span><span class="nf">s/gen</span><span class="w"> </span><span class="no">::paid-cart</span><span class="p">))</span><span class="w">
</span><span class="c1">;; => {:_state "paid",</span><span class="w">
</span><span class="no">:paidItems</span><span class="w">
</span><span class="p">[{</span><span class="no">:description</span><span class="w"> </span><span class="s">"GyvuaWY4XLo46p5cbOH4E3"</span><span class="n">,</span><span class="w">
</span><span class="no">:id</span><span class="w"> </span><span class="s">""</span><span class="n">,</span><span class="w">
</span><span class="no">:title</span><span class="w"> </span><span class="s">"6a5H39kSldjL4Y9OH54te"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:id</span><span class="w"> </span><span class="s">"RE6jZ71sG2A8RhUJBgz2A"</span><span class="n">,</span><span class="w">
</span><span class="no">:title</span><span class="w"> </span><span class="s">"z95292hKUVrme880y7TYOB3Y6K02o"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:description</span><span class="w"> </span><span class="s">"z2A4s1u8PY8B1dR225nG80"</span><span class="n">,</span><span class="w">
</span><span class="no">:id</span><span class="w"> </span><span class="s">"rdaMSp5qi"</span><span class="n">,</span><span class="w">
</span><span class="no">:title</span><span class="w"> </span><span class="s">"MyTMI2KXe036H6y1lG7KgGW80"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:id</span><span class="w"> </span><span class="s">"R4JlD3324500q7tWoGX5FCP2Pi84"</span><span class="n">,</span><span class="w"> </span><span class="no">:title</span><span class="w"> </span><span class="s">"ed"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:id</span><span class="w"> </span><span class="s">"24i1Ft25z0Vcwx39Zt19JQOm"</span><span class="n">,</span><span class="w">
</span><span class="no">:title</span><span class="w"> </span><span class="s">"CN3J2X1Q9laCNqiM56w5Qu98h"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:description</span><span class="w"> </span><span class="s">"e9E7o6wID69252iHuq"</span><span class="n">,</span><span class="w">
</span><span class="no">:id</span><span class="w"> </span><span class="s">"xMxykN9"</span><span class="n">,</span><span class="w">
</span><span class="no">:title</span><span class="w"> </span><span class="s">"xlgTk596KtKqfk14fZ"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:id</span><span class="w"> </span><span class="s">"1vLq4"</span><span class="n">,</span><span class="w"> </span><span class="no">:title</span><span class="w"> </span><span class="s">"6nX8P3rJ"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:id</span><span class="w"> </span><span class="s">"z1IcRi13w9KfCFo5vrsN7QF0b"</span><span class="n">,</span><span class="w"> </span><span class="no">:title</span><span class="w"> </span><span class="s">"4i608Mrli6gTO12u"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:description</span><span class="w"> </span><span class="s">"rIZ1Gb7WRha6k4A7"</span><span class="n">,</span><span class="w">
</span><span class="no">:id</span><span class="w"> </span><span class="s">"i1E7jh4SL62E03KAxw"</span><span class="n">,</span><span class="w">
</span><span class="no">:title</span><span class="w"> </span><span class="s">"46ZTrxJ5NVUd1sP3Ov4l4qVhs"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:id</span><span class="w"> </span><span class="s">"hDz8aLoTLedEl8rSiPOd"</span><span class="n">,</span><span class="w"> </span><span class="no">:title</span><span class="w"> </span><span class="s">"513NfwaT6bXNGrRsFM20"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:id</span><span class="w"> </span><span class="s">"KBpUt8ni0O82668e5BSk"</span><span class="n">,</span><span class="w"> </span><span class="no">:title</span><span class="w"> </span><span class="s">"hc1S8kR0zn05OHZ"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:description</span><span class="w"> </span><span class="s">"ZXQozSg7cF1c9WRs50F4x"</span><span class="n">,</span><span class="w">
</span><span class="no">:id</span><span class="w"> </span><span class="s">"SNe39R8dmHlXalxR8kKj3BVtthV6b"</span><span class="n">,</span><span class="w">
</span><span class="no">:title</span><span class="w"> </span><span class="s">"890HUMb3J3qsq18N7f46905QR"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:description</span><span class="w"> </span><span class="s">"0KOO0"</span><span class="n">,</span><span class="w">
</span><span class="no">:id</span><span class="w"> </span><span class="s">"365k3UX69mlrsRp"</span><span class="n">,</span><span class="w">
</span><span class="no">:title</span><span class="w"> </span><span class="s">"9bCcS688TbYu1r;; => R1"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:id</span><span class="w"> </span><span class="s">"X89JqN8WA2mf8x6"</span><span class="n">,</span><span class="w"> </span><span class="no">:title</span><span class="w"> </span><span class="s">"BdQK3hXD1lEqJVp5mtqD"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:description</span><span class="w"> </span><span class="s">"Uc3614Es3VzLe1"</span><span class="n">,</span><span class="w"> </span><span class="no">:id</span><span class="w"> </span><span class="s">"C56Z4h481"</span><span class="n">,</span><span class="w"> </span><span class="no">:title</span><span class="w"> </span><span class="s">"2H920Z"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:description</span><span class="w"> </span><span class="s">"M7CS3886ASPY9HX30IZp4K7Vk8"</span><span class="n">,</span><span class="w">
</span><span class="no">:id</span><span class="w"> </span><span class="s">"WqeQc1vF1wV8asa18edG15joaGnEW"</span><span class="n">,</span><span class="w">
</span><span class="no">:title</span><span class="w"> </span><span class="s">"UgRa"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:description</span><span class="w"> </span><span class="s">"oS439d98t"</span><span class="n">,</span><span class="w">
</span><span class="no">:id</span><span class="w"> </span><span class="s">"BQMQBpG1BP7SX7GzG06sf7p3pQuFeN"</span><span class="n">,</span><span class="w">
</span><span class="no">:title</span><span class="w"> </span><span class="s">"hGq4Sgdeaq0G17"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:id</span><span class="w"> </span><span class="s">"zgbx2v6D03"</span><span class="n">,</span><span class="w"> </span><span class="no">:title</span><span class="w"> </span><span class="s">"3K42M5G0ix870Z2q8JhI8jv4Km"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:id</span><span class="w"> </span><span class="s">"pz65Sy46YW22809p7"</span><span class="n">,</span><span class="w"> </span><span class="no">:title</span><span class="w"> </span><span class="s">"r66BqkjEQ9dFLE"</span><span class="p">}</span><span class="w">
</span><span class="p">{</span><span class="no">:id</span><span class="w"> </span><span class="s">"1o0viZrbl4"</span><span class="n">,</span><span class="w"> </span><span class="no">:title</span><span class="w"> </span><span class="s">"sdp138TYcWJ4eQe4"</span><span class="p">}]</span><span class="n">,</span><span class="w">
</span><span class="no">:payment</span><span class="w"> </span><span class="p">{</span><span class="no">:amount</span><span class="w"> </span><span class="mi">0</span><span class="n">,</span><span class="w"> </span><span class="no">:currency</span><span class="w"> </span><span class="s">"USD"</span><span class="p">}</span><span class="n">,</span><span class="w">
</span><span class="no">:timestamp</span><span class="w"> </span><span class="o">#</span><span class="n">inst</span><span class="w"> </span><span class="s">"1969-12-31T23:59:04.657-00:00"</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>So now we can write something like:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">let</span><span class="w"> </span><span class="p">[</span><span class="n">cart</span><span class="w"> </span><span class="p">(</span><span class="nb">-></span><span class="w"> </span><span class="n">json</span><span class="w"> </span><span class="p">(</span><span class="nf">json/decode</span><span class="w"> </span><span class="n">true</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nf">coerce-shopping-cart</span><span class="p">))]</span><span class="w">
</span><span class="p">(</span><span class="nb">when-not</span><span class="w"> </span><span class="p">(</span><span class="nf">s/valid</span><span class="w"> </span><span class="no">::shopping-cart</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nf">throw</span><span class="w"> </span><span class="p">(</span><span class="nf">Exception.</span><span class="w"> </span><span class="p">(</span><span class="nb">str</span><span class="w"> </span><span class="s">"Invalid cart"</span><span class="w"> </span><span class="p">(</span><span class="nf">s/explain</span><span class="w"> </span><span class="no">::shopping-cart</span><span class="w"> </span><span class="n">cart</span><span class="p">))))</span><span class="w">
</span><span class="n">cart</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<h1 id="summary">Summary</h1>
<p>Einars post was rather long, and as with most verbose things, both prose and code, the important bits might be lost in the noise, so there might have been finer points that I have missed.
But I didn’t miss the question at the end. So I think that you should treat data as data, and be done with it.</p>
<p>I’ll leave you with a tweet from <a href="https://twitter.com/swannodette">David Nolen</a>, the lead developer for Clojurescript:</p>
<blockquote>
<p>Potential isn’t about doing N things nor abstractions. It’s about doing <em>ONE</em> thing and doing it so simply that adding another thing is trivial. In some circles, aka “writing some functions”.</p>
</blockquote>
Why Clojure Is My Favourite Language2019-12-27T00:00:00+00:00http://slipset.github.io/posts/Why-Clojure-is-my-favourite-language<p><a href="https://twitter.com/hillelogram">Hillel Wayne</a> has a newsletter that you should absolutely <a href="https://buttondown.email/hillelwayne">subscribe</a> to.
<a href="https://buttondown.email/hillelwayne/archive/why-python-is-my-favorite-language/">Todays edition</a> is called “Why Python Is My Favourite Languge”,
and describes all the hurdles you need to jump in order to solve your $PROBLEM in a new language.</p>
<p>So in this post, I’ll try to look at these hurdles, and see how they are overcome in my favourite language, Clojure:</p>
<h2 id="how-do-i-install-the-thing">How do I install the thing?</h2>
<p>Hillel didn’t actually ask this question, but it’s IMO worth asking.
<a href="https://clojure.org">Clojure</a> is language running on the JVM, which means you need to have java installed (and yes I’m assuming a mac here):</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>brew <span class="nb">install </span>adoptopenjdk
</code></pre></div></div>
<p>Once Java is installed, you should install <code class="language-plaintext highlighter-rouge">clojure</code> and you’re good to go:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>brew <span class="nb">install </span>clojure
</code></pre></div></div>
<p>This gives you two new commands, of which we’ll be focusing on <code class="language-plaintext highlighter-rouge">clj</code> which drops you into a repl:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>clj
Clojure 1.10.1
<span class="nv">user</span><span class="o">=></span>
</code></pre></div></div>
<p>You can read more about how to get started <a href="https://clojure.org/guides/getting_started">here</a>.</p>
<h2 id="how-am-i-supposed-to-be-writing-this">How am I supposed to be writing this?</h2>
<p>Clojure is editor agnostic, but anyone working in Clojure will be using her favourite $EDITOR with some plugin:</p>
<ul>
<li>Emacs, you will of course be using <a href="https://docs.cider.mx/cider/index.html">CIDER</a>, unless you’re <a href="https://twitter.com/stuarthalloway">Sherlock</a> and you’re using
<a href="https://github.com/clojure-emacs/inf-clojure">inf-clojure-mode</a></li>
<li>Vim, here <a href="https://github.com/tpope/vim-fireplace">fireplace</a> seems to be the choice of champions</li>
<li>VSCode, your choice is <a href="https://calva.readthedocs.io/en/latest/">Calva</a>, which aims at a great experience for beginners and pros alike</li>
<li>For Intellij, just download <a href="https://cursive-ide.com">Cursive</a>, which is free for personal use.</li>
<li>Atom has <a href="https://atom.io/packages/chlorine">Chlorine</a>, read more about it <a href="https://corfield.org/blog/2018/12/19/atom-chlorine/">here</a></li>
</ul>
<p>2) How do I read from a file? How do I parse JSON, How do I pull environmental variables?
This section also contains two sub-questions, so let’s start with those:</p>
<h3 id="how-do-i-do-any-of-the-things-that-arent-part-of-the-core-syntaxsemantics-but-are-super-common-problems-people-face-every-day">How do I do any of the things that aren’t part of the core syntax/semantics, but are super common problems people face every day?</h3>
<p>Let’s answer this and the first question from the section with one function: <a href="https://clojuredocs.org/clojure.core/slurp"><code class="language-plaintext highlighter-rouge">slurp</code></a>.
<code class="language-plaintext highlighter-rouge">slurp</code> lets you read from a file or a URL.</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">passwords</span><span class="w"> </span><span class="p">(</span><span class="nb">slurp</span><span class="w"> </span><span class="s">"/etc/password"</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">news-letter</span><span class="w"> </span><span class="p">(</span><span class="nb">slurp</span><span class="w"> </span><span class="s">"https://buttondown.email/hillelwayne/archive/why-python-is-my-favorite-language/"</span><span class="p">))</span><span class="w">
</span></code></pre></div></div>
<p>its companion is calleds <a href="https://clojuredocs.org/clojure.core/spit"><code class="language-plaintext highlighter-rouge">spit</code></a>:</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">spit</span><span class="w"> </span><span class="s">"/tmp/password"</span><span class="w"> </span><span class="p">(</span><span class="nb">slurp</span><span class="w"> </span><span class="s">"/etc/password"</span><span class="p">))</span><span class="w">
</span></code></pre></div></div>
<h3 id="how-do-i-parse-json">How do I parse JSON?</h3>
<p>Parsing JSON is (unfortunatly) not part of the core language, so first we need to understand how we do dependency management in Clojure.</p>
<h4 id="dependency-management">Dependency management</h4>
<p>For dependency management in Clojure, there are several options (in addition to doing it manually which I will not cover here).
There is <a href="https://clojure.org/guides/deps_and_cli"><code class="language-plaintext highlighter-rouge">deps</code></a> which is the most official way, and which is understood by the tools you installed previously,
<a href="https://leiningen.org">Leiningen</a> which was the defacto standard for many years, and <a href="https://boot-clj.com">boot</a> which seems to be somewhat less popular these days.
For this post, I’ll be focusing on <code class="language-plaintext highlighter-rouge">deps</code>.</p>
<p>So when you start <code class="language-plaintext highlighter-rouge">clj</code>, it will look for a file called <code class="language-plaintext highlighter-rouge">deps.edn</code> and parse it looking for dependencies. In its simplest form a <code class="language-plaintext highlighter-rouge">deps.edn</code> file will look like:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="no">:deps</span><span class="w">
</span><span class="p">{</span><span class="n">cheshire</span><span class="w"> </span><span class="p">{</span><span class="no">:mvn/version</span><span class="w"> </span><span class="s">"5.9.0"</span><span class="p">}}}</span><span class="w">
</span></code></pre></div></div>
<p>With a <code class="language-plaintext highlighter-rouge">deps.edn</code> like this, <code class="language-plaintext highlighter-rouge">clj</code> will download <a href="https://github.com/dakrone/cheshire">cheshire</a> and start up Clojure with <code class="language-plaintext highlighter-rouge">cheshire</code> as a dependency, and voila, you can parse json:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">require</span><span class="w"> </span><span class="o">'</span><span class="p">[</span><span class="n">cheshire.core</span><span class="w"> </span><span class="no">:as</span><span class="w"> </span><span class="n">json</span><span class="p">])</span><span class="w">
</span><span class="p">(</span><span class="nf">json/decode</span><span class="w"> </span><span class="s">"{foo: \"bar\"}"</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nf">json/encode</span><span class="w"> </span><span class="p">{</span><span class="no">:foo</span><span class="w"> </span><span class="err">"</span><span class="n">bar</span><span class="p">})</span><span class="w">
</span></code></pre></div></div>
<h3 id="how-do-i-pull-environment-variables">How do I pull environment variables</h3>
<p>Since Clojure is running on the JVM, it’s a matter of doing some <a href="https://www.clojure.org/reference/java_interop">Java interop</a></p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">System/getProperty</span><span class="w"> </span><span class="s">"user.dir"</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>The final question in this section was “Do I need to memorize another 100 functions and their params?”. My answer to this is of course “it depends”.
First of all, the standard lib of Clojure is quite small, and since we’re basically always operating on maps and lists, you get fairly far with the basic operations on these datastructures (<code class="language-plaintext highlighter-rouge">map</code>, <code class="language-plaintext highlighter-rouge">filter</code>, <code class="language-plaintext highlighter-rouge">reduce</code>, <code class="language-plaintext highlighter-rouge">assoc</code>, <code class="language-plaintext highlighter-rouge">dissoc</code>)</p>
<p>As a final note in this section, I’d recommend having a look at <a href="https://github.com/dakrone/clj-http">clj-http</a> which should cover all your <code class="language-plaintext highlighter-rouge">http</code> needs.
So with a <code class="language-plaintext highlighter-rouge">deps.clj</code> looking like</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="no">:deps</span><span class="w">
</span><span class="p">{</span><span class="n">cheshire</span><span class="w"> </span><span class="p">{</span><span class="no">:mvn/version</span><span class="w"> </span><span class="s">"5.9.0"</span><span class="p">}</span><span class="w">
</span><span class="n">clj-http</span><span class="w"> </span><span class="p">{</span><span class="no">:mvn/version</span><span class="w"> </span><span class="s">"3.10.0"</span><span class="p">}}}</span><span class="w">
</span></code></pre></div></div>
<p>you’ll be set for most of your daily tasks.</p>
<h2 id="what-are-the-language-quirks-that-will-cast-me-an-hour-to-discover">What are the language quirks that will cast me an hour to discover</h2>
<p>Clojure is famous for its bad error messages, so time will be spent on understanding them, this is but one example:</p>
<div class="language-clj highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">user=></span><span class="w"> </span><span class="p">(</span><span class="nb">map</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">[</span><span class="ss">'lol</span><span class="p">])</span><span class="w">
</span><span class="n">Error</span><span class="w"> </span><span class="n">printing</span><span class="w"> </span><span class="n">return</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="p">(</span><span class="nf">ClassCastException</span><span class="p">)</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="n">clojure.core/map$fn</span><span class="w"> </span><span class="p">(</span><span class="nf">core.clj</span><span class="no">:2753</span><span class="p">)</span><span class="nb">.</span><span class="w">
</span><span class="nb">class</span><span class="w"> </span><span class="n">java.lang.Long</span><span class="w"> </span><span class="n">cannot</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="nb">cast</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="nb">class</span><span class="w"> </span><span class="n">clojure.lang.IFn</span><span class="w">
</span></code></pre></div></div>
<p>Having said that, a lot of work has been put down in order to make the error messages better in the last releases.</p>
<h2 id="how-is-the-help-organized-is-there-an-official-site-hows-the-site-laid-out">How is the help organized? Is there an official site? How’s the site laid out?</h2>
<p>A lot of help is done in the <a href="http://clojurians.net">Clojurians slack</a>, so yes, you may have to join yet another slack community.
Otherwise, I find <a href="clojuredocs.org">Clojure docs</a> extremely helpful for documentation on the standard library, <a href="https://cljdoc.org">cljdoc</a> for documentation on most of the important community libraries, and the <a href="https://www.clojure-toolbox.com">clojure toolbox</a> which is a directory of useful libraries.</p>
<p>The official docs are there in the repl for you, along with the source and apropos:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">$</span><span class="w"> </span><span class="n">clj</span><span class="w">
</span><span class="n">Clojure</span><span class="w"> </span><span class="mf">1.10</span><span class="n">.1</span><span class="w">
</span><span class="n">user=></span><span class="w"> </span><span class="p">(</span><span class="nb">doc</span><span class="w"> </span><span class="nb">map</span><span class="p">)</span><span class="w">
</span><span class="n">-------------------------</span><span class="w">
</span><span class="n">clojure.core/map</span><span class="w">
</span><span class="p">([</span><span class="n">f</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="n">f</span><span class="w"> </span><span class="n">coll</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="n">f</span><span class="w"> </span><span class="n">c1</span><span class="w"> </span><span class="n">c2</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="n">f</span><span class="w"> </span><span class="n">c1</span><span class="w"> </span><span class="n">c2</span><span class="w"> </span><span class="n">c3</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="n">f</span><span class="w"> </span><span class="n">c1</span><span class="w"> </span><span class="n">c2</span><span class="w"> </span><span class="n">c3</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="n">colls</span><span class="p">])</span><span class="w">
</span><span class="n">Returns</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">lazy</span><span class="w"> </span><span class="n">sequence</span><span class="w"> </span><span class="n">consisting</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">applying</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">to</span><span class="w">
</span><span class="n">the</span><span class="w"> </span><span class="nb">set</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="nb">first</span><span class="w"> </span><span class="n">items</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">each</span><span class="w"> </span><span class="n">coll,</span><span class="w"> </span><span class="n">followed</span><span class="w"> </span><span class="n">by</span><span class="w"> </span><span class="n">applying</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">the</span><span class="w">
</span><span class="nb">set</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="nb">second</span><span class="w"> </span><span class="n">items</span><span class="w"> </span><span class="n">in</span><span class="w"> </span><span class="n">each</span><span class="w"> </span><span class="n">coll,</span><span class="w"> </span><span class="n">until</span><span class="w"> </span><span class="n">any</span><span class="w"> </span><span class="n">one</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">colls</span><span class="w"> </span><span class="n">is</span><span class="w">
</span><span class="n">exhausted.</span><span class="w"> </span><span class="n">Any</span><span class="w"> </span><span class="n">remaining</span><span class="w"> </span><span class="n">items</span><span class="w"> </span><span class="n">in</span><span class="w"> </span><span class="n">other</span><span class="w"> </span><span class="n">colls</span><span class="w"> </span><span class="n">are</span><span class="w"> </span><span class="n">ignored.</span><span class="w"> </span><span class="n">Function</span><span class="w">
</span><span class="n">f</span><span class="w"> </span><span class="n">should</span><span class="w"> </span><span class="n">accept</span><span class="w"> </span><span class="n">number-of-colls</span><span class="w"> </span><span class="n">arguments.</span><span class="w"> </span><span class="n">Returns</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">transducer</span><span class="w"> </span><span class="nb">when</span><span class="w">
</span><span class="n">no</span><span class="w"> </span><span class="n">collection</span><span class="w"> </span><span class="n">is</span><span class="w"> </span><span class="n">provided.</span><span class="w">
</span><span class="n">nil</span><span class="w">
</span><span class="n">user=></span><span class="w"> </span><span class="p">(</span><span class="nf">source</span><span class="w"> </span><span class="nb">identity</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="nb">identity</span><span class="w">
</span><span class="s">"Returns its argument."</span><span class="w">
</span><span class="p">{</span><span class="no">:added</span><span class="w"> </span><span class="s">"1.0"</span><span class="w">
</span><span class="no">:static</span><span class="w"> </span><span class="n">true</span><span class="p">}</span><span class="w">
</span><span class="p">[</span><span class="n">x</span><span class="p">]</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w">
</span><span class="n">nil</span><span class="w">
</span><span class="n">user=></span><span class="w"> </span><span class="p">(</span><span class="nf">apropos</span><span class="w"> </span><span class="s">"filter"</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nf">clojure.core/filter</span><span class="w"> </span><span class="n">clojure.core/filterv</span><span class="p">)</span><span class="w">
</span><span class="n">user=></span><span class="w">
</span></code></pre></div></div>
<p>So, no, you don’t have to be online to read the docs.</p>
<p>The official docs could, IMO be considered aimed at masters, but I’d say that between the resources I’ve listed above, a beginner should also be catered to.</p>
<h3 id="i-hit-problem-x-will-i-find-help-in-the-official-docs-or-the-faq-or-the-community-or-should-i-be-putting-random-stuff-into-google">I hit problem X, Will I find help in the official docs, or the faq, or the community, or should I be putting random stuff into Google</h3>
<p>One nice thing about Clojure is that if you put random stuff into Google and you find an answer from 2007 (when Clojure was first released) it is most likely still valid, as Clojure is earily backwards compatible,
which means you can trust old advice. As for the official docs, I don’t think they’ll help you much with your day to day problems, but both the #clojure and #beginners channels are populated with friendly experts who will be able to help you on your way.</p>
<h3 id="how-do-i-debug-will-doing-anything-other-than-breaking-into-a-repl-be-like-pulling-teeth">How do I debug? Will doing anything other than “breaking into a repl” be like pulling teeth?</h3>
<p>I generally debug using <code class="language-plaintext highlighter-rouge">println</code> and also, since you generally program functionally, where you separate pure and sideffective functions, debugging in the repl is pretty sweet.
Especially since Clojure is all about <a href="https://vimeo.com/223309989">repl-driven development</a></p>
<h3 id="testing-is-unit-testing-part-of-the-core-library">Testing. Is unit testing part of the core library?</h3>
<p>Yes it is. <a href="https://clojure.github.io/clojure/clojure.test-api.html">clojure.test</a>
Clojure has great support for <a href="https://github.com/clojure/test.check">property based testing</a>, where <a href="https://www.clojure.org/about/spec">clojure.spec</a> can be used to generate values for us. Read more about that <a href="http://www.adamfrey.me/posts/datomic-prop-testing-part-1.html">here</a></p>
<p>As for test runners. Tests are just normal functions which are annotated with <code class="language-plaintext highlighter-rouge">test</code> metadata, so you can easily run them in your repl. Having said that, most of the Clojure plugins come with some test integrations, and they basically work. Otherwise, both <code class="language-plaintext highlighter-rouge">lein</code> and <code class="language-plaintext highlighter-rouge">boot</code> come with ways of running the tests in the terminal, and with <a href="https://github.com/cognitect-labs/test-runner">test.runner</a> you can make <code class="language-plaintext highlighter-rouge">clj</code> run your tests as well.
I also have to mention <a href="https://github.com/lambdaisland/kaocha">kaocha</a> which is the newest, coolest kid on the block.</p>
<h3 id="how-do-i-build-how-do-i-package-how-do-i-manage-my-environment">How do I build? How do I package? How do I manage my environment?</h3>
<p>Building is not really neccesary, as runing a Clojure program is as simple as:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>clj foo.clj
</code></pre></div></div>
<p>given that you have a file called <code class="language-plaintext highlighter-rouge">foo.clj</code> which contains a valid Clojure program.
As for the rest of the questions in this section, I believe this is answered elsewhere in the post, a part from the fact that yes, you will need to interact with other humans to figure out which of the competing libs are best for your use case.</p>
<h3 id="so-the-language-community">So… the language community</h3>
<p>Yes, you’ll have to, as already mentioned, join Yet Another Slack. There is also <a href="https://clojureverse.org">Clojureverse</a> where a lot of the Clojure community hang out.
This community has a reputation of being friendly and helpful, which I think stems from what Rich Hickey <a href="https://clojure.org/community/etiquette">wrote</a> years ago on how he wanted the community to behave.</p>
Performance tuning with tufte2019-12-08T00:00:00+00:00http://slipset.github.io/posts/Performance-tuning-with-tufte<p>I really enjoy performance tuning. It’s a bit like debugging, you are presented with a problem (this thing is too slow), and you
need to figure out where the slowness is hiding, and then how to fix it. Luckily the slowness I was working on today was reproducible
and consistent, so it was just a matter of profiling the code. Previously, and especially when working with Java, I’ve been using
<a href="yourkit.com">Yourkit</a> with great success, but this time I figured I’d try something slightly more lightweight. Enter <a href="https://github.com/ptaoussanis/tufte">tufte</a>.</p>
<p>Set up a handler like so</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">ns</span><span class="w"> </span><span class="n">my.metrics</span><span class="w">
</span><span class="p">(</span><span class="no">:require</span><span class="w"> </span><span class="p">[</span><span class="n">superstring.core</span><span class="w"> </span><span class="no">:as</span><span class="w"> </span><span class="nb">str</span><span class="p">]</span><span class="w">
</span><span class="p">[</span><span class="n">my.logger</span><span class="w"> </span><span class="no">:as</span><span class="w"> </span><span class="n">log</span><span class="p">]</span><span class="w">
</span><span class="p">[</span><span class="n">taoensso.tufte</span><span class="w"> </span><span class="no">:as</span><span class="w"> </span><span class="n">tufte</span><span class="p">]))</span><span class="w">
</span><span class="p">(</span><span class="k">defn-</span><span class="w"> </span><span class="n">nanos->ms</span><span class="w"> </span><span class="p">[</span><span class="n">elapsed-time</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nb">double</span><span class="w"> </span><span class="p">(</span><span class="nb">/</span><span class="w"> </span><span class="n">elapsed-time</span><span class="w"> </span><span class="mi">1000000</span><span class="p">)))</span><span class="w">
</span><span class="p">(</span><span class="k">defn-</span><span class="w"> </span><span class="n">wall-time-ms-elapsed</span><span class="w"> </span><span class="p">[</span><span class="n">pstats</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nb">-></span><span class="w"> </span><span class="n">pstats</span><span class="w"> </span><span class="no">:clock</span><span class="w"> </span><span class="no">:total</span><span class="w"> </span><span class="n">nanos->ms</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="k">defn-</span><span class="w"> </span><span class="n">slow?</span><span class="w"> </span><span class="p">[</span><span class="n">pstats</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nb">></span><span class="w"> </span><span class="p">(</span><span class="nf">wall-time-ms-elapsed</span><span class="w"> </span><span class="n">pstats</span><span class="p">)</span><span class="w"> </span><span class="mi">5</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="k">defn-</span><span class="w"> </span><span class="n">pretty-pstats</span><span class="w"> </span><span class="p">[</span><span class="n">pstats</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nb">str</span><span class="w"> </span><span class="s">"Function call took "</span><span class="w"> </span><span class="p">(</span><span class="nf">Math/round</span><span class="w"> </span><span class="p">(</span><span class="nf">wall-time-ms-elapsed</span><span class="w"> </span><span class="n">pstats</span><span class="p">))</span><span class="w"> </span><span class="s">" ms in total.\n\n"</span><span class="w">
</span><span class="p">(</span><span class="nf">tufte/format-pstats</span><span class="w">
</span><span class="n">pstats</span><span class="w"> </span><span class="p">{</span><span class="no">:columns</span><span class="w"> </span><span class="p">[</span><span class="no">:n-calls</span><span class="w"> </span><span class="no">:min</span><span class="w"> </span><span class="no">:max</span><span class="w"> </span><span class="no">:mean</span><span class="w"> </span><span class="no">:clock</span><span class="w"> </span><span class="no">:total</span><span class="p">]</span><span class="w">
</span><span class="no">:format-id-fn</span><span class="w"> </span><span class="nb">name</span><span class="p">})))</span><span class="w">
</span><span class="p">(</span><span class="k">defn-</span><span class="w"> </span><span class="n">slow-stuff-logger</span><span class="w">
</span><span class="p">[{</span><span class="no">:keys</span><span class="w"> </span><span class="p">[</span><span class="n">pstats</span><span class="w"> </span><span class="n">pstats-str_</span><span class="p">]}]</span><span class="w">
</span><span class="p">(</span><span class="nf">try</span><span class="w">
</span><span class="p">(</span><span class="nb">when</span><span class="w"> </span><span class="p">(</span><span class="nf">slow?</span><span class="w"> </span><span class="o">@</span><span class="n">pstats</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nf">log/info</span><span class="w"> </span><span class="p">(</span><span class="nf">pretty-pstats</span><span class="w"> </span><span class="o">@</span><span class="n">pstats</span><span class="p">)))</span><span class="w">
</span><span class="p">(</span><span class="nf">catch</span><span class="w"> </span><span class="n">Exception</span><span class="w"> </span><span class="n">e</span><span class="w">
</span><span class="p">(</span><span class="nf">log/error</span><span class="w"> </span><span class="n">e</span><span class="p">))))</span><span class="w">
</span><span class="p">(</span><span class="nf">tufte/add-handler!</span><span class="w"> </span><span class="no">:log-slow-stuff-handler</span><span class="w"> </span><span class="n">slow-stuff-logger</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>And start profiling away by replacing your normal <code class="language-plaintext highlighter-rouge">defn</code>s with <code class="language-plaintext highlighter-rouge">defnp</code>. Also, don’t forget to add a
<code class="language-plaintext highlighter-rouge">(profile {} ...)</code> around your entrypoints to the slow code.</p>
<p>What was surprising this time around was that normally in my apps, slow code is normally caused by too many accesses to the database,
or some missing indexes in said db. Today was different. The main culprit was</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">edn-conform</span><span class="w"> </span><span class="p">[</span><span class="n">spec</span><span class="w"> </span><span class="nb">doc</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">let</span><span class="w"> </span><span class="p">[</span><span class="n">edn-specs</span><span class="w"> </span><span class="p">(</span><span class="nf">specs/merge</span><span class="w"> </span><span class="no">::specs/metadata</span><span class="w"> </span><span class="n">spec</span><span class="p">)]</span><span class="w">
</span><span class="p">(</span><span class="nf">->></span><span class="w"> </span><span class="p">(</span><span class="nf">spec-tools/conform</span><span class="w"> </span><span class="n">edn-specs</span><span class="w"> </span><span class="nb">doc</span><span class="w"> </span><span class="n">edn-conforming</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nf">log-invalid</span><span class="w"> </span><span class="n">edn-specs</span><span class="w"> </span><span class="n">edn-conforming</span><span class="w"> </span><span class="nb">doc</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nf">specs/maybe-unform</span><span class="w"> </span><span class="n">spec</span><span class="p">))))</span><span class="w">
</span></code></pre></div></div>
<p>which was called on every document fetched from the database. Another fun one was this little snippet</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">eval-node</span><span class="w"> </span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="p">[</span><span class="nb">node</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">cond</span><span class="w">
</span><span class="p">(</span><span class="nf">disabled?</span><span class="w"> </span><span class="nb">node</span><span class="p">)</span><span class="w"> </span><span class="n">true</span><span class="w">
</span><span class="p">(</span><span class="nf">rule?</span><span class="w"> </span><span class="nb">node</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nf">eval-rule</span><span class="w"> </span><span class="nb">node</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nf">filter?</span><span class="w"> </span><span class="nb">node</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nf">eval-filter</span><span class="w"> </span><span class="nb">node</span><span class="p">)</span><span class="w">
</span><span class="no">:else</span><span class="w"> </span><span class="nb">node</span><span class="p">))</span><span class="w">
</span><span class="n">filter-matches-workspace</span><span class="w"> </span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="p">[</span><span class="nb">filter</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nf">walk/postwalk</span><span class="w"> </span><span class="n">eval-node</span><span class="w"> </span><span class="nb">filter</span><span class="p">))</span><span class="w">
</span></code></pre></div></div>
<p>which became quite a bit faster when changed to this:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">eval-node</span><span class="w"> </span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="p">[</span><span class="nb">node</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nb">map?</span><span class="w"> </span><span class="nb">node</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="k">cond</span><span class="w">
</span><span class="p">(</span><span class="nf">disabled?</span><span class="w"> </span><span class="nb">node</span><span class="p">)</span><span class="w"> </span><span class="n">true</span><span class="w">
</span><span class="p">(</span><span class="nf">rule?</span><span class="w"> </span><span class="nb">node</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nf">eval-rule</span><span class="w"> </span><span class="nb">node</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nf">filter?</span><span class="w"> </span><span class="nb">node</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nf">eval-filter</span><span class="w"> </span><span class="nb">node</span><span class="p">)</span><span class="w">
</span><span class="no">:else</span><span class="w"> </span><span class="nb">node</span><span class="p">)</span><span class="w">
</span><span class="nb">node</span><span class="p">)</span><span class="w">
</span><span class="n">filter-matches-workspace</span><span class="w"> </span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="p">[</span><span class="nb">filter</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nf">walk/postwalk</span><span class="w"> </span><span class="n">eval-node</span><span class="w"> </span><span class="nb">filter</span><span class="p">))</span><span class="w">
</span></code></pre></div></div>
Tools Analyzer2019-12-08T00:00:00+00:00http://slipset.github.io/posts/Tools-analyzer<p>One of the hardest things of trying to write a post each day is to start again once you’ve missed a day or two (as I have).
Yesterday I decided to prioritize writing a patch to <a href="https://github.com/clojure/tools.analyzer.jvm">tools.analyzer.jvm</a> that I’d
wanted to submit for quite some time.</p>
<p>At work, we use <a href="https://github.com/jonase/eastwood">Eastwood</a> for linting. Having a 60KLOC pluss code base, linting takes some time,
so I decided to look into where it spent its time. So this summer(!) I hooked it up to Yourkit, and found that Eastwood spends most
of its time analyzing files, and to my surprise, the hotspot seems to be <a href="https://github.com/clojure/tools.analyzer.jvm/blob/master/src/main/clojure/clojure/tools/analyzer/jvm.clj#L56">here</a>.</p>
<p>Since Eastwood inlines its dependencies such as this, it was quite trivial to play around with it and add some debug statements,
and I was quite surprised to see that tools.analyser was “constantly” building a new ns-map.</p>
<p>Reading a bit more code, you find <a href="https://github.com/clojure/tools.analyzer.jvm/blob/master/src/main/clojure/clojure/tools/analyzer/jvm.clj#L150">this</a>,
which basically says “Whenever you analyze a macro, you need to rebuild the ns-map”. The reason for this of course, is that a
macro can do basically anything, including altering the ns-object (which is mutable) and launch missiles. But there are some optimizations to be had.
There are a bunch of macros in Clojure core which are frequently used, which do not alter the ns-object. So we could just enumerate them
and check if the macro was one of those, and in that case, elide the rebuilding of the ns-map.</p>
<p>So this lead me to create this <a href="https://clojure.atlassian.net/browse/TANAL-130">ticket</a>.</p>
<p>And yesterday, I started going down another rabbit hole, which is somewhat related. <a href="https://github.com/clojure-emacs/refactor-nrepl">refactor-nrepl</a>
has functionality to find usages of a Clojure symbol in your project. This is quite handy. Unfortunatly this is b0rken on our
project for some reason, probably related to <a href="https://github.com/clojure-emacs/refactor-nrepl/issues/245">this</a> issue.</p>
<p>And digging through it yesterday, I found that when I commented out <a href="https://github.com/clojure-emacs/refactor-nrepl/blob/master/src/refactor_nrepl/analyzer.clj#L53">this</a> line,
I didn’t get the OOM anymore, which kind of makes sense, since I could imagine the size of the complete AST for our project to be, well, significant.</p>
<p>And why is the cacne in place? Probably because tools.analyzer.jvm is kind of slow.</p>
<p>So, there you go.</p>
Code over configuration2019-12-05T00:00:00+00:00http://slipset.github.io/posts/Code-over-configuration<p>So yesterday, life got the better part of me, so I didn’t prioritize writing a post, but today I’m on it again.</p>
<p>One of my great frustrations is how we try to “configure” things, using languages like XML, JSON, and YAML.
This approach works great for smaller things, but once you’re into something of significant size,
these languages show their limitations: No loops, no conditionals, no variables, so string interpolation is bolted on.</p>
<p>A long time ago <a href="https://twitter.com/thattommyhall">Tommy Hall</a> gave a great <a href="https://vimeo.com/100425264">presentation</a>
where he argues you should build DSLs in layers, so you always have the ability to drop down a level if you need to do something more
complicated. Tommy uses examples from teaching kids in his talk, and it resonates well with me at the moment, as my kids are
learning <a href="https://scratch.mit.edu">Scratch</a> at school these days. Because while Scratch is great, I don’t see how you evolve from
Scratch to “real programming”. There is <a href="https://tosh.blob.codes/app/">tosh</a>, which is promising, but I’d love to see something like
that <em>integrated</em> in Scratch itself.</p>
<p>Tying this back to infrastructure as code, I’m really happy to <a href="https://www.youtube.com/watch?v=TbDmupZyuXk">see</a>.
<a href="https://github.com/StediInc/cdk-clj">clj-cdk</a> seems really promising, allthough I could imagine it’d be hard to get ops-people
away from YAML.</p>
Christin Gorman2019-12-03T00:00:00+00:00http://slipset.github.io/posts/Christin-Gorman<p>This morning, a tweet came across my time line:</p>
<blockquote class="twitter-tweet">
<p lang="en" dir="ltr">
Strongly recommended for all the people who position themselves as a software professionals. Thanks again
<a href="https://twitter.com/ChristinGorman?ref_src=twsrc%5Etfw">@ChristinGorman</a>
<a href="https://t.co/DMY4Fsc1vm">https://t.co/DMY4Fsc1vm</a>
</p>
— Pavel Savinov (@Pavel_Savinov)
<a href="https://twitter.com/Pavel_Savinov/status/1201754123055570944?ref_src=twsrc%5Etfw">December 3, 2019</a>
</blockquote>
<p>and watching the talk I was reminded of what a great speaker Christin is, in my opinion she’s clearly one of Norways best.</p>
<p>But as you’ll see from the talk, she is not only a great speaker, she also has strong opinions, many of which she expresses
in her blog over <a href="https://qristin.wordpress.com">here</a> (mainly in Norwegian, where her focus lately has been the ridiculous
amount of money that the public sector in Norway is throwing after large consultancies running monster projects which we know
are doomed to fail even before they’re started.</p>
<p>So as I was watching the video I linked to over, I was thinking, maybe todays Advent of Parens post should be a post
saying that I basically think she is really damn impressive!</p>
<p>And then, when I come home, I see this tweet</p>
<blockquote class="twitter-tweet">
<p lang="en" dir="ltr">
Current status:
<br />
Being told my opinions don't matter because I'm irrational and don't know what I'm talking about,
I need to read the documentation, blablabla.<br />How's your day going?
</p>
— Christin Gorman (@ChristinGorman)
<a href="https://twitter.com/ChristinGorman/status/1201866960172134400?ref_src=twsrc%5Etfw">December 3, 2019</a>
</blockquote>
<p>Which simply makes me want to say, hang in there Christin! You are the one who knows what you’re talking about!</p>
<p>And for the rest of you, if you’re ever in need of a speaker at your conference, or a strong voice in your panel,
you know who to contact.</p>
Devops?2019-12-02T00:00:00+00:00http://slipset.github.io/posts/Dev-ops<p>Last Tuesday, <a href="https://www.amazon.com/Unicorn-Project-Developers-Disruption-Thriving-ebook/dp/B07QT9QR41">The Unicorn Project</a> was finally launched.
This followup to <a href="https://www.amazon.com/Phoenix-Project-DevOps-Helping-Business/dp/0988262509">The Phoenix Project</a> doesn’t disappoint,
and is as much a must read as its predecessor.</p>
<p>There are a couple of things I’d like to mention. The first thing is that the author <a href="https://twitter.com/RealGeneKim">Gene Kim</a> has
<a href="https://itrevolution.com/love-letter-to-clojure-part-1/">really</a> fallen in love with <a href="https://www.youtube.com/watch?v=5mbp3SEha38">Clojure</a>
and applies the principles of Clojure to the larger organization. As a side note, I’m wondering if The Unicorn Project will spawn
a new interest in Clojure.</p>
<p>The second thing, and it’s more related to me, is the term “devops”. In my 25 years of working, I’ve always identified as a developer.
Sure, I’ve configured my boxes, I know my way around bash, and I could probably run a small production enviroment, but I’ve never
considered myself a true ops person. But I don’t reckognize myself in the stereotypical developer as he is portrayed in these two books,
and in the few jobs I’ve had where I have not been allowed to take responsability for my own code in production has been the most frustrating.
In fact, working in places where we’ve been forced to “throw code over the fence” to ops have been the worst places I worked.</p>
<p>So, I guess what I’m getting at is that to me the term “devops” is a bit too much focussed on the ops part, and that setting up
CI servers, monitoring, and having access to logs is just all part of development.</p>
<p>Spinning up new servers in AWS, configuring network zones, and all that stuff is better left to the pros in ops :)
Especially when it’s all done in <a href="https://www.youtube.com/watch?v=TbDmupZyuXk">YAML</a></p>
Problem Solving2019-12-01T00:00:00+00:00http://slipset.github.io/posts/Problem-solving<p>So <a href="https://lambdaisland.com/blog/2019-11-25-advent-of-parens">Lambda Island</a> has this challenge of writing a blog post
for every day of December until the 24th. I figure I’ll give it a shot.</p>
<p>This will most certainly be in the spirit of not letting perfect be the enemy of the good, so consider yourself warned.</p>
<p>What I want to mention briefly today is one of the less obvious ways that Clojure has helped me become a better programmer.
If you’ve ever tried to encourage the Clojure core to implement your most favorite feature, you’ve most probably had the
feeling of being shot down with these three questions:</p>
<p>1) What problem are you trying to solve
2) What are some approaches to solving this problem
3) What are the pros and cons of these solutions.</p>
<p>And you might feel a bit annoyed, since to you, the problem is obvious given your solution, and of course you’ve already
figured out the best possible solution.</p>
<p>Lately, I’ve found myself being the annoying person always asking these three questions, and if nothing else, it
teaches me a lot more about the problem to be solved, and it enables me to write better software when that time comes.</p>
<p>I guess this is closely related to <a href="https://en.wikipedia.org/wiki/Five_whys">The five whys</a></p>
<p>And that’s about it for today.</p>
On others code2018-07-22T20:17:35+00:00http://slipset.github.io/posts/On-others-code<p><a href="https://www.twitter.com/@jhannes">Johannes Brodwall</a>
posted <a href="http://johannesbrodwall.com/2018/07/01/dirty-code-monday/">Dirty Code Monday</a>
on his, eh, blog, to show some of the dirty code he let through, which he otherwise
would not. In this he also highlighted what about the code he thought was dirty.</p>
<p>This lead me to make an unfortunate tweet</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">What scares me most about the code you’re showing is how tightly coupled the logic is to its environment. A bunch of the values you use in your functions could easily be passed as parameters.</p>— Erik Assum (@slipset) <a href="https://twitter.com/slipset/status/1013704292862169088?ref_src=twsrc%5Etfw">July 2, 2018</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>Unfortunate, because I was critizising something that was already pointed out as bad.</p>
<p>Anyways, I thought I’d try to enumerate what I found smelly about the code.
This is kind of hard, since I no longer write Java, and I most certainly don’t
know the surroundings of the code in question.</p>
<p>But let’s jump into it.</p>
<p>For the first example, I think I would have pulled the <code class="language-plaintext highlighter-rouge">if</code>-test out of this function,
and made it accept only a <code class="language-plaintext highlighter-rouge">HttpsURLConnection</code>:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">setupClientCertificate</span><span class="o">(</span><span class="nc">HttpsURLConnection</span> <span class="n">httpsURLConnection</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">IOException</span> <span class="o">{</span>
<span class="nc">HttpsURLConnection</span> <span class="n">httpsURLConnection</span> <span class="o">=</span> <span class="o">(</span><span class="nc">HttpsURLConnection</span><span class="o">)</span> <span class="n">httpURLConnection</span><span class="o">;</span>
<span class="k">try</span> <span class="o">{</span>
<span class="c1">// TODO: Find out if SSLContext.getSocketFactory is expensive an if so, cache</span>
<span class="n">httpsURLConnection</span><span class="o">.</span><span class="na">setSSLSocketFactory</span><span class="o">(</span><span class="n">createSocketFactory</span><span class="o">(</span><span class="n">keyStorePath</span><span class="o">(),</span> <span class="n">keystorePassword</span><span class="o">(),</span> <span class="n">trustStorePath</span><span class="o">()));</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">KeyStoreException</span> <span class="o">|</span> <span class="nc">CertificateException</span> <span class="o">|</span> <span class="nc">NoSuchAlgorithmException</span> <span class="o">|</span> <span class="nc">UnrecoverableKeyException</span> <span class="o">|</span> <span class="nc">KeyManagementException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">RuntimeException</span><span class="o">(</span><span class="n">e</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Now this code is somewhat logic free, and it’s up to the caller to check if we’re using
client certs and make the cast. Still not happy with it though, but I can’t really put
my finger on what bugs me.</p>
<p>For the second example, my biggest problem is that, at least the last time I programmed Java,
you needed a mock for <code class="language-plaintext highlighter-rouge">HttpServletRequest</code> to set values on it. And I really dislike mocks.
Therefore, I’d like to rewrite it as</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">private</span> <span class="kt">boolean</span> <span class="nf">isValidRequest</span><span class="o">(</span><span class="nc">String</span> <span class="n">method</span><span class="o">,</span> <span class="nc">String</span> <span class="n">pathInfo</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">List</span><span class="o"><</span><span class="nc">String</span><span class="o">></span> <span class="n">validPaths</span> <span class="o">=</span> <span class="n">method</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="s">"GET"</span><span class="o">)</span> <span class="o">?</span> <span class="nc">Configuration</span><span class="o">.</span><span class="na">validGetPaths</span><span class="o">()</span> <span class="o">:</span> <span class="nc">Configuration</span><span class="o">.</span><span class="na">validPostPaths</span><span class="o">();</span>
<span class="k">return</span> <span class="n">pathInfo</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">&&</span> <span class="n">validPaths</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">anyMatch</span><span class="o">(</span><span class="nl">pathInfo:</span><span class="o">:</span><span class="n">startsWith</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Now this method has two <code class="language-plaintext highlighter-rouge">String</code> arguments, not to happy about that either.</p>
<p>Guess the <code class="language-plaintext highlighter-rouge">method</code> should have been an <code class="language-plaintext highlighter-rouge">Enum</code>.</p>
<p>Also not overly enthused about the whole <code class="language-plaintext highlighter-rouge">Configuration</code> bit. I guess I would have rewritten to
<code class="language-plaintext highlighter-rouge">Configuration.validPaths(method);</code>, which would leave us with:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">private</span> <span class="kt">boolean</span> <span class="nf">isValidRequest</span><span class="o">(</span><span class="nc">HttpMethod</span> <span class="n">method</span><span class="o">,</span> <span class="nc">String</span> <span class="n">pathInfo</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">List</span><span class="o"><</span><span class="nc">String</span><span class="o">></span> <span class="n">validPaths</span> <span class="o">=</span> <span class="nc">Configuration</span><span class="o">.</span><span class="na">validPaths</span><span class="o">(</span><span class="n">method</span><span class="o">);</span>
<span class="k">return</span> <span class="n">pathInfo</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">&&</span> <span class="n">validPaths</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">anyMatch</span><span class="o">(</span><span class="nl">pathInfo:</span><span class="o">:</span><span class="n">startsWith</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Which, in which you could let the caller do the <code class="language-plaintext highlighter-rouge">validPaths</code> thingy, so it ends up around</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">private</span> <span class="kt">boolean</span> <span class="nf">isValidRequest</span><span class="o">(</span><span class="nc">List</span><span class="o"><</span><span class="nc">String</span><span class="o">></span> <span class="n">validPaths</span><span class="o">,</span> <span class="nc">String</span> <span class="n">pathInfo</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">pathInfo</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">&&</span> <span class="n">validPaths</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">anyMatch</span><span class="o">(</span><span class="nl">pathInfo:</span><span class="o">:</span><span class="n">startsWith</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>
<p>And you have a function which is quite testable, and does its one thing.</p>
<p>Anyways, thanks for posting this Johannes, it made me think.</p>
On Clojure Hiring2018-03-10T00:00:00+00:00http://slipset.github.io/posts/On-Clojure-Hiring<h1 id="on-hiring-clojure-programmers">On hiring Clojure programmers</h1>
<p>I’ve been in a position for the last five years where I’ve been involved in the hiring process at various
companies. As an architect/senior-dev, I’ve been involved in writing the job-descriptions, reading resumes,
interviewing candidates, and onboarding the ones that got through. And this for positions as Javascript, Java,
and Clojure programmers, as well as general purpose contractors.</p>
<p>When it comes to hiring, at least here in Oslo, Norway, most developers seem happy in their current jobs.
Now, most hiring processes are set up as if there were houndreds of qualified applicants for every position
and that the purpose of the process is to find the very best of that log.</p>
<p>Unfortunatly the reality is quite different. It seems like you’ll be lucky if you manage to get at least one somewhat
qualified applicant. This means that the moment you understand that this is the candidate, you need to start convincing
the candidate that the position you’re offering is worth the hassle of changing jobs.</p>
<h1 id="is-it-easy-to-hire-clojure-devs">Is it easy to hire Clojure devs?</h1>
<p>So the question is, is it easier to hire for a Clojure position than for a, say, Java position. To me it seems like,
with the current job-marked, it doesn’t really matter. It’s hard getting good people any how. The one thing I can say though,
is that I have a feeling we’re getting fewer, but more qualified applicants for the Clojure positions. Which is a good thing,
as it means less work on the people doing the hiring. Now, if you open up to remote workers, it seems easier to get a hold
of people.</p>
<h1 id="how-hard-is-it-to-bring-a-non-clojure-programmer-up-to-speed">How hard is it to bring a non-Clojure programmer up to speed?</h1>
<p>I’ve found that bringing people up to speed in Clojure is not very hard. I think it’s important to have some experienced
Clojure programmers around to mentor the new hires. Tools like Figwheel and Cursive/Intellij makes the transition easier.
Also, it’s much easier for someone with limited Clojure experience to join an already up and running project, than to start
a green field effort where she has to pick libraries and set up projects and such.</p>
<h1 id="whats-the-retention-for-clojure-devs">What’s the retention for Clojure devs?</h1>
<p>Personally, I’m stuck with Clojure for quite some time, as I cannot imagine what other language I’d be as happy in.
having said that, I’ve had colleagues who were quite happy when they went back to the languages they were familiar with,
be it Javascript or Python. As a side note. The fact that a company uses Clojure might be an indicator that the company has
values that are developer friendly, and as such it might be the culture that makes people stay as much as the language itself.</p>
Last seven days of Clojure2017-05-25T00:00:00+00:00http://slipset.github.io/posts/last-seven-days-of-Clojure<p>Not really sure what this is, but it might just be something I’m starting. It’s basically an outsiders view of what’s
going on inside Clojure. I’ll be looking at what tickets moved in the Clojure Jira, the last seven days, and also comment on
any commits done to the github-repo.</p>
<p>Anyways. The issues updated the last seven days were:</p>
<ul>
<li><a href="https://dev.clojure.org/jira/browse/CLJ-2060">CLJ-2060</a> Add support for undefining a spec</li>
<li><a href="https://dev.clojure.org/jira/browse/CLJ-2082">CLJ-2082</a> Improve documentation of clojure.walk/walk</li>
<li><a href="https://dev.clojure.org/jira/browse/CLJ-2163">CLJ-2163</a> Add test for var serialization</li>
<li><a href="https://dev.clojure.org/jira/browse/CLJ-2164">CLJ-2164</a> Case fails when a singel clause with an empty test seq is used</li>
<li><a href="https://dev.clojure.org/jira/browse/CLJ-2165">CLJ-2165</a> #clojure/var tag for transmitting var identity</li>
<li><a href="https://dev.clojure.org/jira/browse/CLJ-2166">CLJ-2166</a> Instrument exception doesn’t contain funciton name in ex-data</li>
</ul>
<p>As you can see from the issue-numbers, the last four of these were new issues. So starting with the old ones, what happened?</p>
<h2 id="add-support-for-undefining-a-spec">Add support for undefining a spec</h2>
<p>As the issue states, there is currently no way to remove a spec from the spec registry, and this issue contains the patch to solve
that. The proposed solution is to let <code class="language-plaintext highlighter-rouge">s/def</code> accept <code class="language-plaintext highlighter-rouge">nil</code> to “clear” a spec. The patch basically ads an if-test to <code class="language-plaintext highlighter-rouge">def-impl</code> and
<code class="language-plaintext highlighter-rouge">dissoc</code>s the key from the registry if the spec is <code class="language-plaintext highlighter-rouge">nil</code>. I guess one could imagine some documentation to be updated along with this.</p>
<p>This weeks update on the issue is that it’s now added to the Clojure 1.9 release so it can be considered for that release.</p>
<h2 id="improve-documentation-of-clojurewalkwalk">Improve documentation of clojure.walk/walk</h2>
<p>This issue, reported by David Cook on the 11th of December 2016 states that</p>
<blockquote>
<p>The documentation for the <code class="language-plaintext highlighter-rouge">clojure.walk</code> module isn’t clear on which methods recurse through data structures, and which only
operate on the outermost layer.</p>
</blockquote>
<p>To this Martin Clausen commented:</p>
<blockquote>
<p>The potential recursive behaviour of clojure.walk/walk depends on the inner function passed to it and is
not inherent to clojure.walk/walk itself. If you look at the source code for clojure.walk/prewalk and
clojure.walk/postwalk, they are both implemented using walk, but passed a recursive inner function.</p>
</blockquote>
<p>I’m not sure if I’m supposed to comment on this, but in my opinion, this should be closed unless the reporter comes up with a
proposal for new documentation.</p>
<h2 id="add-test-for-var-serialization">Add test for var serialization</h2>
<p>Alex Miller recently posted on the <a href="https://groups.google.com/forum/#!topic/clojure-dev/xfFmrVudD98">Clojure Dev mailing list</a> a
RFC on var printing. This issue, which already contains a patch which, reading throught it quickly, seems to be a test to make sure
regressions don’t happen while iplementing</p>
<h2 id="clojurevar-tag-for-transmitting-var-identity">#clojure/var tag for transmitting var identity</h2>
<p>This issue, slated for 1.9 states that “Currently one can’t send vars around in edn” The proposal is to use <code class="language-plaintext highlighter-rouge">#clojure.var</code> for a tag.
Alex has added a patch so people can start playing with this to see if (or how) it might break existing code.</p>
<p>The patch adds a new dynamic var <code class="language-plaintext highlighter-rouge">*print-var-tag*</code>:</p>
<blockquote>
<p>When set to logical true, vars will be printed with the #clojure/var
tagged literal, otherwise vars print with the #’ reader macro.
– <cite>clojure.core/<em>print-var-tag</em> </cite></p>
</blockquote>
<p>It also defines a new reader, <code class="language-plaintext highlighter-rouge">var-reader</code> which is called when we see <code class="language-plaintext highlighter-rouge">#clojure/var</code>.
For the printing part, there’s now an if test in place which switches on <code class="language-plaintext highlighter-rouge">*print-var-tag*</code>, and <code class="language-plaintext highlighter-rouge">print-dup</code> now prints <code class="language-plaintext highlighter-rouge">#clojure/var</code>
unconditionally.</p>
<h2 id="case-fails-when-a-single-single-clause-with-an-empty-test-seq-is-used">Case fails when a single single clause with an empty test seq is used</h2>
<p>Chris Bloom reports</p>
<blockquote>
<p>I would expect</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">case</span><span class="w"> </span><span class="mi">1</span><span class="w">
</span><span class="p">()</span><span class="w"> </span><span class="no">:a</span><span class="w">
</span><span class="no">:none</span><span class="p">)</span><span class="w">
</span></code></pre></div> </div>
<p>to return <code class="language-plaintext highlighter-rouge">:none</code> instead if tails with an uniformative exception: “Unhandled clojure.lang.ArityException: Wrong number of args (-2) passed to: core/max”</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w"> </span><span class="p">(</span><span class="nf">case</span><span class="w"> </span><span class="mi">1</span><span class="w">
</span><span class="p">()</span><span class="w"> </span><span class="no">:a</span><span class="p">)</span><span class="w">
</span></code></pre></div> </div>
<p>to fail with an <code class="language-plaintext highlighter-rouge">IllegalArgumentException</code> but instead this fails with the same exeption as above.</p>
</blockquote>
<p>Also, Chris states,</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">case</span><span class="w"> </span><span class="mi">1</span><span class="w">
</span><span class="p">()</span><span class="w"> </span><span class="no">:a</span><span class="w">
</span><span class="mi">2</span><span class="w"> </span><span class="no">:b</span><span class="w">
</span><span class="no">:none</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>returns <code class="language-plaintext highlighter-rouge">none</code> as expected.</p>
<p>The attatched <a href="https://dev.clojure.org/jira/secure/attachment/16797/0001.patch">patch</a>, which is a bit too involved for me to go through
adds both a solution and tests.</p>
<p>The comments contain a discussion around some of the edge cases in, well, case.</p>
<h2 id="instrumentation-exception-doesnt-contain-function-name-in-ex-data">Instrumentation exception doesn’t contain function name in ex-data</h2>
<p>This issue, reported by James Reeves, states that</p>
<blockquote>
<p>When an instrumented function fails, it throws an IExceptionInfo.
The ex-data of this exception contains the arguments that failed, but not the function that was called.</p>
</blockquote>
<p>and asks for an extra key like <code class="language-plaintext highlighter-rouge">clojure.spec.alpha/fn</code> or <code class="language-plaintext highlighter-rouge">clojure.spec.alpha/var</code>. No patch on this one yet.</p>
Add bin/lein to VCS2017-03-14T00:00:00+00:00http://slipset.github.io/posts/check-in-lein<p>So, <a href="https://twitter.com/technomancy">@technomancy</a> asked on twitter:</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Leiningen users: how do you feel about checking the bin/lein shell script into project repositories so everyone uses the exact same thing?</p>— technomancy (@technomancy) <a href="https://twitter.com/technomancy/status/841448456111570944">March 14, 2017</a></blockquote>
<script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>My answer is no, I don’t see the need for that, but I thought I’d elaborate.</p>
<p>I think the <code class="language-plaintext highlighter-rouge">project.clj</code>s that I’ve made/used have been fairly simple stuff, mainly declaring the dependencies of the project.
Apart, of course, from the projects that use Clojurescript and <a href="https://github.com/bhauman/lein-figwheel">figwheel</a>, which tend to
become a mess of something that feels like it works more out of a coincidence than anything else.</p>
<p>But I guess my main point is that, the way I use lein, is that the main usage is very straight forward, and anything else is handeled
by plugins which are declared in the <code class="language-plaintext highlighter-rouge">project.clj</code> itself with the corresponding versions.</p>
<p>If I were to ask for anything, I guess it would be to be able to specify the lein version exactly in the <code class="language-plaintext highlighter-rouge">project.clj</code>
and that lein bootstrapped itself with that exact version.</p>
<p>Not that that would solve any problem I currently have.</p>
<p>I’d rather have Clojurescript/figwheel build with a simple setup. and not</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="no">:dev</span><span class="w"> </span><span class="p">{</span><span class="no">:source-paths</span><span class="w"> </span><span class="p">[</span><span class="s">"env/dev/clj"</span><span class="p">]</span><span class="w">
</span><span class="no">:dependencies</span><span class="w"> </span><span class="p">[[</span><span class="n">figwheel-sidecar</span><span class="w"> </span><span class="s">"0.5.8"</span><span class="p">]</span><span class="w">
</span><span class="p">[</span><span class="n">com.cemerick/piggieback</span><span class="w"> </span><span class="s">"0.2.1"</span><span class="p">]</span><span class="w">
</span><span class="p">[</span><span class="n">devcards</span><span class="w"> </span><span class="s">"0.2.0-8"</span><span class="p">]</span><span class="w">
</span><span class="p">[</span><span class="n">binaryage/devtools</span><span class="w"> </span><span class="s">"0.8.3"</span><span class="p">]]</span><span class="w">
</span><span class="no">:repl-options</span><span class="w"> </span><span class="p">{</span><span class="no">:init-ns</span><span class="w"> </span><span class="n">core.my-ns</span><span class="p">}</span><span class="w">
</span><span class="no">:plugins</span><span class="w"> </span><span class="p">[[</span><span class="n">lein-figwheel</span><span class="w"> </span><span class="s">"0.5.8"</span><span class="p">]]</span><span class="w">
</span><span class="c1">;;Having source-paths here helps Leiningen IntelliJ plugin recognize source roots after a refresh</span><span class="w">
</span><span class="no">:cljsbuild</span><span class="w"> </span><span class="p">{</span><span class="no">:builds</span><span class="w"> </span><span class="p">{</span><span class="no">:dev</span><span class="w">
</span><span class="p">{</span><span class="no">:source-paths</span><span class="w">
</span><span class="p">[</span><span class="s">"env/dev/cljs/foo"</span><span class="w">
</span><span class="s">"src/cljs/foo"</span><span class="w">
</span><span class="s">"test/cljs"</span><span class="p">]</span><span class="w">
</span><span class="no">:compiler</span><span class="w"> </span><span class="p">{</span><span class="no">:preloads</span><span class="w"> </span><span class="p">[</span><span class="n">devtools.preload</span><span class="p">]}}}}}</span><span class="w">
</span><span class="no">:test</span><span class="w"> </span><span class="p">{</span><span class="no">:plugins</span><span class="w"> </span><span class="p">[</span><span class="c1">;; Runs cljs-tests in various browsers</span><span class="w">
</span><span class="p">[</span><span class="n">lein-doo</span><span class="w"> </span><span class="s">"0.1.6"</span><span class="p">]]</span><span class="w">
</span><span class="no">:cljsbuild</span><span class="w"> </span><span class="p">{</span><span class="no">:builds</span><span class="w"> </span><span class="p">{</span><span class="no">:test</span><span class="w"> </span><span class="p">{</span><span class="no">:source-paths</span><span class="w"> </span><span class="p">[</span><span class="s">"src/cljs/foo"</span><span class="w"> </span><span class="s">"src/cljs/common"</span><span class="w"> </span><span class="s">"test/cljs"</span><span class="p">]</span><span class="w">
</span><span class="no">:compiler</span><span class="w"> </span><span class="p">{</span><span class="no">:output-to</span><span class="w"> </span><span class="s">"resources/public/js/out/testable.js"</span><span class="w">
</span><span class="no">:main</span><span class="w"> </span><span class="n">foo.test-runner</span><span class="w">
</span><span class="no">:foreign-libs</span><span class="w"> </span><span class="p">[{</span><span class="no">:file</span><span class="w"> </span><span class="s">"resources/public/js/lib/jquery-1.11.3.min.js"</span><span class="w">
</span><span class="no">:provides</span><span class="w"> </span><span class="p">[</span><span class="s">"jquery.core"</span><span class="p">]}</span><span class="w">
</span><span class="p">{</span><span class="no">:file</span><span class="w"> </span><span class="s">"resources/public/js/lib/chartist.min.js"</span><span class="w">
</span><span class="no">:provides</span><span class="w"> </span><span class="p">[</span><span class="s">"chartist.core"</span><span class="p">]}</span><span class="w">
</span><span class="p">{</span><span class="no">:file</span><span class="w"> </span><span class="s">"resources/public/js/lib/d3.min.js"</span><span class="w">
</span><span class="no">:provides</span><span class="w"> </span><span class="p">[</span><span class="s">"d3"</span><span class="p">]}]</span><span class="w">
</span><span class="no">:externs</span><span class="w"> </span><span class="p">[</span><span class="s">"externs/jquery-1.9.js"</span><span class="p">]</span><span class="w">
</span><span class="no">:optimizations</span><span class="w"> </span><span class="no">:none</span><span class="p">}}}}}</span><span class="w">
</span><span class="no">:uberjar</span><span class="w"> </span><span class="p">{</span><span class="no">:env</span><span class="w"> </span><span class="p">{</span><span class="no">:browser-caching</span><span class="w"> </span><span class="p">{</span><span class="s">"text/javascript"</span><span class="w"> </span><span class="mi">604800</span><span class="w">
</span><span class="s">"text/html"</span><span class="w"> </span><span class="mi">0</span><span class="p">}}</span><span class="w">
</span><span class="no">:hooks</span><span class="w"> </span><span class="p">[</span><span class="n">leiningen.sass</span><span class="p">]</span><span class="w">
</span><span class="no">:prep-tasks</span><span class="w"> </span><span class="p">[</span><span class="s">"git-info-edn"</span><span class="w"> </span><span class="s">"compile"</span><span class="w"> </span><span class="p">[</span><span class="s">"with-profile"</span><span class="w"> </span><span class="s">"uberjar"</span><span class="w"> </span><span class="s">"cljsbuild"</span><span class="w"> </span><span class="s">"once"</span><span class="p">]]</span><span class="w">
</span><span class="no">:omit-source</span><span class="w"> </span><span class="n">true</span><span class="w">
</span><span class="no">:aot</span><span class="w"> </span><span class="no">:all</span><span class="w">
</span><span class="no">:main</span><span class="w"> </span><span class="n">foo.server</span><span class="w">
</span><span class="no">:sass</span><span class="w"> </span><span class="p">{</span><span class="no">:style</span><span class="w"> </span><span class="no">:compressed</span><span class="p">}</span><span class="w">
</span><span class="no">:cljsbuild</span><span class="w"> </span><span class="p">{</span><span class="no">:builds</span><span class="w"> </span><span class="p">{</span><span class="no">:admin</span><span class="w"> </span><span class="p">{</span><span class="no">:source-paths</span><span class="w"> </span><span class="p">[</span><span class="s">"src/cljs/admin"</span><span class="w"> </span><span class="s">"src/cljs/common"</span><span class="p">]</span><span class="w">
</span><span class="no">:figwheel</span><span class="w"> </span><span class="n">false</span><span class="w">
</span><span class="no">:compiler</span><span class="w">
</span><span class="p">{</span><span class="no">:output-to</span><span class="w"> </span><span class="s">"resources/public/js/admin.js"</span><span class="w">
</span><span class="no">:output-dir</span><span class="w"> </span><span class="s">"resources/public/js/admin-out"</span><span class="w">
</span><span class="no">:source-map-timestamp</span><span class="w"> </span><span class="n">true</span><span class="w">
</span><span class="no">:optimizations</span><span class="w"> </span><span class="no">:advanced</span><span class="w">
</span><span class="no">:externs</span><span class="w"> </span><span class="p">[</span><span class="s">"externs/jquery-1.9.js"</span><span class="w">
</span><span class="s">"resources/public/js/lib/bootstrap.min.js"</span><span class="p">]</span><span class="w">
</span><span class="no">:closure-warnings</span><span class="w"> </span><span class="p">{</span><span class="no">:externs-validation</span><span class="w"> </span><span class="no">:off</span><span class="p">}</span><span class="w">
</span><span class="no">:pretty-print</span><span class="w"> </span><span class="n">false</span><span class="p">}}</span><span class="w">
</span><span class="no">:foo</span><span class="w"> </span><span class="p">{</span><span class="no">:source-paths</span><span class="w"> </span><span class="p">[</span><span class="s">"env/prod/cljs/foo"</span><span class="w"> </span><span class="s">"src/cljs/foo"</span><span class="w"> </span><span class="s">"src/cljs/common"</span><span class="p">]</span><span class="w">
</span><span class="no">:figwheel</span><span class="w"> </span><span class="n">false</span><span class="w">
</span><span class="no">:compiler</span><span class="w">
</span><span class="p">{</span><span class="no">:output-to</span><span class="w"> </span><span class="s">"resources/public/js/foo.js"</span><span class="w">
</span><span class="no">:output-dir</span><span class="w"> </span><span class="s">"resources/public/js/foo-out"</span><span class="w">
</span><span class="no">:source-map-timestamp</span><span class="w"> </span><span class="n">true</span><span class="w">
</span><span class="no">:optimizations</span><span class="w"> </span><span class="no">:advanced</span><span class="w">
</span><span class="no">:externs</span><span class="w"> </span><span class="p">[</span><span class="s">"externs/jquery-1.9.js"</span><span class="w">
</span><span class="s">"resources/public/js/lib/bootstrap.min.js"</span><span class="w">
</span><span class="s">"resources/public/js/lib/chartist.min.js"</span><span class="w">
</span><span class="s">"resources/public/js/lib/moment.min.js"</span><span class="w">
</span><span class="s">"resources/public/js/lib/daterangepicker.min.js"</span><span class="w">
</span><span class="s">"resources/public/js/lib/d3.min.js"</span><span class="w">
</span><span class="s">"resources/public/js/lib/nv.d3.min.js"</span><span class="w">
</span><span class="s">"resources/public/js/lib/d3_sankey.js"</span><span class="p">]</span><span class="w">
</span><span class="no">:closure-warnings</span><span class="w"> </span><span class="p">{</span><span class="no">:externs-validation</span><span class="w"> </span><span class="no">:off</span><span class="p">}</span><span class="w">
</span><span class="no">:pretty-print</span><span class="w"> </span><span class="n">false</span><span class="p">}}}}}})</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>Of course, I’m only complaining and have no real solution to this problem, but I’d love to see something like</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w"> </span><span class="no">:plugins</span><span class="w"> </span><span class="p">[[</span><span class="n">lein-figwheel</span><span class="w"> </span><span class="s">"0.5.8"</span><span class="p">]</span><span class="w">
</span></code></pre></div></div>
<p>and that all magic with sidecars and piggiebackers would be taken care of, as would picking up of externs and stuff which
I would have to place in some directory dictated by <code class="language-plaintext highlighter-rouge">figwheel/cljsbuild</code></p>
<p>So, rewriting my <code class="language-plaintext highlighter-rouge">project.clj</code> above, I’d like to see something like:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w"> </span><span class="no">:plugins</span><span class="w"> </span><span class="p">[[</span><span class="n">lein-figwheel</span><span class="w"> </span><span class="s">"0.5.8"</span><span class="p">]]</span><span class="w">
</span><span class="no">:profiles</span><span class="w"> </span><span class="p">{</span><span class="no">:dev</span><span class="w"> </span><span class="p">{</span><span class="no">:source-paths</span><span class="w"> </span><span class="p">[</span><span class="s">"env/dev/clj"</span><span class="p">]</span><span class="w">
</span><span class="no">:dependencies</span><span class="w"> </span><span class="p">[[</span><span class="n">devcards</span><span class="w"> </span><span class="s">"0.2.0-8"</span><span class="p">]</span><span class="w">
</span><span class="p">[</span><span class="n">binaryage/devtools</span><span class="w"> </span><span class="s">"0.8.3"</span><span class="p">]]</span><span class="w">
</span><span class="no">:repl-options</span><span class="w"> </span><span class="p">{</span><span class="no">:init-ns</span><span class="w"> </span><span class="n">foo.dev</span><span class="p">}</span><span class="w"> </span><span class="c1">;; could be default to be overriden</span><span class="w">
</span><span class="no">:plugins</span><span class="w"> </span><span class="p">[[</span><span class="n">com.jakemccrary/lein-test-refresh</span><span class="w"> </span><span class="s">"0.12.0"</span><span class="p">]]</span><span class="w">
</span><span class="no">:cljs</span><span class="w"> </span><span class="p">{</span><span class="no">:preloads</span><span class="w"> </span><span class="p">[</span><span class="n">devtools.preload</span><span class="p">]}}</span><span class="w">
</span><span class="no">:test</span><span class="w"> </span><span class="p">{</span><span class="no">:plugins</span><span class="w"> </span><span class="p">[[</span><span class="n">lein-doo</span><span class="w"> </span><span class="s">"0.1.6"</span><span class="p">]]</span><span class="w">
</span><span class="no">:cljs</span><span class="w"> </span><span class="p">{</span><span class="no">:optimizations</span><span class="w"> </span><span class="no">:none</span><span class="w">
</span><span class="no">:main</span><span class="w"> </span><span class="n">foo.test-runner</span><span class="p">}</span><span class="w"> </span><span class="c1">;; could be default to be overrriden</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="no">:uberjar</span><span class="w"> </span><span class="p">{</span><span class="no">:env</span><span class="w"> </span><span class="p">{</span><span class="no">:browser-caching</span><span class="w"> </span><span class="p">{</span><span class="s">"text/javascript"</span><span class="w"> </span><span class="mi">604800</span><span class="w">
</span><span class="s">"text/html"</span><span class="w"> </span><span class="mi">0</span><span class="p">}}</span><span class="w">
</span><span class="no">:hooks</span><span class="w"> </span><span class="p">[</span><span class="n">leiningen.sass</span><span class="p">]</span><span class="w">
</span><span class="no">:prep-tasks</span><span class="w"> </span><span class="p">[</span><span class="s">"git-info-edn"</span><span class="w"> </span><span class="s">"compile"</span><span class="w"> </span><span class="p">[</span><span class="s">"with-profile"</span><span class="w"> </span><span class="s">"uberjar"</span><span class="w"> </span><span class="s">"cljsbuild"</span><span class="w"> </span><span class="s">"once"</span><span class="p">]]</span><span class="w">
</span><span class="no">:omit-source</span><span class="w"> </span><span class="n">true</span><span class="w">
</span><span class="no">:aot</span><span class="w"> </span><span class="no">:all</span><span class="w">
</span><span class="no">:main</span><span class="w"> </span><span class="n">foo.server</span><span class="w">
</span><span class="no">:sass</span><span class="w"> </span><span class="p">{</span><span class="no">:style</span><span class="w"> </span><span class="no">:compressed</span><span class="p">}</span><span class="w">
</span><span class="no">:cljs</span><span class="w"> </span><span class="p">{</span><span class="no">:optimizations</span><span class="w"> </span><span class="no">:advanced</span><span class="p">}</span><span class="w"> </span><span class="c1">;; could be default to be overridden</span><span class="w">
</span><span class="p">}}</span><span class="w">
</span></code></pre></div></div>
Fun Fridays2017-03-11T00:00:00+00:00http://slipset.github.io/posts/fun-fridays<p>At work we have this concept of “Fun Fridays” - every other Friday we get to work on whatever we want.
It’s a plus if it’s work related, but that’s not required. This is nothing new, Google has had it for years.</p>
<p>So, what do you do on a Fun Friday? Very often it seems like stuff that’s in category of
“stuff I want to do with our product/project that never gets prioritized” or maybe “I really wonder if this works?”.</p>
<p>But I’ve been wanting to do something else for quite a while. I’m a <a href="http://corgibytes.com/blog/makers/menders/software/2015/08/14/makers-vs-menders/">mender</a>,
so greenfield work is not so attractive to me. I need some scaffolding to be present for me to work, and I really like hunting bugs and
rewriting old code. So how can I relate this to our Fun Fridays?</p>
<p>Well, I can contribute to OSS.</p>
<p>And that’s just what happened yesterday.</p>
<p>Earlier this week <a href="htttps://twitter.com/bbatsov">@bbatsov</a>, the master brewer of <a href="https://cider.readthedocs.org">CIDER</a> tweeted:</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">If you want to get involved in CIDER's development a good place to start would be a "low hanging fruit" issue <a href="https://t.co/sa1ONLGZyh">https://t.co/sa1ONLGZyh</a></p>— Bozhidar Batsov (@bbatsov) <a href="https://twitter.com/bbatsov/status/585880821531340800">April 8, 2015</a></blockquote>
<script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>which resulted in this <a href="https://github.com/clojure-emacs/cider/pull/1957">PR</a></p>
<p>So here’s the deal:</p>
<p>If you’re maintaining an OSS related to Clojure, and want a part of my 10% time, I’d be more than happy working on the most mundane tasks.
I don’t expect much, but for me to finish something within the day, I do need issues that are “ready for work”. Like the issue above,
fixing doc-errors for CIDER is pretty straight forward and was very easy to start working on.</p>
<p>I’m aware that making issues “ready for work” for someone unfamiliar with the project is a lot of work, in fact almost as much as
fixing the issue yourself, but consider it an investment for the future.</p>
The first pain2016-10-16T21:00:00+00:00http://slipset.github.io/posts/the-first-pain<p>As mentioned before, one of the key reasons I love Clojure is the language itself and its many ways of expressing the same thing.
This lets you tinker with an expression until it feels Good(TM). Of course, there are many different versions of Good, but in general,
they can be partitioned in two: My version and all the others. This leads to at least two things. One thing is that I generally spend
way too much time on getting a function “just right”. Sometimes it’s worth the time, sometimes its time wasted, but what’s always true
is that you really need to know <code class="language-plaintext highlighter-rouge">clojure.core</code>. There’s so much there. Last thing I picked up was <code class="language-plaintext highlighter-rouge">replace</code>, which just replaces
elements in a collection:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">replace</span><span class="w"> </span><span class="p">{</span><span class="s">"lol"</span><span class="w"> </span><span class="s">"foo"</span><span class="p">}</span><span class="w"> </span><span class="p">[</span><span class="s">"lol"</span><span class="w"> </span><span class="s">"bar"</span><span class="w"> </span><span class="s">"baz"</span><span class="p">)</span><span class="w">
</span><span class="c1">;; => ["foo" "bar" "baz"]</span><span class="w">
</span></code></pre></div></div>
<p>So this comes in to play when doing code-reviews. One of the things I cannot wrap my head around is overly complicated anonymous functions.
Ideally, I want anonymous functions used when mapping over collection to be no longer than one line, and preferably a retur value from either
<code class="language-plaintext highlighter-rouge">partial</code> or <code class="language-plaintext highlighter-rouge">comp</code> as such:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">map</span><span class="w"> </span><span class="p">(</span><span class="nb">partial</span><span class="w"> </span><span class="nb">+</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="mi">4</span><span class="p">])</span><span class="w">
</span><span class="c1">;; => (2 3 4 5)</span><span class="w">
</span></code></pre></div></div>
<p>When the anonymous functions begin to span several lines, I need to have them broken out into a separate function with a reasonable
name so I can understand what it does. I then try to arrange the params so that it can be used with <code class="language-plaintext highlighter-rouge">partial</code>.</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">create-frobnitzes</span><span class="w"> </span><span class="p">[</span><span class="n">frob</span><span class="w"> </span><span class="n">nit</span><span class="w"> </span><span class="n">i</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nb">str</span><span class="w"> </span><span class="p">(</span><span class="nb">inc</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="s">" "</span><span class="w"> </span><span class="n">frob</span><span class="w"> </span><span class="n">nit</span><span class="w"> </span><span class="p">(</span><span class="nb">when</span><span class="w"> </span><span class="p">(</span><span class="nb"><</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="s">"zes"</span><span class="p">)))</span><span class="w">
</span><span class="p">(</span><span class="nb">map</span><span class="w"> </span><span class="p">(</span><span class="nb">partial</span><span class="w"> </span><span class="n">create-frobnitzes</span><span class="w"> </span><span class="s">"frob"</span><span class="w"> </span><span class="s">"nit"</span><span class="p">)</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="mi">3</span><span class="p">])</span><span class="w">
</span><span class="c1">;; => ("1 frobnit" "2 frobnitzes" "3 frobnitzes" "4 frobnitzes")</span><span class="w">
</span></code></pre></div></div>
<p>This also lets us write unit tests for <code class="language-plaintext highlighter-rouge">create-frobnitzes</code>without the need to construct a whole collection of things, which could be
complicated if the collection was somewhat more involved than just <code class="language-plaintext highlighter-rouge">(range 4)</code>.</p>
<p>Another pet pieve of mine is let functions be passed data, don’t make them ask for it:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="p">[</span><span class="n">bar</span><span class="w"> </span><span class="n">baz</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nf">->></span><span class="w"> </span><span class="p">(</span><span class="nf">fetch-from-database</span><span class="w"> </span><span class="n">bar</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nb">filter</span><span class="w"> </span><span class="n">whatever</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nb">map</span><span class="w"> </span><span class="p">(</span><span class="nb">partial</span><span class="w"> </span><span class="n">whatnot</span><span class="w"> </span><span class="n">baz</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nb">reduce</span><span class="w"> </span><span class="n">with-something</span><span class="p">)))</span><span class="w">
</span></code></pre></div></div>
<p>When testing this, you need to bring out the old <code class="language-plaintext highlighter-rouge">with-redefs</code> so you can mock out the database. In my opinion, it’s much nicer with
something like</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="p">[</span><span class="n">bars-from-the-db</span><span class="w"> </span><span class="n">baz</span><span class="p">]</span><span class="w"> </span><span class="c1">; or even switch the args</span><span class="w">
</span><span class="p">(</span><span class="nf">->></span><span class="w"> </span><span class="n">bars-from-the-db</span><span class="w">
</span><span class="p">(</span><span class="nb">filter</span><span class="w"> </span><span class="n">whatever</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nb">map</span><span class="w"> </span><span class="p">(</span><span class="nb">partial</span><span class="w"> </span><span class="n">whatnot</span><span class="w"> </span><span class="n">baz</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nb">reduce</span><span class="w"> </span><span class="n">with-something</span><span class="p">)))</span><span class="w">
</span></code></pre></div></div>
<p>since this function is now decoupled from the database and testable with pure data.</p>
First serious type-error2016-10-12T21:00:00+00:00http://slipset.github.io/posts/first-serious-type-error<p>So Clojure is a dynamically typed language. So is Javascript, but Javascript feels so much more insecure to me than what Clojure does.
I think one reason for that is that Clojure does a bit more thorough job when it’s compiling.</p>
<p>Consider the following piece of Js-code</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">foo</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">bar</span><span class="p">;</span> <span class="c1">// bar is undefined</span>
<span class="p">}</span>
</code></pre></div></div>
<p>When evaluating this in the console, all is fine and dandy, but when you try to run it, it blows up:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">foo</span><span class="p">();</span>
<span class="c1">//> ReferenceError: Can't find variable bar</span>
</code></pre></div></div>
<p>The equivalent code in Clojure:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="p">[]</span><span class="w">
</span><span class="n">bar</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>When evaluating this, the compiler throws and Exception:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CompilerException java.lang.RuntimeException: Unable to resolve symbol: bar in this context
</code></pre></div></div>
<p>So a whole class of errors, the dreaded speling errors, are gone.
But you still have the type-errors. And that’s what bit me
Consider this function (slightly useless, but suits my example):</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">foo</span><span class="w">
</span><span class="s">"bars is a vector of strings"</span><span class="w">
</span><span class="p">[</span><span class="n">bars</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nb">first</span><span class="w"> </span><span class="n">bars</span><span class="p">))</span><span class="w">
</span></code></pre></div></div>
<p>Sometimes you want to call it when you only have one bar, so you wrap the bar in a vector as such:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">foo</span><span class="w"> </span><span class="p">[</span><span class="s">"the one and only bar"</span><span class="p">])</span><span class="w">
</span><span class="c1">;;=> "the one and only bar"</span><span class="w">
</span></code></pre></div></div>
<p>But, I forgot to wrap my lonely bar in a vector, and noone complained.</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">foo</span><span class="w"> </span><span class="s">"the one and only bar"</span><span class="p">)</span><span class="w">
</span><span class="c1">;;=> \t</span><span class="w">
</span></code></pre></div></div>
<p>The reason for this is that strings in Clojure are seq-able, which means that they behave as collections.
If they didn’t my code would have thrown an <code class="language-plaintext highlighter-rouge">IllegalArgumentException</code> as it does when called with a number:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">foo</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">])</span><span class="w">
</span><span class="c1">;;=> 1</span><span class="w">
</span><span class="p">(</span><span class="nf">foo</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w">
</span><span class="c1">;;=> IllegalArgumentException Don't know how to create ISeq from: java.lang.Long</span><span class="w">
</span></code></pre></div></div>
<p>Which is consistent with the code in <a href="https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L531">RT.java</a></p>
First friday2016-10-07T21:00:00+00:00http://slipset.github.io/posts/first-friday<p>It’s important to know where I’m comming from. I’ve been programming professionally for about 20 years now. I started out using Perl,
switched to Java because reasons in ‘99 and been missing the fun of emerging myself in the language as I did with Perl. In Perl there’s
<a href="https://en.wiktionary.org/wiki/TIMTOWTDI">TIMTOWTDI</a>, and I certainly like working on a function or a piece of code until it looks nice,
for some (my) definition of nice.</p>
<p>Java has had no such qualities. Having worked a bit with Java 8 streams and optional lately, I have found some ways of expressing stuff in
Java the way I want it to be.</p>
<p>But I really enjoy Clojure. Stuff fit very well together, functions can be very concise, and they very often end up being quite elegant as well.
Because I like the language so much, I’m willing more willing to spend time on stuff that’s not quite working as expected, and I’m not (as)
pissed off when I waste a couple of hours on something that I shouldn’t have wasted time on.</p>
<p>One such thing today was solved by the var-quote <code class="language-plaintext highlighter-rouge">#'</code>. I was rewriting some authorization code which uses
<a href="https://funcool.github.io/buddy-auth/latest/#access-rules">buddy</a> which ended up in code like</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">rules</span><span class="w"> </span><span class="p">[{</span><span class="no">:uri</span><span class="w"> </span><span class="s">"/foo"</span><span class="w">
</span><span class="no">:handler</span><span class="w"> </span><span class="n">bar</span><span class="p">}])</span><span class="w">
</span><span class="p">(</span><span class="nb">-></span><span class="w"> </span><span class="n">app</span><span class="w">
</span><span class="p">(</span><span class="nf">buddy/wrap-access-rules</span><span class="w"> </span><span class="n">rules</span><span class="p">))</span><span class="w">
</span></code></pre></div></div>
<p>Problem is, that if you redifine the handler function, in this case <code class="language-plaintext highlighter-rouge">bar</code>, the changes are not visible. The solution here is to var-quote
the handler as such:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">rules</span><span class="w"> </span><span class="p">[{</span><span class="no">:uri</span><span class="w"> </span><span class="s">"/foo"</span><span class="w">
</span><span class="no">:handler</span><span class="w"> </span><span class="o">#</span><span class="ss">'bar</span><span class="p">}])</span><span class="w">
</span></code></pre></div></div>
<p>and the changes will be picked up when <code class="language-plaintext highlighter-rouge">bar</code> is redefined.</p>
<h1 id="the-good-stuff">The Good stuff</h1>
<p>Since I’m new to to the code base and not quite sure how everything works, it seemed prudent to add some tests to make sure my
refactorings were working the way I wanted them to. So I wanted to, in Java parlance, mock out the database and make sure that
the tranformations I did to the data from the db were correct. In Java-land, this would have been a day of pain, but due to
Clojures map/list literals and <code class="language-plaintext highlighter-rouge">with-redefs</code> it’s all quite simple:</p>
<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; First pull your stuff from the db</span><span class="w">
</span><span class="p">(</span><span class="nf">db-fn</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="n">bar</span><span class="w"> </span><span class="n">baz</span><span class="p">)</span><span class="w">
</span><span class="c1">;=> ({:foo "bar" :baz "qix})</span><span class="w">
</span><span class="c1">;; then define a var to hold this in your test-ns</span><span class="w">
</span><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">from-db</span><span class="w"> </span><span class="p">({</span><span class="no">:foo</span><span class="w"> </span><span class="s">"bar"</span><span class="w"> </span><span class="no">:baz</span><span class="w"> </span><span class="s">"qix"</span><span class="p">}))</span><span class="w">
</span><span class="c1">;; Then run your function before the refactor</span><span class="w">
</span><span class="p">(</span><span class="nf">to-be-refactored</span><span class="w"> </span><span class="s">"whatever"</span><span class="w"> </span><span class="s">"whatnot"</span><span class="p">)</span><span class="w">
</span><span class="c1">;;=> 42</span><span class="w">
</span><span class="c1">;; Write the test</span><span class="w">
</span><span class="p">(</span><span class="nf">deftest</span><span class="w"> </span><span class="n">my-function-test</span><span class="w">
</span><span class="p">(</span><span class="nf">testing</span><span class="w"> </span><span class="s">"that it works"</span><span class="w">
</span><span class="p">(</span><span class="nf">with-redefs</span><span class="w"> </span><span class="p">[</span><span class="n">db-fn</span><span class="w"> </span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="p">[</span><span class="n">_</span><span class="w"> </span><span class="n">_</span><span class="w"> </span><span class="n">_</span><span class="p">]</span><span class="w"> </span><span class="n">from-db</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nf">is</span><span class="w"> </span><span class="p">(</span><span class="nb">=</span><span class="w"> </span><span class="mi">42</span><span class="w"> </span><span class="p">(</span><span class="nf">to-be-refactored</span><span class="w"> </span><span class="s">"whatever"</span><span class="w"> </span><span class="s">"whatnot"</span><span class="p">))))))</span><span class="w">
</span></code></pre></div></div>
First day as a full-time Clojure programmer2016-10-05T21:00:00+00:00http://slipset.github.io/posts/First-day-as-a-full-time-Clojure-programmer<p>So, today I had my first day at <a href="https://www.telenordigital.com">Telenor Digital</a>. Not much exciting stuff to report, but a couple of things worth noting:</p>
<p>1) It felt really good to be browsing the sourcecode in emacs, and discover that they’re using <a href="https://www.hugsql.org">Hugsql</a>, <a href="https://github.com/omcljs/om">Om</a>,
<a href="https://www.youtube.com/watch?v=j-kj2qwJa_E">Figwheel</a> and a dash of <a href="https://github.com/clojure/core.async">core.async</a> along with <a href="http://kafka.apache.org">Kafka</a>. I guess I’ll be re-watching <a href="https://www.youtube.com/watch?v=VC_MTD68erY&noredirect=1">One Million Clicks per Minute with Kafka and Clojure</a> a couple of times</p>
<p>2) The tooling. The app I’ll be working on is a web app. Running it straight from <code class="language-plaintext highlighter-rouge">lein repl</code>, the log-statements are printed to stdout and all is well. But when I run it from inside <a href="https://github.com/clojure-emacs/cider">Cider</a> the log-statements disappear.
I wonder why. I guess this would be off-putting for people a bit sceptic to Clojure, but I guess I’ll just have to ask in the #cider channel on Clojurians tomorrow.</p>
<p>Update: Turns out, after some googling that running the repl in a terminal and connecting via <code class="language-plaintext highlighter-rouge">M-x cider-connect</code> was the way to go.
Only downside is that Ciders new ‘I’ll insert correct middleware for you’ feature doesn’t work when connecting to a network repl, as explained <a href="http://cider.readthedocs.io/en/latest/installation/">here</a>. You also want to add <code class="language-plaintext highlighter-rouge">clj-refactor</code>-middleware as explained <a href="https://github.com/clojure-emacs/clj-refactor.el">here</a></p>
Last day at Iterate2016-09-30T21:00:00+00:00http://slipset.github.io/posts/last-day-at-Iterate<p>Today I had my last day as a consultant at <a href="https://www.iterate.no">Iterate As</a>. After almost exactly two years I’m ready to start what
should be the job I’ve been wanting for the last almost three years: A full time job programming Clojure.</p>
<p>On October 5th I’ll be starting at <a href="https://portal.telenordigital.com">Telenor Digital</a> on their analytics/data-insights team.</p>
<p>I’m very curious to see how programming Clojure in the large will play out. Having worked on small one-man-team (myself) Clojure projects
which have been done quickly and then left running, I’m curios to see how it is to dive into a large Clojure codebase which has existed for years
and worked upon by many people, and if the value propositions which I found when working on Clojure in the small are still present when working with Clojure in the large.</p>
<p>Because of this, I’ll make a commitment to blog about my experiences, good or bad, quite frequently from the 5th of October until I get bored of it.</p>
<p>Stay tuned!</p>
Here's what I'd pay for2016-02-05T17:38:00+00:00http://slipset.github.io/posts/heres-what-id-pay-for<p>My twitter feed is full. Over a couple of years, I’ve curated a bunch
of people to follow. Some tweet often, some not. Some retweet links to
relevant articles, some write the articles. Some are just funny,
others are very serious.</p>
<p>And I have this fear of missing the one really important/cool/funny
tweet, so I spend a lot of time skimming through all these tweets.</p>
<p>So what I’d be willing to subscribe to and pay for is a service which
every morning, in my timezone, presented me with a list of the top
interesting articles from my feed. This would be a happy mix of
articles from my local newspapers, the most recent blogposts from the
people I enjoy reading, perhaps a couple of posts from people I didn’t
know I’d enjoy reading.</p>
<p>But I’d also need the one or two tweets everyday which I find funny or
intriguing.</p>
<p>I guess I need a personal tweeter.</p>
<p>Anyone?</p>
Planck and writing tests2016-01-29T00:00:00+00:00http://slipset.github.io/posts/Planck-and-writing-tests<p>Lately I’ve been playing around with <a href="http://planck-repl.org">Planck</a>,
a commandline bootstrapped ClojureScript REPL for OS X based on
JavaScriptCore.</p>
<p>There are two reasons for this, one, I’m trying to write as much
Clojure(Script) as possible and one way to do that is to try to
automate as much as possible using Clojure(Script), and two, it’s fun
to contribute to some opensource projects.</p>
<p>Planck consists, as far as I can tell, of a wee bit of Clojurescript
and quite a bit of Objective C which lets you augment JavasScriptCore
with functionality which isn’t readily available.</p>
<p>Since Planck has fantastic startup times, one of the areas it really
shines in is creating small scripts for automating tasks, much like
you would with shell-scripts. But it was lacking the basic stuff to
query files, so I figured that was a nice little project, to add a
<code class="language-plaintext highlighter-rouge">fstat</code> like function to <code class="language-plaintext highlighter-rouge">planck.io</code>. Which, conceptually is quite
easy, you run some <code class="language-plaintext highlighter-rouge">stat</code> like function in the Objective C part of the
code, then expose that through a function in <code class="language-plaintext highlighter-rouge">planck.io</code>.</p>
<p>##Here be dragons!</p>
<p>As a total Objective C n00b, I had to dig around in the docs to figure
out what I needed to do. I ended up using
<code class="language-plaintext highlighter-rouge">NSFileManager:attributesOfItemAtPath:path:error</code> which seemed to work
ok. It returns a <code class="language-plaintext highlighter-rouge">NSDictionary</code> from which you pull the values, you
create a javascript object, <code class="language-plaintext highlighter-rouge">JSObjectSetProperty</code> on it and Bob is
your uncle. Unless he isn’t.</p>
<p>Because not all file attributes are present in the dictionary that
<code class="language-plaintext highlighter-rouge">NSFileManager</code> returns. So you might want to test if they are
present.</p>
<p><code class="language-plaintext highlighter-rouge">NSDictionary</code> has a method <code class="language-plaintext highlighter-rouge">[NSDictionary doesContain]</code> which should
do the job, but doesn’t. Probably because of some equals semantic, so
you end up having to use <code class="language-plaintext highlighter-rouge">[NSDictionary objectForKey]</code>. Which has a
really subtle thing about it. You see, when doing</p>
<figure class="highlight"><pre><code class="language-objective-c" data-lang="objective-c">if ([result objectForKey:NSFileAppendOnly] != nil) {
bool appendOnly = [ result objectForKey:NSFileAppendOnly ];
JSObjectSetProperty(ctx, retval, JSStringCreateWithUTF8CString("appendonly"),
JSValueMakeBoolean(ctx, appendOnly),
kJSPropertyAttributeReadOnly, nil);
}</code></pre></figure>
<p>the <code class="language-plaintext highlighter-rouge">if</code> test would actually return <code class="language-plaintext highlighter-rouge">true</code> even though the key was not present!</p>
<p>And the even more scary thing was that it would return <code class="language-plaintext highlighter-rouge">false</code> when
stepping through the debugger! The solution to this was
<a href="https://github.com/mfikes/planck/blob/master/planck/PLKClojureScriptEngine.m#L570">scary</a>.</p>
<h2 id="whats-the-point-of-all-this">What’s the point of all this</h2>
<p>The point of this is that this is quite similar to the code I write in
my day-time job. The problem at hand is not very complex nor is it
very difficult and it results in code which basically is sequential
with little need for tests. Apart from the tests you need in order to
ensure that you’ve understood the thing that your’re integrating with.</p>
<p>Here I’m integrating against OS X through an Objective C api, and my
problems lie not in my complicated glue code, but rather in my
understanding of the api.</p>
<p>And the tests you need to write to ensure you’ve understood the API
very easily become mocks (if you know how to write those for the api
you’re working against, I sure don’t know how to write mocks for
Objective C) which only reflect your understanding of the API.</p>
<h2 id="and-one-last-thingy">And one last thingy</h2>
<p>There are of course several versions of
OSX. <a href="https://www.twitter.com/mfikes">Mike Fikes</a>, the creator of
Planck, apparantly has a host of macs running different versions of OS
X. And while testing an early version of my patch, he found that the
way I was formatting dates to ship over to Clojurescript didn’t work
on OSX Lion, since my format-string <code class="language-plaintext highlighter-rouge">yyyy-mm-dd'T'hh:mm:ssZZZZZ</code> which
returns <code class="language-plaintext highlighter-rouge">"2013-08-25T00:16:27.000-00:00"</code> on El Capitan, returns
<code class="language-plaintext highlighter-rouge">"2015-08-31T15:39:19GMT-04:00"</code>, the interesting bit being the added
‘<code class="language-plaintext highlighter-rouge">GMT</code>’, on Lion, which causes <code class="language-plaintext highlighter-rouge">js/Date.</code> to throw its hands in the
air and give up.</p>
<p>So how do you write tests for this? I have no clue. My approach is to
try and visually inspect the results until they’re good. I guess you
could write a test which creates a file, runs <code class="language-plaintext highlighter-rouge">js/PLANCK_FSTAT</code> on it,
and asserts that the output is somewhat expected, but that’s kind of
offputting as well…</p>
OSX automator in clojurescript2014-10-30T00:00:00+00:00http://slipset.github.io/posts/automator-in-clojure-script<p>I don’t quite remember how I found the post, but anyways I landed upon
<a href="http://developer.telerik.com/featured/javascript-os-x-automation-example/">this</a>
blog by <a href="http://www.twitter.com/mbcrump">@mbcrump</a> about how automator
now supports Javascript as a language. I don’t even remember how I got
the idea of playing with clojurescript to get it to automate tasks,
but definitively read it somewhere. Update: Now I was reminded:
<a href="http://www.twitter.com/borkdude">@borkdude</a> retweeted</p>
<blockquote class="twitter-tweet" lang="en"><p>(let [mail (new js/Application "com.apple.mail") inbox (.. mail -inbox -messages) first-message (aget inbox 0)](.subject first-message)) 2/2</p>— Daniel Szmulewicz (@danielszmu) <a href="https://twitter.com/danielszmu/status/527589833472892928">October 29, 2014</a></blockquote>
<script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>So how did I go about this?</p>
<h1 id="starting-a-new-clojurescript-project">Starting a new Clojurescript project</h1>
<p>This is always a pain, since I hardly ever do it. I took a chance on
<a href="http://www.twitter.com/swanodette">David Nolens</a> mies plugin for
leinigen</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>lein new mies applescript</code></pre></figure>
<p>This gives you a new project called applescript with a minimal
directory-structure.</p>
<h1 id="transforming-js-to-clojurescript">Transforming js to clojurescript</h1>
<p>Given the js-code from <a href="http://www.twitter.com/mbcrump">@mbcrump</a>’s
post:</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kd">var</span> <span class="nx">Mail</span> <span class="o">=</span> <span class="nx">Application</span><span class="p">(</span><span class="dl">'</span><span class="s1">Mail</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">content</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">This is my message to you</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">msg</span> <span class="o">=</span> <span class="nx">Mail</span><span class="p">.</span><span class="nx">OutgoingMessage</span><span class="p">({</span>
<span class="na">subject</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Thanks</span><span class="dl">"</span><span class="p">,</span>
<span class="na">content</span><span class="p">:</span> <span class="nx">content</span><span class="p">,</span>
<span class="na">visible</span><span class="p">:</span> <span class="kc">true</span>
<span class="p">});</span>
<span class="nx">Mail</span><span class="p">.</span><span class="nx">outgoingMessages</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">msg</span><span class="p">);</span>
<span class="nx">Mail</span><span class="p">.</span><span class="nx">activate</span><span class="p">();</span></code></pre></figure>
<p>it was quite easy to translate it to clojurescript</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">ns</span><span class="w"> </span><span class="n">applescript.core</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">mail</span><span class="w"> </span><span class="p">(</span><span class="nf">js/Application</span><span class="w"> </span><span class="s">"Mail"</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">content</span><span class="w"> </span><span class="s">"This is my message to you!"</span><span class="p">)</span><span class="w">
</span><span class="c1">;; Note the use of the #js reader macro to make a</span><span class="w">
</span><span class="c1">;; clojure map into a js-map</span><span class="w">
</span><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">msg</span><span class="w"> </span><span class="p">(</span><span class="nf">.OutgoingMessage</span><span class="w"> </span><span class="n">mail</span><span class="w"> </span><span class="o">#</span><span class="n">js</span><span class="p">{</span><span class="no">:subject</span><span class="w"> </span><span class="s">"Thanks"</span><span class="w">
</span><span class="no">:content</span><span class="w"> </span><span class="n">content</span><span class="w">
</span><span class="no">:visible</span><span class="w"> </span><span class="n">true</span><span class="p">}))</span><span class="w">
</span><span class="c1">;; Needed aget to achieve</span><span class="w">
</span><span class="c1">;; mail.outgoingMessages.push(msg)</span><span class="w">
</span><span class="p">(</span><span class="nf">.push</span><span class="w"> </span><span class="p">(</span><span class="nb">aget</span><span class="w"> </span><span class="n">mail</span><span class="w"> </span><span class="s">"outgoingMessages"</span><span class="p">)</span><span class="w"> </span><span class="n">msg</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nf">.activate</span><span class="w"> </span><span class="n">mail</span><span class="p">)</span></code></pre></figure>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>lein cljsbuild once</code></pre></figure>
<p>builds it, but bob is not your uncle yet, since it will not run.</p>
<h1 id="making-the-stuff-run">Making the stuff run</h1>
<p>According to the post, it should only be a matter of running</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>osascript <span class="nt">-l</span> JavaScript file.js</code></pre></figure>
<p>to execute the script. Problem was, how to achieve this, telling
leiningen to include all neccessary js into a file that osascript
could run?</p>
<h1 id="the-solution">The solution</h1>
<p>was in project.clj. changing</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="w"> </span><span class="no">:cljsbuild</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="no">:builds</span><span class="w"> </span><span class="p">[{</span><span class="no">:id</span><span class="w"> </span><span class="s">"applescript"</span><span class="w">
</span><span class="no">:source-paths</span><span class="w"> </span><span class="p">[</span><span class="s">"src"</span><span class="p">]</span><span class="w">
</span><span class="no">:compiler</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="no">:output-to</span><span class="w"> </span><span class="s">"applescript.js"</span><span class="w">
</span><span class="no">:output-dir</span><span class="w"> </span><span class="s">"out"</span><span class="w">
</span><span class="no">:optimizations</span><span class="w"> </span><span class="no">:none</span><span class="w"> </span><span class="c1">;; change this to :simple</span><span class="w">
</span><span class="no">:source-map</span><span class="w"> </span><span class="n">true</span><span class="p">}}]})</span><span class="w"> </span><span class="c1">;; remove this</span></code></pre></figure>
<p>to</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="w"> </span><span class="no">:cljsbuild</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="no">:builds</span><span class="w"> </span><span class="p">[{</span><span class="no">:id</span><span class="w"> </span><span class="s">"applescript"</span><span class="w">
</span><span class="no">:source-paths</span><span class="w"> </span><span class="p">[</span><span class="s">"src"</span><span class="p">]</span><span class="w">
</span><span class="no">:compiler</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="no">:output-to</span><span class="w"> </span><span class="s">"applescript.js"</span><span class="w">
</span><span class="no">:output-dir</span><span class="w"> </span><span class="s">"out"</span><span class="w">
</span><span class="no">:optimizations</span><span class="w"> </span><span class="no">:simple</span><span class="p">}}]})</span></code></pre></figure>
<p>gave me one file, applescript.js, containing everything, which I could run as</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">osascript <span class="nt">-l</span> JavaScript applescript.js</code></pre></figure>
<p>#Bonus
Just for fun, having a look at applescript.js, all the way at the
bottom, you find:</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kd">var</span> <span class="nx">applescript</span> <span class="o">=</span> <span class="p">{</span><span class="na">core</span><span class="p">:{}};</span>
<span class="nx">applescript</span><span class="p">.</span><span class="nx">core</span><span class="p">.</span><span class="nx">mail</span> <span class="o">=</span> <span class="nx">Application</span><span class="p">(</span><span class="dl">"</span><span class="s2">Mail</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">applescript</span><span class="p">.</span><span class="nx">core</span><span class="p">.</span><span class="nx">content</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">This is my message to you!</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">applescript</span><span class="p">.</span><span class="nx">core</span><span class="p">.</span><span class="nx">msg</span> <span class="o">=</span> <span class="nx">applescript</span><span class="p">.</span><span class="nx">core</span><span class="p">.</span><span class="nx">mail</span><span class="p">.</span><span class="nx">OutgoingMessage</span><span class="p">({</span><span class="na">visible</span><span class="p">:</span><span class="o">!</span><span class="mi">0</span><span class="p">,</span> <span class="na">content</span><span class="p">:</span><span class="nx">applescript</span><span class="p">.</span><span class="nx">core</span><span class="p">.</span><span class="nx">content</span><span class="p">,</span> <span class="na">subject</span><span class="p">:</span><span class="dl">"</span><span class="s2">Thanks</span><span class="dl">"</span><span class="p">});</span>
<span class="nx">applescript</span><span class="p">.</span><span class="nx">core</span><span class="p">.</span><span class="nx">mail</span><span class="p">.</span><span class="nx">outgoingMessages</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">applescript</span><span class="p">.</span><span class="nx">core</span><span class="p">.</span><span class="nx">msg</span><span class="p">);</span>
<span class="nx">applescript</span><span class="p">.</span><span class="nx">core</span><span class="p">.</span><span class="nx">mail</span><span class="p">.</span><span class="nx">activate</span><span class="p">();</span></code></pre></figure>
<p>Which translates pretty nicely to the original js-code.</p>
On TDD2014-05-24T00:00:00+00:00http://slipset.github.io/posts/on-TDD<p>Yesterday I tried to do the <a href="http://butunclebob.com/files/downloads/Bowling%20Game%20Kata.ppt">bownling
kata</a>
by <a href="https://twitter.com/unclebobmartin">@unclebobmartin</a>. After
reading the intro, it must be clear to everyone that the scoring rules
of bowling were not designed by a programmer.</p>
<h2 id="where-i-failed">Where I failed</h2>
<p>As you can see from the presentation, Uncle Bob starts out with some
design, which he does before doing anything. So apparently, he draws
up this (big) design before he starts coding. I didn’t quite do
that. I started TTD’ing sort of right away.</p>
<p>Because that’s how I solve
problems, I start playing with ideas to see if they work.</p>
<h2 id="where-i-feel-tdd-fail-in-this-scenario">Where I feel TDD fail in this scenario</h2>
<p>In about slide 11 Uncle Bob starts to code. Note that from the
preceiding slides, he has already identified that he needs</p>
<ul>
<li>A game consisting of a series of</li>
<li>Frames, which contains one or two</li>
<li>Rolls</li>
<li>And some serious magic code for the last frame</li>
</ul>
<p>But still, instead of implementing these concepts, he starts out with
the baby steps that TDD requires, starting out with verifying that we
have a Game class.</p>
<p>Then he spends the next twenty something slides implementing baby
steps while still not introducing the concept of Rolls.</p>
<p>And so he goes on.</p>
<h2 id="and-another-gripe">And another gripe</h2>
<p>During the course of this kata he introduces several private methods
to his Game class, which, being private, are not tested explicitly,
only implicitly through <code>roll</code> and <code>score</code>. I am
aware of these just being implementation details, but when I did this
implementation myself, there were quite a few of my private
helper-methods I would have liked to unit-test to ensure that they
were not the source of my failing implementation. They often were.</p>
<h2 id="the-proof-of-the-pudding">The proof of the pudding</h2>
<p>This problem is obviously functional. Given a set of inputs (rolls)
you get a known score. Same sequence of rolls, same score. Every time.</p>
<p>But yet I fail to see one test actually verifying a known game with a
known score.</p>
<p>In <a href="http://www.bowlingindex.com/instruction/scoring.htm">this</a> you’ll
find examples of games with the correct scores.</p>
<p>So I guess, if I were to implement this kata, I’d start up with
something like:</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@Test</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">testRollSimpleGame</span><span class="o">()</span> <span class="o">{</span>
<span class="c1">// 9-0 3-5 6-1 3-6 8-1 5-3 2-5 8-0 7-1 8-1</span>
<span class="kt">int</span> <span class="o">[]</span> <span class="n">rolls</span> <span class="o">=</span> <span class="o">{</span><span class="mi">9</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="mi">3</span><span class="o">,</span> <span class="mi">5</span><span class="o">,</span> <span class="mi">6</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="mi">3</span><span class="o">,</span> <span class="mi">6</span><span class="o">,</span> <span class="mi">8</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="mi">5</span><span class="o">,</span> <span class="mi">3</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">5</span><span class="o">,</span> <span class="mi">8</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="mi">7</span><span class="o">,</span>
<span class="mi">1</span><span class="o">,</span> <span class="mi">8</span><span class="o">,</span> <span class="mi">1</span><span class="o">};</span>
<span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span><span class="o"><</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
<span class="n">g</span><span class="o">.</span><span class="na">roll</span><span class="o">(</span><span class="n">rolls</span><span class="o">[</span><span class="n">i</span><span class="o">]);</span>
<span class="o">}</span>
<span class="n">assertEquals</span><span class="o">(</span><span class="mi">82</span><span class="o">,</span> <span class="n">g</span><span class="o">.</span><span class="na">score</span><span class="o">());</span>
<span class="o">}</span></code></pre></figure>
<p>And to stop me from mucking around creating an implementation which
returns 82 for any input, I’d implement this one pretty quickly as well.</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@Test</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">testRollSimpleGame</span><span class="o">()</span> <span class="o">{</span>
<span class="c1">// X 3/ 6-1 X X X 2/ 9-0 7/ XXX</span>
<span class="kt">int</span> <span class="o">[]</span> <span class="n">rolls</span> <span class="o">=</span> <span class="o">{</span><span class="mi">10</span><span class="o">,</span> <span class="mi">3</span><span class="o">,</span> <span class="mi">7</span><span class="o">,</span> <span class="mi">6</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="mi">10</span><span class="o">,</span> <span class="mi">10</span><span class="o">,</span> <span class="mi">10</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">8</span><span class="o">,</span> <span class="mi">9</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="mi">7</span><span class="o">,</span> <span class="mi">3</span><span class="o">,</span> <span class="mi">10</span><span class="o">,</span> <span class="mi">10</span><span class="o">,</span> <span class="mi">10</span><span class="o">};</span>
<span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span><span class="o"><</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
<span class="n">g</span><span class="o">.</span><span class="na">roll</span><span class="o">(</span><span class="n">rolls</span><span class="o">[</span><span class="n">i</span><span class="o">]);</span>
<span class="o">}</span>
<span class="n">assertEquals</span><span class="o">(</span><span class="mi">193</span><span class="o">,</span> <span class="n">g</span><span class="o">.</span><span class="na">score</span><span class="o">());</span>
<span class="o">}</span></code></pre></figure>
<p>This last test actually highlights a problem, when you roll a strike,
you do not roll your second roll for the frame, which means that your
game gets less than 20 rolls.</p>
<p>As a bonus, you see that you easily can refactor the tests into
something like:</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kt">void</span> <span class="nf">assertCorrectScore</span><span class="o">(</span><span class="kt">int</span> <span class="o">[]</span> <span class="n">rolls</span><span class="o">,</span> <span class="kt">int</span> <span class="n">score</span><span class="o">)</span> <span class="o">{</span>
<span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span><span class="o"><</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
<span class="n">g</span><span class="o">.</span><span class="na">roll</span><span class="o">(</span><span class="n">rolls</span><span class="o">[</span><span class="n">i</span><span class="o">]);</span>
<span class="o">}</span>
<span class="n">assertEquals</span><span class="o">(</span><span class="n">score</span><span class="o">,</span> <span class="n">g</span><span class="o">.</span><span class="na">score</span><span class="o">());</span>
<span class="o">}</span></code></pre></figure>
<p>As for Uncle Bobs implementation, I fail to see any such tests appart
from the gutter-game and perfect-game, both of which I admit are
important tests, though the former is more important with my bowling
skills.</p>
<h1 id="my-main-point">My main point</h1>
<p>Is still that to me it seems just useless to implement a lot of
small, useless tests, since they disturb my problem-solving process,
and they seem to be of little value when the job is done.</p>
<p>I’d personally much rather have a couple of real-world tests which
ensures that the function is correct, and use those as a guard when I
refactor my code. In the end, that’s why I need tests, to ensure that
I have implemented the requirements, not to help me on my way to
solving the problem.</p>
<h1 id="a-sortof-untested-version-in-clojure">A sortof untested version in Clojure</h1>
<p>Oh, and then the shameless plug for Clojure. I did end up implementing
a scoringthingy in Clojure, which can be found
<a href="https://github.com/slipset/bowling">here</a></p>
<p>The nice thing about doing this in Clojure, is that I could play with
my data-model without having to resort to figuring out how to name
classes and such.</p>
<p>Of course, I should have implemented the tests above, which I might
just end up doing, but not today.</p>
<p>The test-driven java implementation? It was abandoned.</p>
Alfresco transactions and side effects2014-05-19T00:00:00+00:00http://slipset.github.io/posts/Alfresco-transactions-and-side-effects<p>Alfresco has this notion of activities, which basically is stuff
that’s happened in a room in which you are a member. There is an
activity feed, and there is an email which is sendt out every so often
which tells you what has happened since the last time the email was
sendt.</p>
<p>The latest activity you received news about is stored in the
<code>EMAIL_FEED_ID</code> property on your person object. So every
time an activity email is sent out, this property is updated to
reflect the last activity sent to you.</p>
<p>Unless</p>
<p>The class that does this job, the
<a href="http://goo.gl/jeymUa">FeedNotifierImpl</a> wraps each users
notification-email-sender-thingy in a <a href="http://goo.gl/YpvGVF">RetryingTransactionHelper</a>. You can see that in
there somewhere (makes you wish this was written in Clojure,
right). Now, the interesting bit is that if you happen to cause an
exception being thrown in while in this transaction, say by executing</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="k">try</span> <span class="o">{</span>
<span class="nc">NodeRef</span> <span class="n">p</span> <span class="o">=</span> <span class="n">nodeService</span><span class="o">.</span><span class="na">getParentNodeRef</span><span class="o">(</span><span class="n">nodeRef</span><span class="o">);</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">log</span><span class="o">.</span><span class="na">warn</span><span class="o">(</span><span class="s">"no parent for "</span> <span class="o">+</span> <span class="n">nodeRef</span><span class="o">);</span>
<span class="o">}</span></code></pre></figure>
<p>then, even if you catch it, like shown above, Alfresco will mark the
transaction as to be rolled back. This means that the
<code>EMAIL_FEED_ID</code> will never be updated.</p>
<p>This might just be very correct, apart from the fact that there is
stuff done in this transaction that <em>cannot be rolled back</em>, yes, the
emails, they are already dispatched at the time of the rollback, and
thus our users get activity emails with old activities in them.</p>
The three dimensions of Clojure2014-05-02T00:00:00+00:00http://slipset.github.io/posts/The-three-dimensions-of-clojure<p>It seems to me that there are three dimensions of working with Clojure.</p>
<p>#The elegance
The first, and most obvious dimension is the elegance in the language itself.
It is such a pleasure working in a language which lets you do suff like:</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nb">distinct</span><span class="w"> </span><span class="p">(</span><span class="nb">map</span><span class="w"> </span><span class="no">:foo</span><span class="w"> </span><span class="n">bars</span><span class="p">))</span></code></pre></figure>
<p>It’s just like little pieces of functionality waiting to be put together.
Like Lego.</p>
<p>#The higher order
This is where I’m at right now. I’ve just started to realize what powers lie in <code>comp</code> and <code>partial</code>.
What follows is a contrived example, but think it through:</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="p">{</span><span class="no">:foo</span><span class="w"> </span><span class="p">{</span><span class="no">:bar</span><span class="w"> </span><span class="p">{</span><span class="no">:baz</span><span class="w"> </span><span class="s">"qix"</span><span class="p">}}})</span><span class="w">
</span><span class="p">(</span><span class="nf">update-in</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="p">[</span><span class="no">:foo</span><span class="w"> </span><span class="no">:bar</span><span class="w"> </span><span class="no">:baz</span><span class="p">]</span><span class="w"> </span><span class="p">(</span><span class="nb">comp</span><span class="w"> </span><span class="p">(</span><span class="nb">partial</span><span class="w"> </span><span class="nb">str</span><span class="w"> </span><span class="s">"foo"</span><span class="p">)</span><span class="w"> </span><span class="n">clojure.string/reverse</span><span class="w"> </span><span class="n">clojure.string/upper-case</span><span class="p">))</span><span class="w">
</span><span class="c1">;; => {:foo {:bar {:baz "fooXIQ"}}}</span></code></pre></figure>
<p>#The concepts
But maybe the most facinating thing about Clojure is the thoughts of Rich Hickey. It’s so cool that he’s
identified these problems in programming and then set out to solve them by creating this language. And
listening to his talks, like this one, on <a href="http://www.infoq.com/presentations/Value-Identity-State-Rich-Hickey">value, identity state</a>
is just awesome.</p>
Thoughts on getting Clojure into the enterprise2014-04-18T00:00:00+00:00http://slipset.github.io/posts/Thoughts-on-getting-Clojure-into-the-enterprise<p><a href="https://twitter.com/odinodin">@odinodin</a> pointed me to
<a href="https://twitter.com/neal4d">@neal4d</a> talk on <a href="http://t.co/kdQSlHQKIa">Introducing Clojure to
the enterprise</a>. Having watched it I want to
bring forward some of my own thoughts on the matter.</p>
<p>#Guerilla tactics
Neal (I hope he’s okay with my using his first name, Mr. Ford sounds
so formal, and people might confuse him with Harisson) talks about Cat
burglary in his talk, where you let unknown tech piggyback on known
tech, as a strategy for getting Clojure in the door. Personally I have
greater confidence in some sort of guerilla tactics, that is, find
some small project on the side that noone actually cares to much about
and implement it in Clojure, and when you’re done (ahead of schedule)
you ask for forgiveness.</p>
<p>#The worries of the CTO
I’d disagree with Neal in the assumption that the reason the CTO is
reluctant to choose Clojure is because she’s scared of being fired. In
Norway, it’s impossible to get fired, so it can’t be the reason.</p>
<p>I believe that a good CTO is worried about how to best contribute to
her company making money. So, if I were a CTO, I’d definitively rule
out a total rewrite of an existing Java application, that’s just
foolish. So in order to get Clojure in the door, you need to find an
area of your application which is kind of isolated that you can
implement new stuff in Clojure.</p>
<p>Also, your CTO will be worried about who else can maintain the code
you wrote. When you leave your company to work for Cognitect, who’s
going to understand the super-dense code you wrote using zippers and
partial functions? Because, you need to remember, she hired the
cheapest, not the brightest, developers she could get her hands on (so
what are you doing there, anyways?).</p>
<p>Imagine she let’s you start with Clojure, she’ll also have to
bring the other devs up to speed on Clojure, and guess what, that
costs money. Just because you’re willing to teach yourself Clojure on
your spare time, doesn’t mean all your colleagues are willing to do
the same.</p>
<p>So the argument you need to be able to make to the CTO is that by
adopting Clojure, you and your coworkers will deliver value so much
faster that it actually makes up for the investment she has to make to
get your team up to speed in Clojure.</p>
<p>Which brings me to the need for</p>
<p>#Success stories
I guess more stuff like <a href="http://goo.gl/IbYAOn">this</a> from <a href="https://www.twitter.com/thejayfields">Jay
Fields</a> is needed (even though
it scares the hell out of me), but I also need the facts to show that
a team using Clojure delivers more software cheaper than a similar
team using Java.</p>
First 1000 lines of Clojure2014-04-16T00:00:00+00:00http://slipset.github.io/posts/first-1000-lines-of-clojure<p>This is a short summary after having written my first 1000 lines of Clojure.</p>
<p>It all started when I was assigned the task of importing some stuff
into our stuff and nobody cared to specify which language to write the
importer in.</p>
<p>First I thought I’d write it in Scala, but when push came to shove, I
couldn’t be bothered learning a new syntax, so I figured Clojure would
be a good fit. I’ve always been intrigued by
<a href="http://cpansearch.perl.org/src/GAAS/perl-lisp-0.06/Changes">lisp</a>, so
a lisp running on the JVM should be a good fit.</p>
<p>#The importer
Basically I was given a huge XMl-file and some content files, and I
wrote a thingy which transformed this XML-file into a nice
tree-structure, which I then fed to a rest-client responsible for
creating content by interacting with our rest-api.</p>
<p>#Lessons learned
I’ve been working on and off on this importer for the last four
months, with breaks from it in up to a month in length. I was scared
about coming back to the code after such long time, but that has not
been a problem at all, even though</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">parents-of-files</span><span class="w"> </span><span class="p">[</span><span class="n">folder</span><span class="w"> </span><span class="nb">path</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">let</span><span class="w"> </span><span class="p">[</span><span class="nb">children</span><span class="w"> </span><span class="p">(</span><span class="no">:children</span><span class="w"> </span><span class="n">folder</span><span class="p">)</span><span class="w">
</span><span class="n">docs</span><span class="w"> </span><span class="p">(</span><span class="nb">filter</span><span class="w"> </span><span class="no">:document</span><span class="w"> </span><span class="nb">children</span><span class="p">)</span><span class="w">
</span><span class="n">sub-nodes</span><span class="w"> </span><span class="p">(</span><span class="nb">remove</span><span class="w"> </span><span class="no">:document</span><span class="w"> </span><span class="nb">children</span><span class="p">)</span><span class="w">
</span><span class="n">new-path</span><span class="w"> </span><span class="p">(</span><span class="nb">conj</span><span class="w"> </span><span class="nb">path</span><span class="w"> </span><span class="p">(</span><span class="no">:name</span><span class="w"> </span><span class="n">folder</span><span class="p">))</span><span class="w">
</span><span class="nb">rest</span><span class="w"> </span><span class="p">(</span><span class="nf">flatten</span><span class="w"> </span><span class="p">(</span><span class="nb">map</span><span class="w"> </span><span class="o">#</span><span class="p">(</span><span class="nf">parents-of-files</span><span class="w"> </span><span class="p">(</span><span class="no">:folder</span><span class="w"> </span><span class="n">%1</span><span class="p">)</span><span class="w"> </span><span class="n">new-path</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="n">sub-nodes</span><span class="p">))]</span><span class="w">
</span><span class="p">(</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nb">seq</span><span class="w"> </span><span class="n">docs</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nb">cons</span><span class="w"> </span><span class="p">{</span><span class="no">:path</span><span class="w"> </span><span class="n">new-path</span><span class="w"> </span><span class="no">:documents</span><span class="w"> </span><span class="n">docs</span><span class="p">}</span><span class="w"> </span><span class="nb">rest</span><span class="p">)</span><span class="w">
</span><span class="nb">rest</span><span class="p">)))</span><span class="w">
</span><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">flatten-children</span><span class="w"> </span><span class="p">[</span><span class="n">folder</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">let</span><span class="w"> </span><span class="p">[</span><span class="n">flat-tree</span><span class="w"> </span><span class="p">(</span><span class="nf">parents-of-files</span><span class="w"> </span><span class="n">folder</span><span class="w"> </span><span class="p">[])]</span><span class="w">
</span><span class="p">(</span><span class="nf">flatten</span><span class="w"> </span><span class="p">(</span><span class="nb">map</span><span class="w"> </span><span class="o">#</span><span class="p">(</span><span class="nf">add-path-to-docs</span><span class="w"> </span><span class="p">(</span><span class="no">:documents</span><span class="w"> </span><span class="n">%</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">:path</span><span class="w"> </span><span class="n">%</span><span class="p">))</span><span class="w"> </span><span class="n">flat-tree</span><span class="p">))))</span></code></pre></figure>
<p>Still makes me a bit scared. Having said that, given the shortish
functions and their descriptive names, it’s quite easy to follow the code.</p>
<p>##Persistent data structures
Working with persistent data structures was difficult before I
understood that Clojure has some nice functions to make it much
easier. In the beginning, when I wanted to change <tt>baz</tt> to <tt>qux</tt> in</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="p">{</span><span class="no">:foo</span><span class="w"> </span><span class="p">{</span><span class="no">:bar</span><span class="w"> </span><span class="p">{</span><span class="no">:baz</span><span class="w"> </span><span class="s">"qix"</span><span class="p">}}})</span></code></pre></figure>
<p>I ended up with code like</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">update-baz</span><span class="w"> </span><span class="p">[</span><span class="n">h</span><span class="w"> </span><span class="nb">val</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">let</span><span class="w"> </span><span class="p">[</span><span class="n">foo</span><span class="w"> </span><span class="p">(</span><span class="no">:foo</span><span class="w"> </span><span class="n">h</span><span class="p">)</span><span class="w">
</span><span class="n">bar</span><span class="w"> </span><span class="p">(</span><span class="no">:bar</span><span class="w"> </span><span class="n">foo</span><span class="p">)]</span><span class="w">
</span><span class="p">(</span><span class="nb">assoc</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="no">:foo</span><span class="w"> </span><span class="p">(</span><span class="nb">assoc</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="no">:bar</span><span class="w"> </span><span class="p">(</span><span class="nb">assoc</span><span class="w"> </span><span class="n">bar</span><span class="w"> </span><span class="no">:baz</span><span class="w"> </span><span class="nb">val</span><span class="p">)))))</span></code></pre></figure>
<p>which took me 10 minutes to write. Then you find <tt>assoc-in</tt>,
and the whole thing is done in one line:</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">assoc-in</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="p">[</span><span class="no">:foo</span><span class="w"> </span><span class="no">:bar</span><span class="w"> </span><span class="no">:baz</span><span class="p">]</span><span class="w"> </span><span class="s">"qux"</span><span class="p">)</span></code></pre></figure>
<p>If you want to capitalize the value instead of just replacing it, you
use <tt>update-in</tt></p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">update-in</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="p">[</span><span class="no">:foo</span><span class="w"> </span><span class="no">:bar</span><span class="w"> </span><span class="no">:baz</span><span class="p">]</span><span class="w"> </span><span class="n">clojure.string/capitalize</span><span class="p">)</span></code></pre></figure>
<p>##The hard bits
The hardest bit in this project was due to the fact that the XML was
actually a dump of a
<a href="http://docs.oracle.com/javase/6/docs/api/javax/swing/tree/DefaultMutableTreeNode.html">javax.swing.DefaultMutableTreeNode</a>. This
meant that to start the transformation of this XML, I needed to use
the java-beans that were serialized. This meant that in order to test
my functions, I first had to get hold of the Java-objects, which could
only be found by deserializing the stuff. So, even though the
Java-interop worked as a charm, it was a hassle to get
test-data. Lesson learned from this is to get stuff over to lists and
maps as soon as possible, and the
<a href="http://clojuredocs.org/clojure_core/clojure.core/bean">bean</a> function
is your friend here.</p>
<p>##The REPL
Working in the repl is sooo nice. You start out with an idea of what
you want to make, then you polish it in the REPL. As far as I can see
TDD becomes useless, <a href="http://blog.jayfields.com/2014/01/repl-driven-development.html">Jay
Fields</a>
has more on this.</p>
<p>A downside to working in the REPL (through CIDER in emacs) is that I
constantly forget to save my buffers. This leads to my unsureness
about the state of the file I’m currently editing on. Don’t really
know how to handle that.</p>
<p>#The big bonus
Was actually something I discovered today, as the project is getting
finished. Running the import in the REPL means I can interact with the
import <i>after it is done</i></p>
<p>Take this function, which takes a document and creates it on the
server:</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">defmethod</span><span class="w"> </span><span class="n">create-document</span><span class="w"> </span><span class="n">false</span><span class="w"> </span><span class="p">[</span><span class="n">document</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nf">try</span><span class="w">
</span><span class="p">(</span><span class="k">let</span><span class="w"> </span><span class="p">[</span><span class="n">node-id</span><span class="w"> </span><span class="p">(</span><span class="nf">rest/create-document</span><span class="w"> </span><span class="p">(</span><span class="nf">remove-audit-props</span><span class="w"> </span><span class="n">document</span><span class="p">))]</span><span class="w">
</span><span class="p">(</span><span class="nf">rest/set-properties</span><span class="w"> </span><span class="p">(</span><span class="nb">assoc</span><span class="w"> </span><span class="p">(</span><span class="nf">get-audit-props</span><span class="w"> </span><span class="n">document</span><span class="p">)</span><span class="w"> </span><span class="no">:nodeId</span><span class="w"> </span><span class="n">node-id</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nf">swap!</span><span class="w"> </span><span class="n">document-count</span><span class="w"> </span><span class="nb">inc</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nf">print-document-stats</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nf">catch</span><span class="w"> </span><span class="n">Exception</span><span class="w"> </span><span class="n">e</span><span class="w">
</span><span class="p">(</span><span class="nf">swap!</span><span class="w"> </span><span class="n">errors</span><span class="w"> </span><span class="nb">conj</span><span class="w"> </span><span class="n">document</span><span class="p">)</span><span class="w">
</span><span class="p">(</span><span class="nf">error</span><span class="w"> </span><span class="n">e</span><span class="w"> </span><span class="s">"Could not create document "</span><span class="w"> </span><span class="n">document</span><span class="p">))))</span></code></pre></figure>
<p>As you can see, whenever it fails, it adds the document to the
<tt>errors</tt> atom. This lives on after the import is done, and I
can inspect the errors to see how many errors have occured, and I can
even manually retry the documents that failed. I would never have
thought about making that possible had I written this importer in
Java.</p>
<p>#In ending
I do find it kind of sad that most developers seem to be frightened by
Lisps in general, since it is a really nice language-family to work
with.</p>
<p>I find that wrapping my head around some of the stuff I need to do is
hard, but that actually makes me think harder about the problem at
hand, and in the end seems to leed to better solutions.</p>
Mocking leads to bad design2014-03-10T00:00:00+00:00http://slipset.github.io/posts/mocking-lead-to-bad-design<p><a href="https://twitter.com/mfeathers">@mfeathers</a> wrote an
<a href="http://michaelfeathers.typepad.com/michael_feathers_blog/2008/06/the-flawed-theo.html">article</a>
back in 2008 about Unit Testing in which he, if I understood him
correctly, amongst other things say that it doesn’t matter too much if
you unit-test or not, as long as you think carefully about your code.</p>
<p>But that’s not the point of this post. The reason I bring up Michael
Feathers article is that it talks extensivly about mocking as a good
thing.</p>
<p>And I’ve been wondering lately if mocking is a bad thing.</p>
<p>#A bit of background
When evaluating the effects of writing unit-tests, something I only do
very informally (the evaluating, that is), I’ve found that I’m unsure
about how many errors the tests catch. And I find that the least
interesting part about the unit-tests.</p>
<p>The interesting bit is that they force the developer to write code
that’s easy to test. And code that’s easy to test is also easy to
maintain.</p>
<p>Let’s consider the following code snippet from some code I have laying
around. The following fifteen lines are part of a 66 line function
ridled with ifs, elses, and buts.</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="k">if</span> <span class="p">(</span><span class="nx">params</span><span class="p">.</span><span class="nx">foo</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">util</span><span class="p">.</span><span class="nx">MyUtil</span><span class="p">.</span><span class="nx">setLanguage</span><span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">events</span><span class="p">.</span><span class="nx">fireEvent</span><span class="p">(</span><span class="dl">'</span><span class="s1">showDetails</span><span class="dl">'</span><span class="p">,</span> <span class="nx">params</span><span class="p">);</span>
<span class="p">},</span> <span class="nx">me</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">params</span><span class="p">.</span><span class="nx">bar</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">util</span><span class="p">.</span><span class="nx">MyUtil</span><span class="p">.</span><span class="nx">setLanguage</span><span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nx">me</span><span class="p">.</span><span class="nx">dologin</span><span class="p">();</span>
<span class="p">},</span> <span class="nx">me</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">util</span><span class="p">.</span><span class="nx">MyUtil</span><span class="p">.</span><span class="nx">setLanguage</span><span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nx">me</span><span class="p">.</span><span class="nx">isLoggedIn</span><span class="p">();</span>
<span class="p">},</span> <span class="nx">me</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>In order to write tests for this, you’d have to split it up into
smaller, more manageble pieces.</p>
<p>Unless you introduce mocks.</p>
<p>Because if you introduce mocks you can test the code like:</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">describe</span><span class="p">(</span><span class="dl">"</span><span class="s2">my example</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nx">it</span><span class="p">(</span><span class="dl">"</span><span class="s2">calls setLanguage when params.foo is true</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">spy</span> <span class="o">=</span> <span class="nx">spyOn</span><span class="p">(</span><span class="nx">app</span><span class="p">.</span><span class="nx">util</span><span class="p">.</span><span class="nx">MyUtil</span><span class="p">,</span> <span class="dl">"</span><span class="s2">setLanguage</span><span class="dl">"</span><span class="p">),</span>
<span class="nx">params</span> <span class="o">=</span> <span class="p">{</span><span class="na">foo</span><span class="p">:</span> <span class="kc">true</span><span class="p">};</span>
<span class="nx">util</span><span class="p">.</span><span class="nx">myFunc</span><span class="p">(</span><span class="nx">params</span><span class="p">);</span>
<span class="nx">expect</span><span class="p">(</span><span class="nx">app</span><span class="p">.</span><span class="nx">util</span><span class="p">.</span><span class="nx">MyUtil</span><span class="p">.</span><span class="nx">setLanguage</span><span class="p">).</span><span class="nx">toHaveBeenCalled</span><span class="p">();</span>
<span class="p">});</span>
<span class="p">});</span></code></pre></figure>
<p>#The same thing in Java
In Javacode I often see stuff like</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="nc">List</span><span class="o"><</span><span class="nc">Bar</span><span class="o">></span> <span class="n">bars</span><span class="o">)</span> <span class="o">{</span>
<span class="k">for</span> <span class="o">(</span><span class="nc">Bar</span> <span class="nl">bar:</span> <span class="n">bars</span><span class="o">)</span> <span class="o">{</span>
<span class="n">bar</span><span class="o">.</span><span class="na">setBaz</span><span class="o">(</span><span class="n">bar</span><span class="o">.</span><span class="na">getBaz</span><span class="o">()</span> <span class="o">+</span> <span class="mi">1</span><span class="o">);</span>
<span class="o">}</span>
<span class="n">persister</span><span class="o">.</span><span class="na">perist</span><span class="o">(</span><span class="n">bars</span><span class="o">);</span>
<span class="o">}</span></code></pre></figure>
<p>So to test this, you need to break out the Mocks, mock out the
persister, and verify that it is called with a list of bars in which
baz has been incremented by one.</p>
<p>##How would I write this code?
I’d I would like to pull out the mutating bit so you get something
like this:</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="nc">List</span><span class="o"><</span><span class="nc">Bar</span><span class="o">></span> <span class="n">bars</span><span class="o">)</span> <span class="o">{</span>
<span class="k">for</span> <span class="o">(</span><span class="nc">Bar</span> <span class="nl">bar:</span> <span class="n">bars</span><span class="o">)</span> <span class="o">{</span>
<span class="n">incBaz</span><span class="o">(</span><span class="n">bar</span><span class="o">);</span>
<span class="o">}</span>
<span class="n">persister</span><span class="o">.</span><span class="na">perist</span><span class="o">(</span><span class="n">bars</span><span class="o">);</span>
<span class="o">}</span></code></pre></figure>
<p>This way you can test the <code class="language-plaintext highlighter-rouge">incBaz</code> method in total isolation, and IMO,
you now got a better design.</p>
Functional programming and naming2014-03-04T00:00:00+00:00http://slipset.github.io/posts/fp-and-naming<p>#The CleanerUpper
<a href="https://twitter.com/jessitron">@jessitron</a> wrote a
<a href="http://blog.jessitron.com/2014/03/modularity-in-scala-isolation-of.html">post</a>
on some refactoring she’d done in Scala. But it was not the neat
refactoring that got me thinking, it was the name of her class</p>
<figure class="highlight"><pre><code class="language-scala" data-lang="scala"><span class="k">class</span> <span class="nc">CleanerUpper</span><span class="o">(</span><span class="n">broom</span><span class="k">:</span> <span class="kt">Broom</span><span class="o">,</span>
<span class="n">rag</span><span class="k">:</span> <span class="kt">Dishcloth</span><span class="o">,</span>
<span class="n">wiper</span><span class="k">:</span> <span class="kt">MicrofiberTowel</span><span class="o">,</span>
<span class="n">config</span><span class="k">:</span> <span class="kt">CleanConfig</span><span class="o">)</span> <span class="o">{</span>
<span class="o">}</span></code></pre></figure>
<p>##OO and naming
Naming has been a problem for me ever since I started programming
Java. I don’t know how many Managers, Services, Helpers and Utils I’ve
written through the years, not to forget the Creators, Factories and
Homes. The problem arises from the fact that everything in OO needs a
bloody name. And to be able extract stuff from other stuff when doing
a refactoring, you need to put it somewhere, and that somewhere needs
to have a name. Like <code>CleanerUpperer</code>.</p>
<p>##FP (or should I say Clojure) and naming
Naming a bunch of things seems to be much simpler in Clojure. Had I
been writing some cleaner stuff in Clojure, I guess I’d just made
myself a <code>cleaner</code> namespace and I’d be done. Because you
have functions they don’t have to live inside a noun, but rather just
be a collection of stuff that do more or less similar things. If the
<code>cleaner</code> namespace becomes too big, you just create
another one like <code>broom</code>. No <code>BroomManager</code>
needed.</p>
<p>##Problems in FP naming
The one problem I am facing with regards to naming in fp is when you
have a function that does something to a bunch of things:</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">tranform</span><span class="w">
</span><span class="s">"Takes a collection of foos and makes them into bars"</span><span class="w">
</span><span class="p">[</span><span class="n">foos</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nb">map</span><span class="w"> </span><span class="o">#</span><span class="p">(</span><span class="nf">...</span><span class="p">)</span><span class="w"> </span><span class="n">foos</span><span class="p">))</span></code></pre></figure>
<p>This is all fine and dandy until the anonymous function becomes so
complicated that you want to give it a name. What do you call it? Do
you rename your original <code>transform</code> to
<code>transform-all</code> and name your extracted function
<code>transform</code>?</p>
<p>I really have no good answer for this.</p>
The things I love about Clojure and two things that suck2014-03-02T00:00:00+00:00http://slipset.github.io/posts/the-things-I-love-about-clojure-and-two-things-that-suck<p>##The things I love</p>
<p>###REPL
Working in the REPL is just amazing. It lets you experiment with
stuff, redfine functions on the fly, assign stuff to variables, work
with them, and it’s just great.</p>
<p>Working in Java, the closest thing I can come to is running unit-tests
in your IDE. But still then, it’s just way more complicated.</p>
<p>The REPL, combined with the fact that you normally start out
implementing your datastructures in maps and lists, lets you
experiment your way through your development.</p>
<p>In Java, you need to figure out what you want to call stuff before you
can start working. Is this thing a Person, a Student, or an Employee,
and if so, what attributes does it have. In the REPL?</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="p">{</span><span class="no">:name</span><span class="w"> </span><span class="s">"John"</span><span class="p">})</span></code></pre></figure>
<p>You need a couple of these?</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">ps</span><span class="w"> </span><span class="p">[{</span><span class="no">:name</span><span class="w"> </span><span class="s">"John"</span><span class="p">}</span><span class="w"> </span><span class="p">{</span><span class="no">:name</span><span class="w"> </span><span class="s">"Frank"</span><span class="p">}])</span></code></pre></figure>
<p>Now compare this to the amout of code you’d need to write in Java.</p>
<p>###The way stuff fit together
Take <code class="language-plaintext highlighter-rouge">update-in</code></p>
<blockquote>
<p>‘Updates’ a value in a nested associative structure, where ks is a
sequence of keys and f is a function that will take the old value
and any supplied args and return the new value, and returns a new
nested structure. If any levels do not exist, hash-maps will be
created.</p>
</blockquote>
<p>This lets you write stuff like</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">a-foo</span><span class="w"> </span><span class="p">{</span><span class="no">:foo</span><span class="w"> </span><span class="p">{</span><span class="no">:bar</span><span class="w"> </span><span class="mi">2</span><span class="p">}})</span><span class="w">
</span><span class="p">(</span><span class="nf">update-in</span><span class="w"> </span><span class="n">a-foo</span><span class="w"> </span><span class="p">[</span><span class="no">:foo</span><span class="w"> </span><span class="no">:bar</span><span class="p">]</span><span class="w"> </span><span class="nb">+</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w">
</span><span class="c1">;=> {:foo {:bar 3}}</span></code></pre></figure>
<p>The point here is that the function <code class="language-plaintext highlighter-rouge">+</code> is being passed the value of
<code class="language-plaintext highlighter-rouge">:bar</code> in <code class="language-plaintext highlighter-rouge">:foo</code> <em>along with</em> 1, so you’re actually calling</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nb">+</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w">
</span><span class="c1">;=> 3</span></code></pre></figure>
<p>###Sequence abstraction
The sequence abstraction leads to the fact that all the higher-order
functions like <code class="language-plaintext highlighter-rouge">map</code>, <code class="language-plaintext highlighter-rouge">filter</code>, <code class="language-plaintext highlighter-rouge">reduce</code>, etc all work on what ever
kind of collection you throw at them. Even better, if you choose to
start using records with <code class="language-plaintext highlighter-rouge">defrecord</code>, they will also work as
sequences!</p>
<p>Along with destructuring, this lets you write stuff like</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">update-vals</span><span class="w">
</span><span class="s">"updates all the values in a map by applying the function f
on them"</span><span class="w">
</span><span class="p">[</span><span class="n">m</span><span class="w"> </span><span class="n">f</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nb">map</span><span class="w"> </span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="p">[[</span><span class="n">k</span><span class="w"> </span><span class="n">v</span><span class="p">]]</span><span class="w"> </span><span class="p">[</span><span class="n">k</span><span class="w"> </span><span class="p">(</span><span class="nf">f</span><span class="w"> </span><span class="n">v</span><span class="p">)])</span><span class="w"> </span><span class="n">m</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nf">update-vals</span><span class="w"> </span><span class="p">{</span><span class="no">:foo</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="no">:bar</span><span class="w"> </span><span class="mi">2</span><span class="p">}</span><span class="w"> </span><span class="nb">inc</span><span class="p">)</span><span class="w">
</span><span class="c1">;=> {:foo 2 :bar 3}</span></code></pre></figure>
<p>There are a couple of points to be made of this. First of all it is
incredibly concise. My head explodes by just looking at this function.</p>
<p>Secondly it shows that persistent data structures are not that hard to
work with. With functions like <code class="language-plaintext highlighter-rouge">update-in</code> and the one above, it’s not
much harder to work with persistent data structures than the, I’d say,
normal, mutable ones you have in Java.</p>
<p>###Emacs
I’m so happy to be back in Emacs. I started coding in Emacs again a
couple of months ago to see if it was a viable option to Intellij wrt
coding in Javascript/Ext.js. I have found it to be so. Given lintnode
and projectile, Javascript coding in Emacs works.</p>
<p>But it all comes together in Clojure. You navigate the code with
<tt>C-M-f</tt> and <tt>C-M-b</tt>, you kill code with
<tt>C-M-k</tt>. And since Clojure is homoiconic (got to use that
word), it’s actually quite easy to understand what a s-exp is. It’s
the thing in the parens.</p>
<p>Also, Clojure-mode with CIDER just rocks, since it lets you run the
REPL inside emacs, which means you don’t ever need to leave.</p>
<p>##The two things that suck
So far I’ve only found two things I dislike about Clojure, apart from
my brain working on overload trying to remember how my nested
data-structures look like</p>
<p>###No debugger
I know there are debugger tools out there, but I do miss the ability
to insert a <code class="language-plaintext highlighter-rouge">(debugger)</code> statement in my code and drop into, well, a
debugger which lets me examine the frame I’m in. Right now I’m
resorting to <code class="language-plaintext highlighter-rouge">(println)</code>, which to me is a huge step backwards.</p>
<p>###Error messages
The run-time error messages I get from Clojure are so bad I don’t even
want to think about it. It might just be me doing everything wrong, or
even having to high expectations, but I just simply want to know the
line in my clojure file in which the error occured with some
explanation which has some connection to the code I’ve written, not to
the Java code which implements Clojure.</p>
<p>##In conclusion
The sad bit is that the two points of suckage makes it hard for me to
promote Clojure as a language to work in for my colleagues, because
along with all the parens (which I look upon as a feature), the lack of
debugger and the hopeless errormessages without context, makes Clojure
a hard sell.</p>
Clojure and refactoring2014-03-02T00:00:00+00:00http://slipset.github.io/posts/clojure-and-refactoring<p>Last night I tweeted</p>
<blockquote class="twitter-tweet" lang="en"><p>Seems to me that refactoring-tools are much less needed when programming <a href="https://twitter.com/search?q=%23clojure&src=hash">#clojure</a></p>— Erik Assum (@slipset) <a href="https://twitter.com/slipset/statuses/439710783191416832">March 1, 2014</a></blockquote>
<p>to which I got a couple of responses.</p>
<p>First from <a href="https://twitter.com/mikera">@mikera</a> which contained a link to a really nice post he’d written outlining some good points about Java vs Clojure:</p>
<blockquote class="twitter-tweet" data-conversation="none" lang="en"><p><a href="https://twitter.com/slipset">@slipset</a> I've found the opposite - lack of refactoring support is one of my (very few) gripes about <a href="https://twitter.com/search?q=%23Clojure&src=hash">#Clojure</a>. see: <a href="http://t.co/oqRYCrdkU0">http://t.co/oqRYCrdkU0</a></p>— Mike (@mikera) <a href="https://twitter.com/mikera/statuses/439973631645319168">March 2, 2014</a></blockquote>
<p>Then <a href="https://twitter.com/@odinodin">@odinodin</a> tweeted</p>
<blockquote class="twitter-tweet" data-conversation="none" lang="en"><p><a href="https://twitter.com/slipset">@slipset</a> why isn’t there the same need for refactoring support? Just curious about what you’re thinking about</p>— Odin Hole Standal (@odinodin) <a href="https://twitter.com/odinodin/statuses/440065048971857920">March 2, 2014</a></blockquote>
<p>So I thought I’d share some (deeper) thoughts on this.</p>
<h2 id="disclaimer">Disclaimer</h2>
<p>I’ve only coded Clojure for a bit over a month, only written close to
1000 lines of code, and I’m the only person working on this project.</p>
<h2 id="what-kind-of-refactorings-and-other-tools-do-i-use-when-working-in-java">What kind of refactorings and other tools do I use when working in Java?</h2>
<p>Previously, I’ve had the opinion that working in a language which has
less IDE support than Java would be a no-starter, and I still
cannot imagine coding in Java without refactoring and
Intellisense. Which I to some extent miss in Javascript as well.</p>
<p>As for the refactorings I use in Java, I guess extract method,
various renames (method, class, packagae) are the ones I use
most. I do not consider cleaning up imports a refactoring, that’s
just cleanup.</p>
<h2 id="why-dont-i-miss-this-in-clojure">Why don’t I miss this in Clojure</h2>
<p>I’m not sure why I don’t miss these things in Clojure, but I do
notice a couple of things:</p>
<h3 id="working-in-the-repl">Working in the repl</h3>
<p>Since all my development happens in the REPL, I have a workflow
which consists of</p>
<ol>
<li>Make stuff work</li>
<li>Clean it up</li>
<li>recur 0</li>
<li>When happy, I move the code into the file it belongs</li>
</ol>
<p>This leads to code that is much more worked through than the stuff
you bang out in Java</p>
<h3 id="working-with-higher-abstractions">Working with higher abstractions</h3>
<p>Since Clojure lets you work with higher-order functions and has the
great sequence abstraction, you never end up with code lik this:</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">foreach</span> <span class="o">(</span><span class="nc">Foo</span> <span class="nl">f:</span> <span class="n">foos</span><span class="o">)</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(</span><span class="n">foo</span><span class="o">.</span><span class="na">getBaz</span><span class="o">()</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">&&</span> <span class="n">foo</span><span class="o">.</span><span class="na">getOmg</span><span class="o">()</span> <span class="o">!=</span> <span class="no">HAPPENING</span><span class="o">)</span> <span class="o">{</span>
<span class="n">bars</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">foo</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="k">return</span> <span class="n">bars</span><span class="o">;</span></code></pre></figure>
<p>Which I probably would refactor into something like:</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">foreach</span> <span class="o">(</span><span class="nc">Foo</span> <span class="nl">f:</span> <span class="n">foos</span><span class="o">)</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(!</span><span class="n">foo</span><span class="o">.</span><span class="na">isBar</span><span class="o">())</span> <span class="k">continue</span><span class="o">;</span>
<span class="n">bars</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">foo</span><span class="o">);</span>
<span class="o">}</span>
<span class="k">return</span> <span class="n">bars</span><span class="o">;</span></code></pre></figure>
<p>Which includes extract method.</p>
<p>In Clojure this is</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nb">filter</span><span class="w"> </span><span class="o">#</span><span class="p">(</span><span class="nb">and</span><span class="w"> </span><span class="p">(</span><span class="no">:baz</span><span class="w"> </span><span class="n">%</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nb">=</span><span class="w"> </span><span class="p">(</span><span class="no">:omg</span><span class="w"> </span><span class="n">%</span><span class="p">)</span><span class="w"> </span><span class="no">:happening</span><span class="p">))</span><span class="w"> </span><span class="n">foos</span><span class="p">)</span></code></pre></figure>
<p>Pulling out the predicat here is just a <tt>C-M-k</tt> away (plus
some more stuff ;) so the refactor is done so fast I don’t even
have time to miss a refactoring tool.</p>
<h3 id="dense-code">Dense code</h3>
<p>It has also dawned upon me that since Clojure is so dense, eg lots
of stuff happening in few lines of code, I really need to be
prudent when organizing my code. If I let a function become longer
than 10 lines, I’m lost, so I constantly mold my code to keep it
understandable.</p>
<p>Also, files with more than 150 lines of code makes my head explode,
so I constantly move stuff into other packages.</p>
<h3 id="but-isnt-this-what-refactoring-tools-help-you-with">But isn’t this what refactoring tools help you with?</h3>
<p>No, not the way I look at refactoring. Because refactoring for me
is taking something that is functionally finished, even deployed,
and reorganizing it mechanically. The stuff I mention above is stuff
I <em>while</em> developing, not after. Put in another way, working in the
REPL, I constantly refactor stuff before it even has a chance to become a big hairy
ball of mud.</p>
<h3 id="all-the-helpers-are-written">All the helpers are written</h3>
<p>Also I find that extracting stuff to smaller helper
functions/classes like I do in Java is no longer needed since these
methods seem to be already implemented in Clojure.</p>
<p>Classic Java</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="k">if</span> <span class="o">(</span><span class="n">number</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="o">)</span> <span class="o">{</span>
<span class="n">evens</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">number</span><span class="o">);</span>
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
<span class="n">odds</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">number</span><span class="o">);</span>
<span class="o">}</span></code></pre></figure>
<p>clojure</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">group-by</span><span class="w"> </span><span class="n">odd?</span><span class="w"> </span><span class="p">(</span><span class="nb">range</span><span class="w"> </span><span class="mi">10</span><span class="p">))</span></code></pre></figure>
<p>In Java, I’d probably extract <tt>isOdd(int i)</tt> whereas in
Clojure, that’s already done.</p>
<h3 id="functional-code-leeds-to-less-intertwinedness">Functional code leeds to less intertwinedness</h3>
<p>It seems like when banging out some Java-code, even if you take
care, way too many functions seem to know about far too much common
stuff - normally you’d have three methods operating on the same
hashmap or something like this.</p>
<p>In Clojure you simply don’t.</p>
<h2 id="summary">Summary</h2>
<p>So I guess that the combination of the REPL, the sequence
abstraction, dense code, and my stupidity leeds me to writing code
that doesn’t need too much after-the-fact refactoring.</p>
What I want from a good api2014-01-28T09:17:35+00:00http://slipset.github.io/posts/what-do-i-want-from-a-good-api<p>Christian Johansen tweeted </p>
<blockquote lang="en">
<p>What's your favorite API documentation?</p>— Christian Johansen (@cjno) <a href="https://twitter.com/cjno/statuses/428040954965422080">January 28, 2014</a>
</blockquote>
<p>this morning to which I answered </p>
<blockquote lang="en">
<p><a href="https://twitter.com/cjno">@cjno</a> The source</p>— Erik Assum (<a href="https://github.com/slipset" class="user-mention">@slipset</a>) <a href="https://twitter.com/slipset/statuses/428050172728578048">January 28, 2014</a>
</blockquote>
<p>He obviously was not impressed by that answer, so that got me thinking, what do I want out of a good api (documentation)</p>
<p>First and foremost, I want an api which lets me do what I need to do without learning everything about the api before getting my stuff done. So to start off, with one of the examples that Christian brought up in a later tweet, say I wanted to do something with Facebook.</p>
<p>First of all I’d like to have a client library in my favourite language so I could say something like:</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kd">var</span> <span class="nx">fb</span> <span class="o">=</span> <span class="nx">Facebook</span><span class="p">.</span><span class="nx">login</span><span class="p">(</span><span class="dl">'</span><span class="s1">john@doe.com</span><span class="dl">'</span><span class="p">,</span> <span class="nx">password</span><span class="p">);</span>
<span class="nx">fb</span><span class="p">.</span><span class="nx">friends</span><span class="p">().</span><span class="nx">map</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">f</span><span class="p">)</span> <span class="p">{</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">this is my friend </span><span class="dl">"</span> <span class="o">+</span> <span class="nx">f</span> <span class="p">)};</span>
<span class="nx">fb</span><span class="p">.</span><span class="nx">news</span><span class="p">().</span><span class="nx">map</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">n</span><span class="p">)</span> <span class="p">{</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">this is my wall </span><span class="dl">"</span> <span class="o">+</span> <span class="nx">n</span> <span class="p">)};</span>
<span class="kd">var</span> <span class="nx">friend</span> <span class="o">=</span> <span class="nx">fb</span><span class="p">.</span><span class="nx">findFriend</span><span class="p">({</span><span class="na">firstName</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Ola</span><span class="dl">'</span><span class="p">,</span> <span class="na">lastName</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Dunk</span><span class="dl">'</span><span class="p">});</span>
<span class="nx">fb</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="nx">f</span><span class="p">,</span> <span class="p">{</span><span class="na">title</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Hi Ola</span><span class="dl">'</span><span class="p">,</span> <span class="na">text</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Check out this cool api</span><span class="dl">'</span><span class="p">});</span>
<span class="nx">fb</span><span class="p">.</span><span class="nx">logout</span><span class="p">();</span></code></pre></figure>
<p>Having no idea what the Facebook api looks like, but some of the things I want: I want an api which speaks in the clients language and which is optimized for the clients tasks.</p>
<p>So I guess for an api like this I would like some tutorials which showed me how to achieve some common tasks, and then, yes, I’d love to be able to see the code behind it, so I could figure out how to do the stuff the api-designer didn’t know I wanted to do.</p>
<p>So to answer @cjno, the documentation I want for an api is a set of annotated, <em>working</em>, tutorials which show me how common tasks are achieved. If I then also could have access to the sources, I’d be as happy as could be. <a href="http://harshen.github.io/jquery-share/">This</a> is probably a good example.</p>
Functional vs object oriented2013-11-01T17:38:00+00:00http://slipset.github.io/posts/functional-vs-object-oriented<p>As a mainly programmer working in mainly in Java, but also using Ext.js for frontend development, most of our code is object-oriented, that is stuff like:</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">Ext</span><span class="p">.</span><span class="nx">define</span><span class="p">(</span><span class="dl">'</span><span class="s1">app.model.room.Room</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
<span class="na">extend</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Ext.data.Model</span><span class="dl">'</span><span class="p">,</span>
<span class="p">...</span>
<span class="na">isFooEnabled</span><span class="p">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="o">!!</span><span class="k">this</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">fooEnabled</span><span class="dl">'</span><span class="p">);</span>
<span class="p">},</span>
<span class="p">});</span></code></pre></figure>
<p>Which, when you code in a normal, oo/imperative style, leads to code like this:</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">giefFooRooms</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">rooms</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">fooRooms</span> <span class="o">=</span> <span class="p">[];</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">rooms</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span> <span class="o">=</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">rooms</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">isFooEnabled</span><span class="p">())</span> <span class="p">{</span>
<span class="nx">fooRooms</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">rooms</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">fooRooms</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>Having an interest in functional programming, and not being able to switch to Scala at my day-time job, I often try to write this in a more functional manner, like:</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">giefFooRooms</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">rooms</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">rooms</span><span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">r</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">r</span><span class="p">.</span><span class="nx">isFooEnabled</span><span class="p">();</span> <span class="p">});</span>
<span class="p">}</span></code></pre></figure>
<p>Which leads me to my problem. Since in a more functional setting, you’d implemented this like:</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">fooEnabledp</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">room</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="o">!!</span><span class="nx">room</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">fooEnabled</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="nl">giefFooRooms</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">rooms</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">rooms</span><span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">fooEnabledp</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>
<p>Which leads to some sort of a break in paradigm, since the former is an example of enriching data with functionality (albeit a simple one in this example) and the latter is an example of functions operating on data, and mixing the two paradigms in one project sort of give me a head ache.</p>
<p>To round this off, here’s another example of this one impelemented in Javascript, which shows the extra boilerplate code needed in a non-functional language, and the other in emacs-lisp which shows how it should be done.</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="p">[</span><span class="dl">"</span><span class="s2">a</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">b</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">c</span><span class="dl">"</span><span class="p">].</span><span class="nx">map</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">s</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">s</span><span class="p">.</span><span class="nx">toUpperCase</span><span class="p">();});</span>
<span class="c1">//=> ["A", "B", "C"]`</span></code></pre></figure>
<figure class="highlight"><pre><code class="language-lisp" data-lang="lisp"><span class="p">(</span><span class="nb">mapcar</span> <span class="ss">'upcase</span> <span class="o">'</span><span class="p">(</span><span class="s">"a"</span> <span class="s">"b"</span> <span class="s">"c"</span><span class="p">))</span>
<span class="c1">;=> ("A" "B" "C")</span></code></pre></figure>