<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Janet A. Carr]]></title><description><![CDATA[Clojurian thought: A Clojure programming language blog]]></description><link>https://blog.janetacarr.com/</link><image><url>https://blog.janetacarr.com/favicon.png</url><title>Janet A. Carr</title><link>https://blog.janetacarr.com/</link></image><generator>Ghost 5.79</generator><lastBuildDate>Tue, 20 Feb 2024 08:47:23 GMT</lastBuildDate><atom:link href="https://blog.janetacarr.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Building a Clojure CI/CD pipeline of CERTAIN DOOM]]></title><description><![CDATA[<h3 id="when-things-go-wrong">When things go wrong</h3><p>Devops is one of those important positions where nobody cares what you&apos;re doing until things stop working. Along with SRE folks, the position may as well be akin to a firefighter. I know this first hand having been a loaded-title myself. You haven&apos;</p>]]></description><link>https://blog.janetacarr.com/building-a-clojure-ci-cd-pipeline/</link><guid isPermaLink="false">65733d93fbf7870001c415f8</guid><category><![CDATA[clojure]]></category><category><![CDATA[clojurescript]]></category><category><![CDATA[computer programming]]></category><category><![CDATA[functional programming]]></category><category><![CDATA[software development]]></category><category><![CDATA[software engineering]]></category><dc:creator><![CDATA[Janet A. Carr]]></dc:creator><pubDate>Mon, 11 Dec 2023 19:55:21 GMT</pubDate><media:content url="https://blog.janetacarr.com/content/images/2023/12/carbon-80.png" medium="image"/><content:encoded><![CDATA[<h3 id="when-things-go-wrong">When things go wrong</h3><img src="https://blog.janetacarr.com/content/images/2023/12/carbon-80.png" alt="Building a Clojure CI/CD pipeline of CERTAIN DOOM"><p>Devops is one of those important positions where nobody cares what you&apos;re doing until things stop working. Along with SRE folks, the position may as well be akin to a firefighter. I know this first hand having been a loaded-title myself. You haven&apos;t really lived until you get paged at 2am because something is wrong with the deploys in South East Asia. </p><p>Like any software &quot;engineering&quot; position, there&apos;s an art and skill to determining what might be wrong, usually because you didn&apos;t build the shit yourself. That&apos;s okay though. We learn from experience and move on. Or, if you&apos;re reading my blog, you learn from me and my experience, and I receive warm-fuzzies in exchange. So, if I&apos;m in a position where I have to create a Clojure CI/CD pipeline, as I often am, here&apos;s what I usually do.</p><h3 id="continuous-irritation-ci">Continuous Irritation (CI)</h3><p>I&apos;m not certain, but I think Continuous Integration means continuous build pipeline minutes billed to clients. Most clients use everybody&apos;s favourite version control: Github. When they&apos;re not trying to destroy the Software developer profession, Github serves as managed Git repositories. In the realm of professional software development, services like Github and Gitlab (and BitBucket, if you&apos;re a corpo) have completely supplanted managing Git repositories by hand. It is where our code lives, but you already know that.</p><p>Github comes with a dandy little package management solution as well. You just didn&apos;t look hard enough because it&apos;s covered in dust. Seriously, I haven&apos;t met anyone who uses the Github Packages private maven repository except for me. So lets go ahead and set that up.</p><p>Setting up Github Packages for private use is remarkably similar to setting up an AWS S3 bucket as our private repository:</p><figure class="kg-card kg-code-card"><pre><code class="language-XML">&lt;settings xmlns=&quot;http://maven.apache.org/SETTINGS/1.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
          xsi:schemaLocation=&quot;http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd&quot;&gt;

  &lt;servers&gt;
    &lt;server&gt;
      &lt;id&gt;github&lt;/id&gt;
      &lt;username&gt;GITHUB_USERNAME_HERE&lt;/username&gt;
      &lt;password&gt;PERSONAL_ACCESS_TOKEN_HERE&lt;/password&gt;
    &lt;/server&gt;
  &lt;/servers&gt;

&lt;/settings&gt;</code></pre><figcaption><p><span style="white-space: pre-wrap;">settings.xml</span></p></figcaption></figure><p>Put this in your <code>~/.m2/settings.xml</code> file. You&apos;ll notice it requires a Github Personal Access Token (with Github Packages Read &amp; Write permissions). This will give maven the credentials to deploy to Github Packages. Depending on your Github subscription, this can cost money. </p><p>Now we have to come up with a method to deploy if we want to deploy. I think using a tools.build script fits the bill perfectly. Let&apos;s go ahead and create a build alias in <code>deps.edn</code>: </p><pre><code class="language-clojure">...
:aliases {:build {:deps {slipset/deps-deploy {:mvn/version &quot;0.2.0&quot;}
                          io.github.clojure/tools.build {:mvn/version &quot;0.9.6&quot;}}
                   :ns-default build}}
...</code></pre><p>We&apos;re going to use deps-deploy to help us deploy our code, but we&apos;ll get to the deploying in a bit. First let&apos;s focus on building the thing with our <code>build.clj</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">(ns build
  (:refer-clojure :exclude [test])
  (:require [clojure.tools.build.api :as b]
            [deps-deploy.deps-deploy :as dd]))

(def lib &apos;com.janetacarr/clojure-for-pros)
(def version (format &quot;0.1.%s&quot; (b/git-count-revs nil)))
(def class-dir &quot;target/classes&quot;)
(def basis (b/create-basis {:project &quot;deps.edn&quot;}))
(def uber-file (format &quot;target/%s-%s-standalone.jar&quot; (name lib) version))

(defn clean [_]
  (b/delete {:path &quot;target&quot;}))

(defn uber [_]
  (clean nil)
  (b/copy-dir {:src-dirs [&quot;src&quot; &quot;public&quot;]
               :target-dir class-dir})
  (b/compile-clj {:basis basis
                  :ns-compile &apos;[clojure-for-pros.core]
                  :class-dir class-dir})
  (b/uber {:class-dir class-dir
           :uber-file uber-file
           :basis basis
           :main &apos;clojure-for-pros.core}))
</code></pre><figcaption><p><span style="white-space: pre-wrap;">build.clj</span></p></figcaption></figure><p>Our <code>build.clj</code> copies our source code to our working directory, <code>class-dir</code>, with the <code>copy-dir</code> function. Then, <code>compile-clj</code> compiles our Clojure source files as described in the <code>basis</code> to the working directory. The basis, or runtime basis, is a configuration map that contains the source directories from <code>deps.edn</code> as well as runtime information like dependencies. Then it&apos;s also used to bundle the working directory into an uberjar with <code>b/user</code>. Now we can create a the uberjar with the command <code>clj -T:build uber</code> from the project directory, and run the jar with <code>java -jar target/clojure-for-pros-standalone.jar</code>. </p><h3 id="continuous-distraction-cd">Continuous Distraction (CD)</h3><p>So far, this is straight out of the <a href="https://clojure.org/guides/tools_build?ref=blog.janetacarr.com" rel="noreferrer">tools.build Guide</a> (mostly).  What we really need to do is write a deploy function. Simple enough thanks to deps-deploy:</p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">(ns build
  (:refer-clojure :exclude [test])
  (:require [clojure.tools.build.api :as b]))

(def lib &apos;com.janetacarr/clojure-for-pros)
(def version (format &quot;0.1.%s&quot; (b/git-count-revs nil)))
(def class-dir &quot;target/classes&quot;)
(def basis (b/create-basis {:project &quot;deps.edn&quot;}))
(def uber-file (format &quot;target/%s-standalone.jar&quot; (name lib)))

(defn clean [_]
  (b/delete {:path &quot;target&quot;}))

(defn uber [_]
  (clean nil)
  (b/copy-dir {:src-dirs [&quot;src&quot; &quot;public&quot;]
               :target-dir class-dir})
  (b/compile-clj {:basis basis
                  :ns-compile &apos;[clojure-for-pros.core]
                  :class-dir class-dir})
  (b/uber {:class-dir class-dir
           :uber-file uber-file
           :basis basis
           :main &apos;clojure-for-pros.core}))

(defn deploy [_]
  (let [dd-deploy (try (requiring-resolve &apos;deps-deploy.deps-deploy/deploy) (catch Throwable _))]
    (if dd-deploy
      (dd-deploy {:installer :remote
                  :artifact (b/resolve-path uber-file)
                  :repository &quot;github&quot;
                  :pom-file (b/pom-path {:lib lib 
                                         :class-dir class-dir})})
      (println &quot;borked&quot;))))
</code></pre><figcaption><p><span style="white-space: pre-wrap;">build.clj with deploy function</span></p></figcaption></figure><p>Running <code>clj -T:build deploy</code> comes back with an interesting error:</p><figure class="kg-card kg-code-card"><pre><code class="language-shell">:repository has value github which is an unknown :mvn/repos
Execution error (FileNotFoundException) at java.io.FileInputStream/open0 (FileInputStream.java:-2).
/Users/janet/clojure-for-pros/target/classes/META-INF/maven/com.janetacarr/clojure-for-pros/pom.xml (No such file or directory)

Full report at:
/var/folders/py/pc9dw_557nl93lsc4npft5j00000gn/T/clojure-6437169465784041420.edn</code></pre><figcaption><p><span style="white-space: pre-wrap;">Predictable Cryptic Error</span></p></figcaption></figure><p>What the heck is a pom.xml file? A POM file, as it&apos;s called, is an XML file that contains data Maven uses to build a project. It also happens to be where our Maven repository data will live. A Maven repository needs an artifact(jar) POM file to determine the coordinates of the artifact. We could write a <code>pom.xml</code> file for our project and write its contents to our working directory. In fact, tools.build has a function expressly for this purpose called <code>write-pom</code>. So let&apos;s go ahead and do that.</p><pre><code class="language-clojure">;; updated uber function from clojure-for-pros
;; build.clj file
(defn uber [_]
  (clean nil)
  ;; default pom file path is &quot;./pom.xml&quot;
  (b/write-pom {:class-dir class-dir
                :lib lib
                :version version
                :basis basis
                :src-dirs [&quot;src&quot;]}) 
  (b/copy-dir {:src-dirs [&quot;src&quot; &quot;public&quot;]
               :target-dir class-dir})
  (b/compile-clj {:basis basis
                  :ns-compile &apos;[clojure-for-pros.core]
                  :class-dir class-dir})
  (b/uber {:class-dir class-dir
           :uber-file uber-file
           :basis basis
           :main &apos;clojure-for-pros.core}))</code></pre><p>And we need a pom.xml file too. Most of the final POM in our uberjar will be generated by the run-time basis, but we need this bit for our private maven repo:</p><pre><code class="language-XML">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;
  &lt;distributionManagement&gt;
    &lt;repository&gt;
      &lt;id&gt;github&lt;/id&gt;
      &lt;name&gt;janetacarr github packages&lt;/name&gt;
      &lt;url&gt;https://maven.pkg.github.com/janetacarr/clojure-for-pros&lt;/url&gt;
    &lt;/repository&gt;
  &lt;/distributionManagement&gt;
&lt;/project&gt;
</code></pre><p>We also need to add a <code>:mvn/repos</code> key-value pair to the top-level of <code>deps.edn</code>. This will take care of the &quot;:repository has value github which is an unknown :mvn/repos&quot; error message.</p><pre><code class="language-clojure">:mvn/repos {&quot;github&quot; {:url &quot;https://maven.pkg.github.com/janetacarr/clojure-for-pros&quot;}}</code></pre><p>Finally, we can deploy with <code>clj -T:build deploy</code>. </p><pre><code class="language-shell">$ clj -T:build deploy
Deploying com.janetacarr/clojure-for-pros-0.1.11 to repository github as janetacarr
Sending com/janetacarr/clojure-for-pros/0.1.11/clojure-for-pros-0.1.11.pom (7k)
    to https://maven.pkg.github.com/janetacarr/clojure-for-pros/
Sending com/janetacarr/clojure-for-pros/0.1.11/clojure-for-pros-0.1.11-standalone.jar (671195k)
    to https://maven.pkg.github.com/janetacarr/clojure-for-pros/
Retrieving com/janetacarr/clojure-for-pros/maven-metadata.xml (1k)
    from https://maven.pkg.github.com/janetacarr/clojure-for-pros/
Sending com/janetacarr/clojure-for-pros/maven-metadata.xml (1k)
    to https://maven.pkg.github.com/janetacarr/clojure-for-pros/</code></pre><h3 id="trust-me-bro">Trust me, bro</h3><p>Since this is all done in a private repository, it feels very &quot;trust me, bro&quot;, so I&apos;m going to do similar things for an open-source library on my Github called <a href="https://github.com/janetacarr/quadtree-cljc?ref=blog.janetacarr.com" rel="noreferrer">quadtree-cljc</a>. quadtree-cljc is just a library for building <a href="https://en.wikipedia.org/wiki/Quadtree?ref=blog.janetacarr.com" rel="noreferrer">quadtrees</a> and finding out which nodes intersect. </p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">(ns build
  (:require [clojure.tools.build.api :as b]))

(def lib &apos;com.janetacarr/quadtree-cljc)
(def version &quot;0.1.4&quot;)
(def class-dir &quot;target/classes&quot;)
(def basis (b/create-basis {:project &quot;deps.edn&quot;}))
(def jar-file (format &quot;target/%s-%s.jar&quot; lib version))

(defn clean [_]
  (b/delete {:path &quot;target&quot;}))

(defn- pom-template [version]
  [[:description &quot;A quadtree implementation for Clojure(script)&quot;]
   [:url &quot;https://github.com/janetacarr/quadtree-cljc&quot;]
   [:licenses
    [:license
     [:name &quot;APACHE LICENSE, VERSION 2.0&quot;]
     [:url &quot;https://www.apache.org/licenses/LICENSE-2.0&quot;]]]
   [:developers
    [:developer
     [:name &quot;Janet A. Carr&quot;]]]
   [:scm
    [:url &quot;https://github.com/janetacarr/quadtree-cljc&quot;]
    [:connection &quot;scm:git:https://github.com/janetacarr/quadtree-cljc.git&quot;]
    [:developerConnection &quot;scm:git:ssh://git@github.com/janetacarr/quadtree-cljc.git&quot;]
    [:tag version]]])

(defn jar [_]
  (clean nil)
  (b/write-pom {:class-dir class-dir
                :lib lib
                :version version
                :basis basis
                :src-dirs [&quot;src&quot;]
                :pom-data (pom-template version)})
  (b/copy-dir {:src-dirs [&quot;src&quot;]
               :target-dir class-dir})
  (b/jar {:class-dir class-dir
          :jar-file jar-file}))

(defn deploy
  [{:keys [repository] :as opts}]
  (let [dd-deploy (try (requiring-resolve &apos;deps-deploy.deps-deploy/deploy) (catch Throwable _))]
    (if dd-deploy
      (dd-deploy {:installer :remote
                  :artifact (b/resolve-path jar-file)
                  :repository (or (str repository) &quot;clojars&quot;)
                  :pom-file (b/pom-path {:lib lib
                                         :class-dir class-dir})})
      (println &quot;borked&quot;))))

</code></pre><figcaption><p><span style="white-space: pre-wrap;">build.clj for quadtree-cljc</span></p></figcaption></figure><p>Since quadtree-cljc is open-source, it might be a good idea to let developers choose where to upload this jar by default, this is where <code>repository</code> comes in. If we want to deploy to Github, we just use the command <code>clj -T:build deploy :repository github</code> provided we have both the <code>pom.xml</code> and<code>deps.edn</code> <code>:mvn/repos</code> set up correctly for quadtree-cljc like above. Because I also deploy quadtree-cljc to <a href="https://clojars.org/?ref=blog.janetacarr.com" rel="noreferrer">Clojars</a>, I opted for <code>pom-template</code> (with a licenses) using hiccup style syntax instead of having a <code>pom.xml</code>. </p><h3 id="actions-speak-louder-than-words">Actions speak louder than words</h3><p>Creating JARs and putting them into Maven repos isn&apos;t really a CI/CD pipeline now is it? Ideally, we&apos;d have a Github Organization account, and use Github packages to store library JARs and our app Docker Images, gluing it all together with Github Actions or CircleCI (or Jenkins, corpo). I don&apos;t want to pay for Github Organizations, so let&apos;s go ahead and set up some Github Actions on regular Github.</p><p>For quadtree-cljc we&apos;ll set up a Github Actions to build our jar and deploy it to clojars whenever a pull request (PR) is merged into master. It&apos;s also probably a good idea that the Action trigger, test, and build the PR code before a merge. You can find the Github Action YAML <a href="https://github.com/janetacarr/quadtree-cljc/blob/main/.github/workflows/ci.yml?ref=blog.janetacarr.com" rel="noreferrer">here</a>. </p><p>We&apos;ll do something similar for clojure-for-pros. Instead of just deploying the uberjar to Github&apos;s private Maven repo, we&apos;re going to build a Docker image that will run the uberjar, and then trigger a deploy to production with the Docker image. </p><figure class="kg-card kg-code-card"><pre><code class="language-yaml">name: Clojure Uberjar and Docker CI/CD

on:
  pull_request:
    branches: [ master, main ]
  push:
    branches: [ master, main ]

jobs:
  build-and-push-docker:
    runs-on: ubuntu-latest
    needs: build-and-test-uberjar
    if: github.event_name == &apos;push&apos; &amp;&amp; (github.ref == &apos;refs/heads/master&apos; || github.ref == &apos;refs/heads/main&apos;)
    steps:
      - uses: actions/checkout@v2
      - name: Set up JDK 20
        uses: actions/setup-java@v2
        with:
          java-version: &apos;20&apos;
          distribution: &apos;temurin&apos;
      - name: Install Clojure
        run: |
          curl -L -O https://github.com/clojure/brew-install/releases/latest/download/posix-install.sh
          chmod +x posix-install.sh
          sudo ./posix-install.sh
      - name: Build Uberjar
        run: clojure -T:build uber
      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v1
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GH_PAT }}
      - name: Build and push Docker image
        run: |
          docker build --platform=linux/amd64 -t ghcr.io/${{ github.repository }}/clojure-for-pros:${{ github.sha }} .
          docker push ghcr.io/${{ github.actor }}/clojure-for-pros:${{ github.sha }}
          docker push ghcr.io/${{ github.actor }}/clojure-for-pros:latest

</code></pre><figcaption><p><span style="white-space: pre-wrap;">A semi-real github action</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code>FROM clojure:temurin-20-alpine
COPY . /app
WORKDIR /app

ENV DATABASE_URL=jdbc:postgresql://localhost:5432/postgres?user=postgres\&amp;password=postgres
ENV PORT=8080
ENV API_HOST=localhost:8080
ENV CLOUDFRONT_KEY=&quot;&quot;
ENV TOKEN_SECRET=&quot;&quot;
ENV DEV_MODE=false

CMD java -jar target/clojure-for-pros.jar</code></pre><figcaption><p><span style="white-space: pre-wrap;">Totally secure Dockerfile</span></p></figcaption></figure><h3 id="party-time">Party Time</h3><figure class="kg-card kg-image-card kg-width-wide"><img src="https://blog.janetacarr.com/content/images/2023/12/Clojure-CI_CD-Pipeline-5-2.png" class="kg-image" alt="Building a Clojure CI/CD pipeline of CERTAIN DOOM" loading="lazy" width="2000" height="1096" srcset="https://blog.janetacarr.com/content/images/size/w600/2023/12/Clojure-CI_CD-Pipeline-5-2.png 600w, https://blog.janetacarr.com/content/images/size/w1000/2023/12/Clojure-CI_CD-Pipeline-5-2.png 1000w, https://blog.janetacarr.com/content/images/size/w1600/2023/12/Clojure-CI_CD-Pipeline-5-2.png 1600w, https://blog.janetacarr.com/content/images/size/w2400/2023/12/Clojure-CI_CD-Pipeline-5-2.png 2400w" sizes="(min-width: 1200px) 1200px"></figure><p>Once all that is done, we can trigger a deploy from a Github Action. I primarily deploy on <a href="render.com" rel="noreferrer">Render</a>. It&apos;s like a Heroku competitor. Typically, If I&apos;m lazy (I am), I&apos;ll just build the docker image inside the Render build pipeline and be done with it. </p><p>But, this is a CI/CD pipeline, damn it! We&apos;re going to do the real thing&#x2122;&#xFE0F; and set up deploys to production. Here&apos;s a job to hit Render&apos;s deploy hook when the Docker image is built.</p><pre><code class="language-yaml">....
  notify-render:
    runs-on: ubuntu-latest
    needs: build-and-push-docker
    if: github.event_name == &apos;push&apos; &amp;&amp; (github.ref == &apos;refs/heads/master&apos; || github.ref == &apos;refs/heads/main&apos;)
    steps:
      - name: Notify Render.com
        run: |
          curl https://api.render.com/deploy/srv-fakefakefakefake?key=${{ secrets.RENDER_API_TOKEN }}</code></pre><p>And there you have it. A Clojure CI/CD pipeline. With the right credentials, builds can pull dependencies and Docker images from Github Packages. </p><h3 id="conclusion">Conclusion</h3><p>None of this is very trivial to understand. Most of it is buried in obscure blog posts, documentation, and codebases, but is a core piece of a Software Architecture, so I felt it deserved along blog post of it&apos;s own. </p><p>I do want to give a huge shout out to Sean Corfield for his now deprecated <a href="https://github.com/seancorfield/build-clj/blob/main/src/org/corfield/build.clj?ref=blog.janetacarr.com" rel="noreferrer">build-clj</a> helper library. Between that and the tools.build documentation, I was able to work through this. </p><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-text"><i><em class="italic" style="white-space: pre-wrap;">And now the part where I shamelessly self promote myself. I am a Clojure(script) consultant/freelancer, so I&apos;m always starving for a new gig. I also have a Clojure course </em></i><a href="https://clojureforpros.com/?ref=blog.janetacarr.com"><i><em class="italic" style="white-space: pre-wrap;">available</em></i></a><i><em class="italic" style="white-space: pre-wrap;"> for early access if you&apos;re into that kind of thing. You can also follow me on Twitter and around the web </em></i><a href="https://x.com/janetacarr?ref=blog.janetacarr.com"><i><em class="italic" style="white-space: pre-wrap;">@janetacarr</em></i></a><i><em class="italic" style="white-space: pre-wrap;"> , or not. &#xAF;\_(&#x30C4;)_/&#xAF;</em></i></div></div>]]></content:encoded></item><item><title><![CDATA[Thriving in the dynamically type-checked hell scape of Clojure]]></title><description><![CDATA[<p>People often come to me asking &quot;I love the idea of Clojure, but how do you write code without <em>types</em>?&quot;. I struggle to answer this question. I have no idea what they&apos;re talking about half the time. The nuance of strong and weak typing, and static</p>]]></description><link>https://blog.janetacarr.com/thriving-in-the-dynamically-type-checked-hell-scape-of-clojure/</link><guid isPermaLink="false">64bbc948a287fa0001182122</guid><dc:creator><![CDATA[Janet A. Carr]]></dc:creator><pubDate>Mon, 24 Jul 2023 16:27:59 GMT</pubDate><media:content url="https://blog.janetacarr.com/content/images/2023/07/FiLgjPVWQAAL8u6-1.jpeg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.janetacarr.com/content/images/2023/07/FiLgjPVWQAAL8u6-1.jpeg" alt="Thriving in the dynamically type-checked hell scape of Clojure"><p>People often come to me asking &quot;I love the idea of Clojure, but how do you write code without <em>types</em>?&quot;. I struggle to answer this question. I have no idea what they&apos;re talking about half the time. The nuance of strong and weak typing, and static vs dynamic type checking, is often lost on people. I think they want their tools to tell them what to do. I don&apos;t struggle with that like others. I never have. It never occured to me that I might just be a <em>weirdo</em>.</p><h3 id="weird-life">Weird life</h3><p>Like a lot of things, I think I can directly attribute my cognitive model of writing code to <em>how</em> I learned to program. Right around the time I was getting into Linux in high-school and becoming a script kiddy. I learned how to program in C. At first on Windows with something called Bloodshed Dev C++, then I quickly graduated to the terminal because of this cool thing called <em>Linux</em>. I used GCC and GEdit for a long time. Not because I&apos;m some arogant asshole (debateable). I didn&apos;t really know better. Then my hacky brain <em>stole this book</em> called Hacking: The Art of Exploitation. At sixteen I learned how to disassemble the C programs I had written and attach GNU debugger (GDB) to examine memory, graduating from:</p><p><code>printf(&quot;HERE DUMBASS: %s&quot;, *buf);</code> </p><p>This &quot;bad&quot; habit of GEdit + command line followed me to University where I coasted and watched people new to programming struggle writing Java. I used it during labs, competitions, assignments, etc. The first time I was actually introduced to Eclipse was when my friend used it on our Intro to Software Engineering project.  </p><p>All of this was made worse when I finally dropped out of my Computer Science program to work in the industry. My first real developer job was writing Clojure, and the office preference was to use Emacs prelude + CIDER. </p><p>Every office has it problems, but what I quickly learned was that documentation was always out of date. I had to build the muscle memory to just read the code which wasn&apos;t out of date, ever. I suspect this is why I always find myself reading the Clojure source code for interesting technical nuggets. Even long after I was a Go developer, I still read code everywhere. </p><h3 id="okay-so-what">Okay, so what? </h3><p>The less code kept in the developer&apos;s head the better. The typical model of software development follows a loop of getting product requirements, understanding enough of the codebase to formulate a solution, and then implementing that solution. More code in the head leads to more complexity. </p><p>Blackboxing code addresses complexity by reducing something strictly to inputs and outputs. I think people coming from statically type-checked languages conflate complier errors and type declarations with <em>blackboxing</em>. In reality, they&apos;ve traded flexibility for guardrails. While I argee that dynamic type checking requires a little bit more cognitive load, docstrings and idioms cut down on cognitive load, and they are far more descriptive than type declarations on function arguments. </p><p>Similarly, by sending type mismatching off to the compile time, rather than runtime, those developers lose out on the flexibility on deciding what to do with that type mismatch. Of course, the type mismatch fault can mitigated by testing and assertions. Often, it doesn&apos;t matter in Clojure anyways. </p><p>While Clojure is a dynamically type-checked language, it is also <strong>strongly-typed</strong>. Clojure types are several types at once rather than implicitly converting types between function calls. Collections (vectors, maps, sets, and lists) adhere to enough type interfaces they work with many functions like <code>filter</code>, <code>reduce</code>, <code>partition</code>, <code>group-by</code>, etc. <code>get</code>, <code>assoc</code>, and <code>update</code> not only operate on maps, but can also operate on vectors and so on.</p><p>However, while developers might have a hard time shooting themselves in the foot, that doesn&apos;t mean they can&apos;t shoot their colleagues in the foot. Here&apos;s some ways to avoid that:</p><h3 id="idioms">Idioms</h3><p>Clojure idioms convey information about the type of value being passed a function, macro, and methods at a glance like type declarations. They are great for smaller, general functions. </p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">Follow clojure.core&apos;s example for idiomatic names like pred and coll.
in functions:

f, g, h - function input

n - integer input usually a size

index, i - integer index

x, y - numbers

xs - sequence

m - map

k, ks - key, keys

</code></pre><figcaption><p><span style="white-space: pre-wrap;">Excerpt from the Clojure </span><a href="https://guide.clojure.style/?ref=blog.janetacarr.com#idiomatic-names"><span style="white-space: pre-wrap;">style guide Idioms</span></a><span style="white-space: pre-wrap;"> section</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-clojure">(defn drop-last
  &quot;Return a lazy sequence of all but the last n (default 1) items in coll&quot;
  {:added &quot;1.0&quot;
   :static true}
  ([coll] (drop-last 1 coll))
  ([n coll] (map (fn [x _] x) coll (drop n coll))))</code></pre><figcaption><p><span style="white-space: pre-wrap;">drop-last using idioms as function args from </span><a href="https://github.com/clojure/clojure/blob/clojure-1.10.1/src/clj/clojure/core.clj?ref=blog.janetacarr.com#L2934"><span style="white-space: pre-wrap;">clojure.core</span></a></p></figcaption></figure><p>Idioms only capture part of the story, and are not entirely suitable for all cases. Sometimes, we want our bindings or argument names to convey more domain information. We can describe them in docstrings. </p><h3 id="docstrings">Docstrings</h3><p>Docstrings are first-class documentation for functions. Clojure tools like editors and documentation generators look at docstrings first, so It&apos;s important to do well. Docstrings should describe what the function does, takes as parameters, and returns. Use backticks functions parameters and other important bits like so:</p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">(defn insert
  &quot;Insert `bounds-obj` into the node, returning a freshly grown quadtree.
  If the node exceeds the capacity, it will split and add all objects to
  their corresponding subnodes.&quot;
  [quadtree bounds-obj]
  (let [{:keys [nodes objects bounds
                level max-levels
                max-objects objects]} quadtree
        all-objects (conj objects bounds-obj)]
    (if (pos? (count nodes))
      (as-&gt; quadtree quadtree
        (assoc quadtree :objects [])
        (reduce (fn [quadtree obj]
                  (let [quadrant (get-quadrant quadtree obj)
                        nodes (:nodes quadtree)]
                    (if quadrant
                      (merge quadtree {:nodes (assoc nodes
                                                     quadrant
                                                     (insert (nth nodes quadrant)
                                                             obj))})
                      (update quadtree :objects #(conj % obj)))))
                quadtree
                all-objects))
      (if (and (&gt; (count all-objects) max-objects) (&lt; level max-levels))
        (let [quadtree (if (empty? nodes) (split quadtree) quadtree)]
          (insert quadtree bounds-obj))
        (merge quadtree {:objects all-objects})))))</code></pre><figcaption><p><span style="white-space: pre-wrap;">insert from my quadtree-cljc library</span></p></figcaption></figure><h3 id="comments">Comments</h3><p>Similar to docstrings are Clojure&apos;s comments. These are comments like any other comments from any language, but Clojure comes with a couple more types of comments: </p><ul><li>semi-colon comments <code>;</code> - typical boring comments, completely ignored</li><li>reader comments <code>#_</code> - tells the reader to ignore the next form</li><li>rich comments <code>(comment ....)</code> - form evaluates contents, but unreachable</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-clojure">;; This comment is ignored by the complier
;; It&apos;s great for long form comments. 
;; and some editors allow storing and evaluating
;; REPL-like expressions here.

#_(defn hello [] (println &quot;This form ignored, and not evaluated&quot;))

(comment
  (def hello &quot;This comment IS evaluated, but not reachable by code))</code></pre><figcaption><p><span style="white-space: pre-wrap;">These are some of the best places to cuss in the codebase</span></p></figcaption></figure><h3 id="repl">REPL</h3><p>Some IDEs allow storing and evaluating REPL-like expressions in Clojure. If you haven&apos;t heard of a REPL, it&apos;s a Read-Eval-Print-Loop. Clojure features a robust REPL compared to other programming languages as developers can spin up their application process and access the state of the application <em>while it&apos;s running</em>.</p><p>It&apos;s great for debugging and hardening code, and the closest to thing to static type checked process of compiling and waiting for type errors. Except the Clojure REPL doesn&apos;t have to build the entire program again, so it can be much faster to iterate with than a statically type-checeked compiler. </p><p>Here&apos;s a dev script I use to bootstrap my process with the main entry point <code>:main-opts [&quot;dev.clj&quot;]</code> in my <code>deps.edn</code> alias. I use (CIDER) nREPL to connect to the process once it&apos;s running. </p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">(defmulti task first)

(defmethod task :default
  [[task-name]]
  (println &quot;Unknown task:&quot; task-name)
  (System/exit 1))

(defmethod task nil
  [_]
  (require &apos;[shadow.cljs.devtools.cli :as shadow])
  (require &apos;[app.core :as app])
  ((resolve &apos;app/-main))
  ((resolve &apos;shadow/-main) &quot;watch&quot; &quot;app&quot;))

(defmethod task &quot;repl&quot;
  [_]
  (clojure.main/repl :init #(doto &apos;app.core require in-ns)))

(task *command-line-args*)</code></pre><figcaption><p><span style="white-space: pre-wrap;">A dev.clj script I derived from </span><a href="https://github.com/oakes/play-cljc?ref=blog.janetacarr.com"><span style="white-space: pre-wrap;">play-cljc</span></a><span style="white-space: pre-wrap;">&apos;s</span></p></figcaption></figure><p>Once connected, I can <code>deref</code> the server atom or alter a root var to enable debug logs  or prototype functions for my current dev task. nREPL can be very handy to debug production systems as it can be used with a SSH tunnel for secure access. </p><h3 id="clojurespec">Clojure.spec</h3><p>My thoughts on spec are well known at this point. I really don&apos;t like bolting on quasi-static-but-at-run-time-type-checking. I find it&apos;s best used for the system boundaries to check and coerce input as well as some critical code pathways. Developers should exercise caution when using spec though. Codebases with too much spec suffer from rigidity, making changes harder. </p><p>Rigidity is brought on by the false promise of spec test generators (using spec to generate function test cases). If you want to use generators, you can&apos;t just sprinkle in some Clojure spec. Spec generators are great at generating obscure test cases. They create a cycle of tweaking functions and specs, so it doesn&apos;t generate unintended non-sense and the function can handle the desired input. I find the time spent on this has little value for the payoff and makes codebases more difficult to develop in. </p><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-text"><i><em class="italic" style="white-space: pre-wrap;">And now the part where I shamelessly self promote myself. I have a Clojure course </em></i><a href="https://clojureforpros.com/?ref=blog.janetacarr.com"><i><em class="italic" style="white-space: pre-wrap;">available for pre-order</em></i></a><i><em class="italic" style="white-space: pre-wrap;"> if you&apos;re into that kind of thing. You can also follow me on Twitter? X? Xitter </em></i><a href="https://x.com/janetacarr?ref=blog.janetacarr.com"><i><em class="italic" style="white-space: pre-wrap;">@janetacarr</em></i></a><i><em class="italic" style="white-space: pre-wrap;"> , or not. &#xAF;\_(&#x30C4;)_/&#xAF;</em></i></div></div>]]></content:encoded></item><item><title><![CDATA[Building an  Event-Driven Architecture in Clojure (Part 1)]]></title><description><![CDATA[Clojure has two types of publish/subscribe facilities built-in. The first is a watch, quite literally a first-class observer. The second, and the one we'll be using, is built into clojure's core.async library.]]></description><link>https://blog.janetacarr.com/building-an-event-driven-architecture-in-clojure-part-1/</link><guid isPermaLink="false">6493390bfbd733000117782e</guid><category><![CDATA[clojure]]></category><category><![CDATA[functional programming]]></category><category><![CDATA[software engineering]]></category><dc:creator><![CDATA[Janet A. Carr]]></dc:creator><pubDate>Fri, 14 Jul 2023 15:06:59 GMT</pubDate><media:content url="https://blog.janetacarr.com/content/images/2023/07/carbon-127.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.janetacarr.com/content/images/2023/07/carbon-127.png" alt="Building an  Event-Driven Architecture in Clojure (Part 1)"><p> If you&apos;ve ever wanted to build the event-processing startup of your dreams and exit for billions of dollars, this post is for you, or you just want to know how to code one. I didn&apos;t know how they worked at my first developer job. We had this events pipeline with all the frills: A highly-available event bus, definitions, consumers, producers, consumer-producers. I always figured the architecture just started like that. Right out of the gate, we&apos;re scalling for millions of events per second. Now that I fancy myself as a lean startup person (or whatever), I think a lot in terms of Minimum-Viable-Product (MVP).</p><p>You can use this architecture as your blueprint for any event handling service. I think the ideas here will translate well enough. If you&apos;re new to event-driven architecture, we decouple receiving events from processing events with one hell-of-a-buffer called an event bus. Consumers consume messages from the event bus, and producers produce messages by putting them on the event bus. We segregate the events by attributes or shape with some kind of publish/subscribe technique (or <em>message broker</em>).</p><p>Lucky for us, Clojure has two types of publish/subscribe facilities built-in. The first is a watch, quite literally a first-class <a href="https://blog.janetacarr.com/software-design-patterns-in-clojure/#observer">observer</a>. The second, channels, and the one we&apos;ll be using, is built into clojure&apos;s <a href="https://clojure.org/guides/async_walkthrough?ref=blog.janetacarr.com">core.async</a> library. It allows us to supply a function to create our publication topic. Let&apos;s use this for a stand-in until we hit millions of events and exit for billions with our new event-processing startup. </p><h3 id="enter-the-webhooks-as-a-service">Enter the Webhooks-as-a-Service</h3><p>Event driven architecture MVP is relatively straight forward. </p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://blog.janetacarr.com/content/images/2023/07/Event-driven-baby-architecture.png" class="kg-image" alt="Building an  Event-Driven Architecture in Clojure (Part 1)" loading="lazy" width="2000" height="533" srcset="https://blog.janetacarr.com/content/images/size/w600/2023/07/Event-driven-baby-architecture.png 600w, https://blog.janetacarr.com/content/images/size/w1000/2023/07/Event-driven-baby-architecture.png 1000w, https://blog.janetacarr.com/content/images/size/w1600/2023/07/Event-driven-baby-architecture.png 1600w, https://blog.janetacarr.com/content/images/size/w2400/2023/07/Event-driven-baby-architecture.png 2400w" sizes="(min-width: 1200px) 1200px"><figcaption>The internet is a series of tubes....</figcaption></figure><p>If you&apos;re a long time reader, you know where this is heading. We&apos;re going to sandwich our event-bus in between a few <a href="https://blog.janetacarr.com/mindset-shifts-for-functional-programming-with-clojure/">higher-order functions</a>. Not only can we decouple the event-bus from the application and swap it out for something more &apos;cloud&apos;, we can also supply a multimethod and dispatch on the incoming source or outgoing destination. Dispatching like that on a multimethod gives us the potential for having multiple event buses. Like a poor man&apos;s sharding, or in reality a way to deprioritize certain events. All from passing a function as an argrument!</p><p>Okay, real simple, lets create an event bus with a core.async channel, and we&apos;ll spin up our event bus and <em>message broker</em>. </p><pre><code class="language-clojure">(defn payment-received-consumer
  [events-chan]
  (a/go-loop [event (a/&lt;! events-chan)]
    ;; Do something with event
    (println &quot;Received payment&quot; event)))

(defn user-unsubscribed-consumer
  [events-chan]
  (a/go-loop [event (a/&lt;! events-chan)]
    ;; Do something with event
    (println &quot;User unsubscribed&quot; event)))

(defn -&gt;event-deserializer
  [publish-fn]
  (fn event-deserializer
    [event-chan]
    (a/go-loop [event (a/&lt;! event-chan)]
      (try
        (let [parsed-event (json/parse-string event)]
          (if (valid-event? parsed-event)
            (publish-fn parsed-event)
            (log/warn &quot;Dropping unsigned event: &quot; event)))
        (catch Exception e
          (log/error &quot;Internal error processing event: &quot;
                     event
                     (.getMessage e))))
      (recur (a/&lt;! event-chan)))))

(defn setup-consumer
  [consumer-fn publication topic]
  (let [consumer-chan (a/chan)]
    (a/sub publication topic consumer-chan)
    (consumer-fn consumer-chan)))

(def event-bus (a/chan 2048))
(def publication (a/pub event-bus :event-type))
(def payments-consumer (setup-consumer payment-received-consumer
                                       publication
                                       :payment))
(def user-consumer (setup-consumer user-unsubscribed-consumer
                                   publication
                                   :unsubscribed))
                                   
(def serializing-consumer-producer (setup-consumer (-&gt;event-deserializer publish-event)
                                                   publication
                                                   nil))</code></pre><p><code>core.async/pub</code> creates a &apos;publication&apos; on channel <code>event-bus</code> and a topic function, <code>:event-type</code> (taking advantage of the iFn interface). For now we&apos;ll assume the shape of our events are all the same, and we&apos;ll only receive events that tell us what they are via the <code>:event-type</code> keyword. </p><p>We also have a topic <code>nil</code>. We&apos;ll use this topic for a consumer-producer that de-serializes JSON to EDN for us. If you&apos;re wondering why on earth we&apos;d want to do that, most streaming tech (eg AWS kinesis) passes JSON strings through to our consumers. We could also serialize JSON to EDN-encoded strings and put them back on the bus. This will also give us the ability to respond to requests faster since we don&apos;t have to process the body of the request (yet); we&apos;ll return HTTP status code 202 whenever we receive an event. </p><p>Of course, just putting raw events on the event bus, and de-serializing them back onto the event bus will create back pressure. There are techniques for dealing with back pressure I won&apos;t go into here. To manage initial back pressure, I will say we should supply a buffer to our <code>event-bus</code> channel. Channels created without one create an <em>unbuffered channel</em> where the value will only take if there is a put waiting. Without a buffer, back pressure on the default buffer of <code>put!</code> and <code>take!</code> will rise too quickly depending on our context. We can take back pressure on our buffered channel to be a good sign though: We can start burning captial on AWS infrastructure, signalling our soon-to-be billion dollar exit.</p><h3 id="consumers-producers-and-consumer-producers">Consumers, Producers, and Consumer-Producers</h3><p>You&apos;ll notice in the <code>setup-consumer</code> adapter contains an internal unbuffered channel, <code>consumer-chan</code>, passed to <code>consumer-fn</code>. <code>consumer-fn</code> exibits our consumer interface, a function that takes a channel. This makes for nice core.async programming in our consumers regardless of what the event bus looks like. If we wanted to get super fancy, we could store descriptions of the event data (&quot;Event Definitions&quot;) in a database to further decouple our consumers from the events they handle. </p><p>On the other hand, producers are pretty simple:</p><pre><code class="language-clojure">(defn publish-event
  [event]
  (a/go (a/&gt;! event-bus event)))
  
(defn -&gt;event-handler
  [publish-fn]
  (fn [req]
    (let [{:keys [body]} req]
      (publish-fn body)
      {:status 202})))</code></pre><p>The <code>-&gt;event-handler</code> constructor creates a request handler for our system boundary, closing over <code>publish-event</code>. Any consumers that want to produce events, like <code>event-deserializer</code>, can close over <code>publish-event</code>, or just call it directly. </p><h3 id="caveats">Caveats</h3><p>We can&apos;t talk about event-driven anything without talking about eventual consistency. By introducing an event bus, or even an event buffer, we&apos;ve decoupled receiving events from processing events. We now have a lead time between event generation, and it&apos;s intended effect on the system. Typically, it&apos;s a bad fit for certain types of real-time or responsive applications unless the lead time can be well managed into the <em>milliseconds</em>. A challenging feat without sufficient software engineering resources. &#xA0;</p><h3 id="conclusion">Conclusion?</h3><p>And that&apos;s pretty much it for our MVP. Add consumers as needed. You can find the full source code on <a href="https://github.com/janetacarr/event-driven-architecture-example/?ref=blog.janetacarr.com">Github</a>. Since I was dragging my heels on this post, I decided to break it up into a two (or three) part series. In part two I&apos;ll separate out the event bus into AWS Kinesis and the consumers into AWS lambdas with Holy Lambda. Remember, billions.</p><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-text"><em>At the risk of sounding like shill, I&apos;m going to plug my course here. You are reading my blog after all. So, If you want to level up your Clojure game, I started taking pre-orders for my course <a href="https://clojureforpros.com/?ref=blog.janetacarr.com">Clojure for Pros</a> . Otherwise, you can follow me on all the usual places <a href="https://twitter.com/janetacarr?ref=blog.janetacarr.com">@janetacarr</a> </em>&#xAF;\_(&#x30C4;)_/&#xAF;</div></div>]]></content:encoded></item><item><title><![CDATA[How to Hire Clojure Developers]]></title><description><![CDATA[<p>This odd thing keeps happening to me where companies reach out to ask if I know of any Clojure developers they can hire instead of just hiring me. I understand why they do this. I am not interested in full-time position, after all. I think most people would bitterly look</p>]]></description><link>https://blog.janetacarr.com/how-to-hire-clojure-developers/</link><guid isPermaLink="false">6488958a1dfbc70001f3c64d</guid><dc:creator><![CDATA[Janet A. Carr]]></dc:creator><pubDate>Mon, 19 Jun 2023 18:04:59 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1487528278747-ba99ed528ebc?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDN8fGhpcmluZ3xlbnwwfHx8fDE2ODY2NzI4MDZ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1487528278747-ba99ed528ebc?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDN8fGhpcmluZ3xlbnwwfHx8fDE2ODY2NzI4MDZ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="How to Hire Clojure Developers"><p>This odd thing keeps happening to me where companies reach out to ask if I know of any Clojure developers they can hire instead of just hiring me. I understand why they do this. I am not interested in full-time position, after all. I think most people would bitterly look at this as if the company were asking for free labour. In some cases, I agree with this sentiment. However, when it comes to Clojure developers, I can empathize as I was something of a hiring manager once. The pipeline doesn&apos;t exist.</p>
<h3 id="do-you-really-need-a-full-time-dev">Do you really need a full-time dev? </h3>
<p>You should think hard about this question. We&apos;re in the midst of a recession, so people with existing Clojure jobs or experience will probably be reluctant to jump ship from their current job since the job market has begun to dry up (for now). If you&apos;re sinking an unreasonable amount of time into searching for a full-time Clojure(script) developer, why not consider a contractor or agency? If Clojure/Conj 2023 was anything to go by, most Clojure developers are self-employed, or at least, most of the people I met are. This is compounded by the fact that most of the Clojure/Conj 2023 sponsors and tables were agencies specializing in Clojure. </p>
<p>Sure, there are plenty of people in the #available-for-jobs channel in on the Clojurians slack looking for full-time work right now. Because full-time positions typically can&apos;t cross nationalities (not without legal), a company&apos;s nationality rarely intersects with the people in the channel. I did a quick search for a Canadian in the channel, and there was only explicitly one Canadian in there. Companies could use a service like remote.com to hire Clojure developers around the world, but that creates two problems: They might not be a remote first company (I know, I know), or they might not want to spin up a managed subsidiary in a different country or whatever. </p>
<p>According to the StackOverflow developer survey, Clojure developers are some of the highest paid in the world. If you want to command the forty to sixty hours per week of a Clojure developer&apos;s time, you better be willing to pay for it. I see plenty of companies offering paltry pay because developers get to use Clojure.</p>
<p>One tactic I&apos;ve seen in the past is to hire functional programmers from other developer backgrounds, or just hire some functional-curious developers, and train them to use Clojure. Easier said than done, but it might be worth considering if you&apos;re wasting too much time or money searching for a Clojure developer to hire. Either way there are ways to evaluate the Clojure, functional programmer, and functional-curious developer in an interview.</p>
<h3 id="functional-programming-interview">Functional Programming Interview</h3>
<p>As a base, A functional programming interview should evaluate the use of higher-order functions, function composition, polymorphism, reducers, persistent data structures, idiomatic things, and testing. Huge bonus points if they know how to design software with them. </p>
<p>On top of that, it would be wise to see how familiar the interviewee is with the Clojure ecosystem. For example, do they know the current state-of-affairs for http router, webserver, database, frontend combos? Can they build and push jars to Github Packages or Clojars? Can they deploy a Clojure project to <em>something</em>? Do they know how to contribute to a Clojure library without creating a major version change? I know you may not use what&apos;s &quot;standard&quot;, so your mileage may vary on this one.</p>
<p>For senior (and higher) level Clojure developers, You may want to evaluate whether candidates understand performance characteristics like transients, transducers, or inlining, and at this level you&apos;re probably looking for more application of Software Engineering principles.  For example, you could ask questions like &quot;By which mechanisms can you decouple parts of Clojure code with?&quot;, &quot;How would you architect an event-driven architecture with only Clojure (no cloud/IaaS)?&quot; or just ask them to do the take home project and look for design decisions. </p>
<p>A full-stack re-frame frontend and ring backend with XTDB or PostgreSQL might be a good jumping off point. An instagram clone, for example. What&apos;s the schema look like? What concerns are being separated, and <em>how</em> is the interviewee choosing to separate them? How did they choose to structure their re-frame events, co-effects, and effects namespaces? Should this regular function call actually be a higher-order function passed as an argument? The list goes on.</p>
<p>Unfortunately, there&apos;s a class of people I&apos;ve included that might have higher failure rates: the functional-curious. Pick these battles on a case-by-case basis. Often less experienced folks will do Clojure faux pas without knowing. For example, using the <code>for</code> macro for iteration, or worse, side-effects. Other Clojure faux pas&apos; to look out for are: using macros when not needed; state when not needed; not using core.async when doing concurrency; or not understanding the difference between atoms, agents, and refs.</p>
<p>Finally the best tip I can give is to see if interviewees read Clojure.core source code for a better understanding of how things work under the hood. One can gain a lot of understanding from this, half of what I know about Clojure has come from reading the Clojure.core source code on Github.</p>
<h3 id="conclusion">Conclusion</h3>
<p>I think companies pursue full-time employees without really thinking about what they want out of employment. Usually, companies want full-time employees because of warped notions of work and management. I think companies hiring Clojure developers should at least consider a freelancer or agency (at the risk of sounding like an ad for my own consulting services). The &apos;hiring pipeline&apos; doesn&apos;t really exist for Clojure developers. The companies that seem to be actually executing on their vision are not afraid to spend the scratch on good freelancers or an agency. At the end of the day, employment is a service-based role (developers), and results are results. There are no results if you&apos;re wasting all your time trying to hire people who aren&apos;t there.</p>
<div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-text"><p><i><em class="italic">Thanks for reading. Subscribe for the next one or follow me on twitter </em></i><a href="https://twitter.com/janetacarr?ref=blog.janetacarr.com"><i><em class="italic">@janetacarr</em></i></a><i><em class="italic"> , or don&apos;t </em></i><span>&#xAF;\_(&#x30C4;)_/&#xAF; </span><i><em class="italic">. You can also join the discussion about this post on hackernews or reddit if you think I&apos;m wrong.</em></i></p></div></div>
<p></p>]]></content:encoded></item><item><title><![CDATA[Ports and Adapters Architecture for Functional Programmers (with Clojure)]]></title><description><![CDATA[the small codebases of microservices provide great refuge for the salaried functional programmer.]]></description><link>https://blog.janetacarr.com/ports-and-adapters-architecture-for-the-functional-programmer/</link><guid isPermaLink="false">643858bb5bdb3b003db1bc2b</guid><category><![CDATA[functional programming]]></category><category><![CDATA[clojure]]></category><category><![CDATA[clojurescript]]></category><category><![CDATA[computer programming]]></category><category><![CDATA[software development]]></category><category><![CDATA[software engineering]]></category><dc:creator><![CDATA[Janet A. Carr]]></dc:creator><pubDate>Tue, 02 May 2023 21:21:19 GMT</pubDate><media:content url="https://blog.janetacarr.com/content/images/2023/04/Architecture-and-Design-diagrams---Page-4-2.png" medium="image"/><content:encoded><![CDATA[<h3 id="back-in-the-day">Back in the day</h3><img src="https://blog.janetacarr.com/content/images/2023/04/Architecture-and-Design-diagrams---Page-4-2.png" alt="Ports and Adapters Architecture for Functional Programmers (with Clojure)"><p>When I started in this industry, the architecture &apos;all the rage&apos; was microservices. Clojure lends itself nicely to microservices. Some developers struggle in large Clojure codebases, so the small codebases of microservices provide great refuge for the salaried functional programmer. However, the many small codebases create engineering complexity through multiple teams and services. That complexity comes at a hefty cost for software engineering budgets, so microservices aren&apos;t exactly a great approach if you have three users.</p><p>I&apos;ve done the startup thing before too. After leaving the microservices place, I got a Clojure gig at a place with a Service-Oriented Architecture (SOA). Great company, but developing with their codebase felt like nails on a chalkboard because they had a monorepo with stuff all over the place. Unsurprisingly, these are the kind of companies I suspect want to move away from functional programming languages once they&apos;re no longer a fun toy to play with. </p><p>When they started looking at other options, I learned about Hexagonal Architecture also known as Ports and Adapters Architecture. Ports and Adapters Architecture decouples system inputs, business logic, and system outputs by separating them into distinct domains. If that sounds like a three-tiered architecture to you, you&apos;re not too far off, except the &apos;tiers&apos; would be further broken down by domain into &apos;sub-tiers&apos;. Specifically, our sub-tiers can be thought of as the adapters in this metaphor. Adapters literally meaning <a href="https://blog.janetacarr.com/fix-your-clojure-code-clojure-comes-with-design-patterns-part-2/#adapter">adapter(ish) pattern</a>. Adapters reify the interface of a port for the benefit of the of the system inputs or outputs. Traditionally, ports are interfaces. So in Clojure speak, they could be protocols.</p><h3 id="pa">P&amp;A</h3><p>If you see a protocol and wince, I don&apos;t blame you. Protocols can introduce rigidity to your design, and they&apos;re tough to design like any <a href="https://blog.janetacarr.com/software-design-patterns-in-clojure/#were-speaking-the-same-language">bag of function signatures</a>. They remind functional programmers of being in the trenches of the brittle old Object-Oriented Design. But what if we could deconstruct a protocol? If it really is just a bag of function signatures, we&apos;d be able to decouple our domains by using functions as arguments. </p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">;; Driven adapter for Sentry satistfies the &quot;interface&quot;
;; or port that `process-string` expects. In this case the
;; signature for logging-fn is:
;; (Throwable) =&gt; nil
;;
;; `capture-exception-adapter` function is adapting
;; the &quot;interface&quot; provided by the sentry-clj lib.
(defn capture-exception-adapter
  [exception]
  (-&gt; exception
      (Throwable-&gt;map)
      (sentry/send-event)))

;; Core business logic expects the `logging-fn`
;; interface/port, presumably for side-effects,
;; of the function signature (Throwable) =&gt; nil
(defn process-string
  [logging-fn input]
  (try
    (apply str (reverse input))
    (catch Exception e
      (logging-fn e)
      (throw e))))

;; Our business logic Driving adapter. Here it
;; composes our business logic with the driven
;; adapter, but that doesn&apos;t necessarily need to be
;; the case. The important thing is to decouple
;; the business logic from the input(s).
(defn process-string-adapter
  [input]
  (process-string capture-exception-adapter input))

;; API handler expects an &quot;interface&quot; or port
;; `biz-logic-fn` that takes a string and
;; returns a string.
(defn -&gt;handler
  [biz-logic-fn]
  (fn handler-fn
    [request]
    (let [input (get-in request [:params :input])]
      {:status 200
       :headers {&quot;Content-Type&quot; &quot;application/json&quot;}
       :body (str &quot;{\&quot;result\&quot;: \&quot;&quot; (biz-logic-fn input) &quot;\&quot;}&quot;)})))

;; Here at the system boundary with either inject or close
;; over our adapters
(let [handler (-&gt;handler process-string-adapter)]
  (defroutes app-routes
    (GET &quot;/process/:input&quot; request (handler request))
    (route/not-found &quot;Not Found&quot;)))

(def app
  (wrap-defaults app-routes site-defaults))</code></pre><figcaption>A toy Ports and Adapters webserver</figcaption></figure><p>In the above example, our handler factory <code>-&gt;handler</code> closes over a function called <code>biz-logic-fn</code>. &#xA0;<code>biz-logic-fn</code> gives us the smallest example of a port: a function that takes a string <code>input</code> and returns a string. The actual business logic <strong>may</strong> neither take a string, nor return a string, so we must convert our &quot;interface&quot; to suit our needs. Lucky for us, we have just the thing: our <code>process-string-adapter</code>. </p><p><code>process-string-adapter</code> will make good on our promise to the <code>handler-fn</code> . Since <code>process-string-adapter</code> calls a business logic function, we can call it a <em>driving adapter</em>, as in, it&apos;s driving the process forward. Driving adapters wrap our business logic &quot;interface&quot;(functions) for the system inputs. The business logic here lives in our <code>process-string</code> function which gets called by <code>process-string-adapter</code> (I&apos;m aware <code>process-string</code> does in fact take a string and return a string, it&apos;s a contrived example, stay with me here). </p><p><code>process-string</code> has it&apos;s own port called <code>logging-fn</code>. <code>logging-fn</code> takes a map and returns nothing, presumably for side-effects. The adapter we supply for our <code>logging-fn</code> port comes in the form of <code>capture-exception-adapter</code> which wraps the &quot;interface&quot; provided by the sentry-clj library. We can call <code>capture-exception-adapter</code> a <em>driven adapter</em>, as in, it&apos;s being driven by the process. Driven adapters wrap the &quot;interfaces&quot;(functions) provided by our external services and libraries. </p><h3 id="other-methods">Other Methods</h3><p>Great, so we can deconstruct protocols into higher-order functions. Instead of passing a list of functions in lieu of protocols, a more realistic alternative to this might be multimethods. It&apos;s a rather trivial exercise to replace our functions with multimethods in the example above.</p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">(defmulti log-exception class)

(defmethod log-exception Throwable
  [exception]
  (-&gt; exception
      Throwable-&gt;map
      sentry/send-event))

(defmulti process-string class)

(defmethod process-string String
  [input]
  (try
    (apply str (reverse input))
    (catch Exception e
      (log-exception e)
      (throw e))))

(defn handler
  [request]
  (let [input (get-in request [:params :input])]
    {:status 200
     :headers {&quot;Content-Type&quot; &quot;application/json&quot;}
     :body (str &quot;{\&quot;result\&quot;: \&quot;&quot; (process-string input) &quot;\&quot;}&quot;)}))

(defroutes app-routes
  (GET &quot;/process/:input&quot; request (handlerrequest))
  (route/not-found &quot;Not Found&quot;))</code></pre><figcaption>Contrived examples are great until people point out it&apos;s unrealistic</figcaption></figure><p>With multimethods we can dispatch on anything, but the better approach might be to dispatch on data. In fact, let&apos;s borrow a concept from Onion Architecture: the domain model. Consider a software-as-a-Service solution (SaaS) where a user makes a request to view her business&apos;s EBITDA . Her identity, our domain model, is built by the business logic using joins on the users table through an adapter, of course.</p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">{:email &quot;jane.doe@example.com&quot;
 :user-id 1
 :oauth-user false
 :accounting-provider &quot;quickbooks&quot;
 :etc &quot;...&quot;}</code></pre><figcaption>Hopefully a less contrived example</figcaption></figure><p>Now we can create a multimethod called <code>gross-profit</code> that dispatches on the value <code>:accounting-provider</code>. Dispatch allows the business logic to only care about gross profit for calculating EBITDA provided it has a valid identity. The business logic could conceivably pull gross profit data from any accounting integration added to the system. The multimethod definition gives us a port, and every method creates an adapter for each integration. </p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">(ns best.ebitda.app.gross-profit)

(defmulti gross-profit-for-user
  &quot;A port for getting the gross-profit for a user model.
  Takes a `user-profile` and returns a gross-profit bigdec
  for that user.&quot;
  (fn [user-profile]
    (keyword (:provider user-profile))))

(defmethod gross-profit-for-user :default
  [user-profile] 0M)
  
;; in another namespace
(defmethod gross-profit/gross-profit-for-user :quickbooks
  [user-profile]
  (let [{:keys [user-id]} user-profile]
    (some-&gt;&gt; user-profile
             :user-id
             (get-quickbooks-account-id)
             (get-quickbooks-gross-profit user-id))))
</code></pre><figcaption>No wincing here</figcaption></figure><p>So far all of these examples live in a single process, but we&apos;ve created a pathway to a strangler pattern where we can easily strip out our dependencies into separate processes if we so choose.</p><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-text"><em>Thanks for reading. Subscribe for the next one or follow me on twitter </em><a href="https://twitter.com/janetacarr?ref=blog.janetacarr.com"><em>@janetacarr</em></a><em> , or don&apos;t </em>&#xAF;\_(&#x30C4;)_/&#xAF; <em>. You can also join the discussion about this post on twitter, hackernews, or reddit if you think I&apos;m wrong.</em></div></div>]]></content:encoded></item><item><title><![CDATA[Mindset shifts for Functional Programming (with Clojure)]]></title><description><![CDATA[<p>For more experienced functional programmers, most of this post will seem introductory, but I introduce some more advanced stuff near the end.</p><h3 id="functional-programming-over-canadian-programming">Functional Programming over Canadian Programming</h3><p>Lately, I&apos;ve been thinking about this Functional Programming journey I&apos;ve been on. I thought it started when I was</p>]]></description><link>https://blog.janetacarr.com/mindset-shifts-for-functional-programming-with-clojure/</link><guid isPermaLink="false">642ae9489ad8f5003d7ac055</guid><category><![CDATA[clojure]]></category><category><![CDATA[clojurescript]]></category><category><![CDATA[functional programming]]></category><category><![CDATA[computer programming]]></category><category><![CDATA[software development]]></category><category><![CDATA[software engineering]]></category><dc:creator><![CDATA[Janet A. Carr]]></dc:creator><pubDate>Tue, 04 Apr 2023 14:08:42 GMT</pubDate><media:content url="https://blog.janetacarr.com/content/images/2023/04/Game-FSM-2.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.janetacarr.com/content/images/2023/04/Game-FSM-2.png" alt="Mindset shifts for Functional Programming (with Clojure)"><p>For more experienced functional programmers, most of this post will seem introductory, but I introduce some more advanced stuff near the end.</p><h3 id="functional-programming-over-canadian-programming">Functional Programming over Canadian Programming</h3><p>Lately, I&apos;ve been thinking about this Functional Programming journey I&apos;ve been on. I thought it started when I was twenty, but It may have started when I was twelve. See, I used to watch a lot of <a href="https://en.wikipedia.org/wiki/G4_(Canadian_TV_channel)?ref=blog.janetacarr.com">G4TechTV</a> here in Canada. I still remember Amber Macarthur introducing a cool new website called Remember the Milk. </p><p>Remember the Milk was, to my knowledge, one of the first ToDo list Software-as-a-Service apps, circa 2005. All that tech consumer television certainly inspired me to, not only become a computer nerd, but it inspired me to take up programming at thirteen years old because I believed computing was the future.</p><p>I didn&apos;t learn <em>functional</em> programming at thirteen years old though. Like most, I started with an imperative programming language. I learned to program with the easiest programming language around: The C programming language. Okay, it wasn&apos;t that easy, but I still learned. Making introduction to computer programming in University a breeze. </p><p>All throughout University I was still a Remember the Milk user. One day their website spawned a careers page. Much to my curiousity, I decided to checkout the Software Engineer position as I usually did on those kinds of job postings back then. Remember the Milk&apos;s job description was different though. There was talk about <a href="https://www.amazon.ca/Scalable-Internet-Architectures-Theo-Schlossnagle/dp/067232699X/ref=sr_1_1?crid=2BB8B48XVHL22&amp;keywords=scalable+internet+architectures&amp;qid=1680538484&amp;sprefix=scalable+internet+architectures%2Caps%2C90&amp;sr=8-1&amp;ref=blog.janetacarr.com">Scalable Internet Architectures</a>, and this obscure programming language called Scala.</p><p>Soon after, I became enamoured with Scala. I thought &quot;this was what Java should have been&quot;, but I hit a wall soon after reading <a href="https://www.amazon.ca/Scala-Impatient-Cay-S-Horstmann/dp/0321774094/ref=sr_1_3?keywords=scala+for+the+impatient&amp;qid=1680538563&amp;sprefix=Scala+for+the+Imp%2Caps%2C110&amp;sr=8-3&amp;ref=blog.janetacarr.com">Scala for the Impatient</a>. And, I was <em>impatient</em>. I didn&apos;t really understand the funcitonal programming features of Scala. Most of my Scala code looked similar to the Java code I was writing in my programming classes. What the hell were closures, reducers, special-access methods, actors, and pattern matching? No fucking clue. Of course my internet research lead me to another functional programming language, a pure functional programming language, Haskell.</p><p>Haskell suffered from none of the deficiencies of Java Virtual Machine (JVM) functional programming languages at the time. It had it&apos;s own complier that produced binaries as well as having it&apos;s own read-eval-print-loop (REPL), and importantly, because I was a broke student, there was a great book online for free to learn Haskell. Finally, I had unlocked functional programming. I went back to Scala, only using the functional programming features for years. </p><p>Solving problems with Scala and functional programming eventually qualified me for a full-time Clojure position when I finally dropped out of University.</p><h3 id="transformations-over-instructions">Transformations over Instructions</h3><p>The first mindset shift when learning Haskell was to think of a program as a <a href="http://learnyouahaskell.com/introduction?ref=blog.janetacarr.com">series of transformations</a> on data rather than a series of instructions. A philosophy I would carry into other programming languages throughout my career, like when I was Golang developer. Pure functions and reducers like <code>map</code> and <code>filter</code> made for simplicity and easy testing. Transformations on data are so important, Clojure provides <a href="https://blog.janetacarr.com/clojure-transducers-your-composable-big-data-pipelines/">transducers</a> to decouple those transformations from their contexts. Of course, most of us know what a simple series of transformations look like in Clojure:</p><pre><code class="language-clojure">(-&gt;&gt; (range)
     (filter even?)
     (map inc)
     (take 10))

(-&gt;&gt; (range)
     (filter even?)
     (map inc)
     (take 10)
     (reduce +))</code></pre><p>Thinking of programs as a series of transformations was necessary because functional programming languages defaulted to immutable or persistent data structures. Meaning, if you want to change the data in the structure, you didn&apos;t mutate the data structure, rather you got a whole new data structure in memory at the end of the transformation, preserving the old data structure.</p><p>At a high level, an operation like <code>map</code> produces a collection the same length as it&apos;s input collection, applying an input function to each value in the input collection as the output collection. Simple on the surface. But, how do you do that without state and, therefore, looping? </p><h3 id="recursion-over-looping">Recursion over Looping</h3><p>Pure functional programming languages like Haskell do not contain a looping construct like <code>for</code> <code>while</code> or <code>do...while</code>. Loops, by their nature, often facilitate side-effects and mutate a variable to track whether or not to continue iteration. </p><p>Inspired by mathematics (a <em>recurring</em> theme in functional programming), functional programming languages often facilitate iteration through <a href="https://en.wikipedia.org/wiki/Recursion?ref=blog.janetacarr.com">recursion</a>. The mindset shift being, how do we construct a recursive function to emulate a loop? </p><p>We can emulate an iteration in a functional programming language by taking advantage of the lexical scope each recursive call has. </p><pre><code class="language-clojure">(defn recursive-map
  &quot;Recursively applies `f` to each element in `coll`,
  returning the new collection.&quot;
  [f coll]
  (let [[head &amp; tail] coll]
    (if (empty? coll)
      nil
      (cons (f head) (recursive-map f tail)))))
      
user&gt; (recursive-map identity (range 10))
(0 1 2 3 4 5 6 7 8 9)
user&gt; (recursive-map inc (range 10))
(1 2 3 4 5 6 7 8 9 10)</code></pre><p>Typically, code like this is an anti-pattern in Clojure as it would consume too much stack space for large input. We would have passed our output through each call, building it through the recursive calls like using Clojure&apos;s <code>loop</code> and <code>recur</code>. Unfortunately, Clojure does not have tail-call optimization. To get around this, it has a special form <code>recur</code> to signal to the compiler not to consume stack space, but it has to be in the end position unlike our <code>recursive-map</code> call.</p><p>I chose the example above because it shows a common functional programming technique: Destructuring our input collection into a <code>head</code> and <code>tail</code>. Head being the first element in our collection, and tail being a collection with all except the head of the collection. Rather than looping over an array and applying our function, each recursive call applies a 1-arity function <code>f</code> to each element before getting <code>cons</code>&apos;d into the list.</p><h3 id="functions-over-objects">Functions over Objects</h3><p>Our <code>recursive-map</code> above example uses another mindset shift: higher-order functions. Higher-order functions form the basis for everything else in functional programming. In functional programming languages, functions are first class, meaning we can treat them like any other piece of data. We can pass them to other functions as arguments, return functions from functions, and even having lists of functions. Higher-order functions let us decouple a function from it&apos;s usage, provided the function signatures align. </p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">user&gt; (take 1 (map println [1 2 3 4 5]))
;; 1
;; 2
;; 3
;; 4
;; 5
;; (nil)
user&gt; (take 1 (map println &apos;(1 2 3 4 5)))
;; 1
;; (nil)</code></pre><figcaption>Clojure side-effects <a href="https://blog.janetacarr.com/how-clojure-works-for-you/#chunked-sequences">gotcha</a></figcaption></figure><p>Functional Programming emphasizes pure functions. That is, functions free from side-effects. Side-effects are behaviours functions perform during their execution aside from computing the output. For example, IO operations, network transmission, and writing to a database are all side-effects. Side-effects cause numerous bugs in software development, so by (nearly) eliminating side-effects, functional programming (nearly) elminates this whole class of bugs. </p><h3 id="design-over-spaghetti">Design over Spaghetti</h3><p>I like to think of transformations, recursion, and functions as the fundamentals of functional programming. With them we can design and emulate a finite state machine (FSM) without any actual state by using the recurring lexical scope to bind our current FSM state. Whenever the state &quot;transitions&quot;, we&apos;ll return a function to replace our <code>game-state</code> in <code>game-loop</code> with a new state for our fake game engine below. Even though I wrote this example in Clojure, there&apos;s nothing stopping someone from replicating it in Haskell:</p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">(defn pause-menu
  [game]
  (let [{:keys [menu player]} game]
    (do
      (draw-game game)
      (if (= :affirm (:action player))
        (when-let [menu-item (collision player)]
          (cond
            (= menu-item :resume-game) play-game
            (= menu-item :options) (partial options-menu pause-menu)
            (= menu-item :quit-game) quit-game
            :else pause-menu))
        pause-menu))))

(defn options-menu
  [previous game]
  (let [{:keys [menu player]} game]
    (do
      (draw-game game)
      (if (= :affirm (:action player))
        (when-let [menu-item (collision player)]
          (cond
            (= menu-item :controls) controls-menu
            (= menu-item :accessibility) accessibility-menu
            (= menu-item :exit-options) previous
            :else options-menu))
        options-menu))))

(defn play-game
  [game]
  (let [{:keys [components player]} game]
    (do
      (doseq [component components]
        (update! component))
      (draw-game game)
      (if (= :paused (:action player))
        pause-menu
        play-game))))

(defn start-menu
  [game]
  (let [{:keys [menu player]} game]
    (do
      (draw-game game)
      (if (= :affirm (:action player))
        (when-let [menu-item (collision player)]
          (cond ;; our state transition
            (= menu-item :start-game) play-game
            (= menu-item :options) (partial options-menu start-menu)
            (= menu-item :quit-game) quit-game
            :else start-menu))
        start-menu))))

;; Our initial state
(defn start-game
  [game]
  (start-menu game))

(defn game-loop
  [game-state game-engine]
  (when-not (:quit game-engine)
    (recur (game-state game-engine) (game-engine))))

(defn -main
  []
  (game-loop (start-game game-engine) (game-engine)))</code></pre><figcaption>A stateless <a href="https://blog.janetacarr.com/software-design-patterns-in-clojure/#state">state machine</a></figcaption></figure><p>Regular readers will recognize this FSM as my &quot;stateless&quot; state pattern from my design patterns series, but I want to emphasis something else: how we can use the fundamentals of Functional Programming to design solutions without making our lives miserable. At least until AI puts us out of work.</p><h3 id="closure-over-conclusion">Closure over Conclusion</h3><p>Functional Programming is awesome. When I started learning Haskell, it felt like learning to code all over again. After the initial hurdle, Functional Programming gave me a cognitive model for programming that leads to more simplicity and less bugs by emphasizing transformations, recursion, and functions.</p><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-text"><em>Thanks for reading. Subscribe for the next one or follow me on twitter </em><a href="https://twitter.com/janetacarr?ref=blog.janetacarr.com"><em>@janetacarr</em></a><em> , or don&apos;t </em>&#xAF;\_(&#x30C4;)_/&#xAF; <em>. I got a little more personal than usual in this post, so I hope it doesn&apos;t detract from the content. Let me know if it did. You can also join the discussion about this post on twitter, hackernews, or reddit if you think I&apos;m wrong.</em></div></div>]]></content:encoded></item><item><title><![CDATA[Clojure Transducers: Your Composable Data Pipelines]]></title><description><![CDATA[<h3 id="what-is-a-transducer-anyways">What is a transducer anyways? </h3><p>Specifically, from the documentation &apos;a transducer is a transformation from one reducing function to another&apos;. We can think of a transducer as a context-independent transformation composed of, say, many reducers (like <code>map</code> and <code>filter</code>). If we think of functional programming as a series</p>]]></description><link>https://blog.janetacarr.com/clojure-transducers-your-composable-big-data-pipelines/</link><guid isPermaLink="false">641f2f23e2b1c3003db25f92</guid><dc:creator><![CDATA[Janet A. Carr]]></dc:creator><pubDate>Thu, 30 Mar 2023 14:53:22 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1592438944517-ee7d4fd058c9?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDE4fHxwaXBlbGluZXxlbnwwfHx8fDE2Nzk3NjUyNjg&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<h3 id="what-is-a-transducer-anyways">What is a transducer anyways? </h3><img src="https://images.unsplash.com/photo-1592438944517-ee7d4fd058c9?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDE4fHxwaXBlbGluZXxlbnwwfHx8fDE2Nzk3NjUyNjg&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Clojure Transducers: Your Composable Data Pipelines"><p>Specifically, from the documentation &apos;a transducer is a transformation from one reducing function to another&apos;. We can think of a transducer as a context-independent transformation composed of, say, many reducers (like <code>map</code> and <code>filter</code>). If we think of functional programming as a series of transformations on data, we&apos;d naturally want to decouple the transformations from the contexts they&apos;re used in. Decoupling our transformations gives us better building blocks for functional programs. </p><h3 id="independence-means-composition">Independence means composition</h3><p>If transducers are independent of their context, we can also compose transducers into larger transducers instead of only composing reducers. Let&apos;s look at an example.</p><pre><code class="language-clojure">;; Consider a transducer that filters out deleted records and
;; packages them into a format that reagent likes to consume.
(def active-indexed-xf
  (comp (filter #(false? (:deleted %)))
        (map-indexed (fn [idx item] (merge item {:idx idx})))))

(defn list-orders
  &quot;Returns all active orders in a format that Reagent components
  like. Expects pagination query params `page` and `limit` to be
  present in `req`.&quot;
  [req]
  (let [results (get-all-orders)
        {:keys [page limit year]
         :or {page 1 limit 25}} (:query-params req)
        page (dec page)
        xfv (cond-&gt; [active-indexed-xf]
              ;; For each optional query param we can just
              ;; keep conj&apos;ing different transducers to the vector to
              ;; further refine the result for our users.
              year (conj (filter #(= (:year %) year)))
              ;; month (conj (filter #(= (:month %) month)))
              (and (not (neg? page)) (pos? limit)) (conj (drop (* page limit))
                                                         (take limit)))
        xf (apply comp xfv)]
    ;; Could also use (apply eduction (conj xfv results))
    ;; or (sequence xf results)
    (into [] xf results)))
</code></pre><p>Here we can see the classic way of creating a transducer, by using <code>comp</code> to compose many reducers into a single transform, <code>active-indexed-xf</code>. When the <code>list-orders</code> handle is called, our transducer can be <code>comp</code> &apos;d with other functions that return transducers as well, allowing our API return a list of orders according to the query parameters provided. </p><p>We understand how transducers can be composed, but how is it transducers be independent of their context? Well, like most things in Clojure: the higher-order function.</p><h3 id="transducer-as-a-type">Transducer as a type</h3><p>As some of you may know, I have a little thing for <a href="https://blog.janetacarr.com/software-design-patterns-in-clojure/#were-speaking-the-same-language">types</a>. Anything conforming to an interface is a type, and an interface is a bag of functions, or even just one function that has multiple arity, and returns something specific for each. Looking at the code for reducers returning transducers like <code>map</code>, we can see the transducer interface in the 1-arty <code>map</code> function.</p><pre><code class="language-clojure">;; Copyright Rich Hickey, used under license.
;; map from clojure.core 
(defn map
  &quot;Returns a lazy sequence consisting of the result of applying f to
  the set of first items of each coll, followed by applying f to the
  set of second items in each coll, until any one of the colls is
  exhausted.  Any remaining items in other colls are ignored. Function
  f should accept number-of-colls arguments. Returns a transducer when
  no collection is provided.&quot;
  {:added &quot;1.0&quot;
   :static true}
  ([f]
    (fn [rf]
      (fn
        ([] (rf))
        ([result] (rf result))
        ([result input]
           (rf result (f input)))
        ([result input &amp; inputs]
           (rf result (apply f input inputs))))))
  ([f coll]
   (lazy-seq
    (when-let [s (seq coll)]
      (if (chunked-seq? s)
        (let [c (chunk-first s)
              size (int (count c))
              b (chunk-buffer size)]
          (dotimes [i size]
              (chunk-append b (f (.nth c i))))
          (chunk-cons (chunk b) (map f (chunk-rest s))))
        (cons (f (first s)) (map f (rest s)))))))
  ([f c1 c2]
   (lazy-seq
    (let [s1 (seq c1) s2 (seq c2)]
      (when (and s1 s2)
        (cons (f (first s1) (first s2))
              (map f (rest s1) (rest s2)))))))
  ([f c1 c2 c3]
   (lazy-seq
    (let [s1 (seq c1) s2 (seq c2) s3 (seq c3)]
      (when (and  s1 s2 s3)
        (cons (f (first s1) (first s2) (first s3))
              (map f (rest s1) (rest s2) (rest s3)))))))
  ([f c1 c2 c3 &amp; colls]
   (let [step (fn step [cs]
                 (lazy-seq
                  (let [ss (map seq cs)]
                    (when (every? identity ss)
                      (cons (map first ss) (step (map rest ss)))))))]
     (map #(apply f %) (step (conj colls c3 c2 c1))))))</code></pre><p>Looking the 1-arity call to filter, we can see something similar.</p><pre><code class="language-clojure">;; Copyright Rich Hickey, used under license.
;; filter from clojure.core
(defn filter
  &quot;Returns a lazy sequence of the items in coll for which
  (pred item) returns logical true. pred must be free of side-effects.
  Returns a transducer when no collection is provided.&quot;
  {:added &quot;1.0&quot;
   :static true}
  ([pred]
    (fn [rf]
      (fn
        ([] (rf))
        ([result] (rf result))
        ([result input]
           (if (pred input)
             (rf result input)
             result)))))
  ([pred coll]
   (lazy-seq
    (when-let [s (seq coll)]
      (if (chunked-seq? s)
        (let [c (chunk-first s)
              size (count c)
              b (chunk-buffer size)]
          (dotimes [i size]
              (let [v (.nth c i)]
                (when (pred v)
                  (chunk-append b v))))
          (chunk-cons (chunk b) (filter pred (chunk-rest s))))
        (let [f (first s) r (rest s)]
          (if (pred f)
            (cons f (filter pred r))
            (filter pred r))))))))</code></pre><p>Now for the last piece of the puzzle, look at how <code>comp</code> composes functions.</p><pre><code class="language-clojure">;; Copyright Rich Hickey, used under license.
;; comp from clojure.core
(defn comp
  &quot;Takes a set of functions and returns a fn that is the composition
  of those fns.  The returned fn takes a variable number of args,
  applies the rightmost of fns to the args, the next
  fn (right-to-left) to the result, etc.&quot;
  {:added &quot;1.0&quot;
   :static true}
  ([] identity)
  ([f] f)
  ([f g] 
     (fn 
       ([] (f (g)))
       ([x] (f (g x)))
       ([x y] (f (g x y)))
       ([x y z] (f (g x y z)))
       ([x y z &amp; args] (f (apply g x y z args)))))
  ([f g &amp; fs]
     (reduce1 comp (list* f g fs))))</code></pre><p>I&apos;m sure some of you have figured out that calling <code>comp</code> on transducers will give us nested <code>fn</code> calls.</p><pre><code class="language-clojure">;; Doing this
(comp (filter even?)
      (map inc))
      
;; Gives us something like this:

;; rf is reducing function here
;; if we passed this xf to transduce with `+`, + is our reducing fn
;; rf from filter, is now bound to the function returned by 1-arty map
(fn [rf]
  (fn
    ([] (;; rf from map. I&apos;ve sustituted the rf from filter for what
         ;; it is bound to, the function from map.
         (fn [rf]
           (fn
             ([] (rf))
             ([result] (rf result))
             ([result input]
              (rf result (f input)))
             ([result input &amp; inputs]
              (rf result (apply f input inputs)))))))
    ([result] ((fn [rf]
                 (fn
                   ([] (rf))
                   ([result] (rf result))
                   ([result input]
                    (rf result (f input)))
                   ([result input &amp; inputs]
                    (rf result (apply f input inputs))))) result))
    ([result input]
     (if (pred input)
       ((fn [rf]
          (fn
            ([] (rf))
            ([result] (rf result))
            ([result input]
             (rf result (f input)))
            ([result input &amp; inputs]
             (rf result (apply f input inputs))))) result input)
       result))))

</code></pre><p>Passing a transducer to another transducer &quot;stacks&quot; the operation on top of one another, revealing the interface for transducers. A transducer is a <a href="https://clojure.org/reference/transducers?ref=blog.janetacarr.com#_creating_transducers">function</a> that takes a reducing function ( <code>rf</code> ) and returns a closure over it with three arities. </p><ul><li><strong>Init, or arity zero</strong>, calls the init arity on the rest of the stack. </li><li><strong>Step, or arity two</strong>, calls the reducing function on two values, like a single step of <code>reduce</code>.</li><li><strong>Completion, or arity one, </strong>Cleans up stateful transducers and returns a value. It must call the reducing function completion once.</li></ul><p>If <code>even?</code> is true, then the value will be incremented in our example before being passed to the reducing function <code>+</code> in transduce.</p><pre><code class="language-clojure">(def xf (comp (filter even?) (map inc)))
(transduce xf + (range 100))</code></pre><p>In a sense transducers &apos;parallelize&apos; multiple transformations from stacking them on top of one another. </p><h3 id="gotta-go-fast">Gotta Go Fast</h3><p>For most, developers often think of the parallelization as a forgone conclusion. I don&apos;t blame them. Every Computer Science faculty in the world (I hope) teaches about computational complexity analysis of algorithms like <code>filter</code> and <code>map</code>. They&apos;re both average <a href="https://en.wikipedia.org/wiki/Time_complexity?ref=blog.janetacarr.com">time complexity</a> of O(n), or linear time. Meaning, the algorithms time to run will be a linear function of it&apos;s input. So, according to Big-O Notation, even if our input is 5n, our time complexity will still be on the order of O(n). </p><p>Unfortunately for us working outside of the classroom, we have cloud bills to worry about. If we&apos;re working with the massive input of a collection with, say, five million records, we might not have the computational luxury of naively threading ( <code>-&gt;&gt;</code>) through a bunch of reducers. Even though crunching one million records and five million records have the same time complexity for clojure.core&apos;s reducers, in reality the latter has five times more instructions to execute sequentially with threading macros. It would be far more efficient if we just parallelize them using transducers! </p><p>Let&apos;s do a benchmark with Criterium to confirm.</p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">user&gt; (criterium.core/with-progress-reporting
        (criterium.core/bench
         (into []
               (comp
                (map inc)
                (filter odd?)
                (map dec)
                (filter even?)
                (map (fn [n] (+ 3 n)))
                (filter odd?)
                (map inc)
                (filter odd?)
                (map dec)
                (filter even?)
                (map (fn [n] (+ 3 n)))
                (filter odd?))
               (range 5000000))))
Warming up for JIT optimisations 10000000000 ...
Estimating execution count ...
Sampling ...
Final GC...
Checking GC...
Finding outliers ...
Bootstrapping ...
Checking outlier significance
Evaluation count : 600 in 60 samples of 10 calls.
             Execution time mean : 105.381854 ms
    Execution time std-deviation : 900.473165 &#xB5;s
   Execution time lower quantile : 103.346469 ms ( 2.5%)
   Execution time upper quantile : 106.385211 ms (97.5%)
                   Overhead used : 1.598527 ns

Found 4 outliers in 60 samples (6.6667 %)
	low-severe	 3 (5.0000 %)
	low-mild	 1 (1.6667 %)
 Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
nil
user&gt; (criterium.core/with-progress-reporting
        (criterium.core/bench
         (-&gt;&gt; (range 5000000)
              (map inc)
              (filter odd?)
              (map dec)
              (filter even?)
              (map (fn [n] (+ 3 n)))
              (filter odd?)
              (map inc)
              (filter odd?)
              (map dec)
              (filter even?)
              (map (fn [n] (+ 3 n)))
              (filter odd?)
              (into []))))
Warming up for JIT optimisations 10000000000 ...
Estimating execution count ...
Sampling ...
Final GC...
Checking GC...
Finding outliers ...
Bootstrapping ...
Checking outlier significance
Evaluation count : 240 in 60 samples of 4 calls.
             Execution time mean : 256.346727 ms
    Execution time std-deviation : 1.908808 ms
   Execution time lower quantile : 254.553894 ms ( 2.5%)
   Execution time upper quantile : 258.981447 ms (97.5%)
                   Overhead used : 1.598527 ns

Found 4 outliers in 60 samples (6.6667 %)
	low-severe	 1 (1.6667 %)
	low-mild	 2 (3.3333 %)
	high-mild	 1 (1.6667 %)
 Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
nil</code></pre><figcaption><p><span style="white-space: pre-wrap;">Example based on example from this </span><a href="https://groups.google.com/g/clojure/c/iIju063QmG0?pli=1&amp;ref=blog.janetacarr.com"><span style="white-space: pre-wrap;">discussion</span></a></p></figcaption></figure><p>Quite a reduction in execution time when using transducers on large input! You won&apos;t see that if  the input was <code>(range 10)</code> and <code>(range 50)</code> though, there&apos;s just not enough to execute sequentially to see a worthy jump in performance. </p><h3 id="conclusion">Conclusion</h3><p>In my opinion, transducers are an underrated feature in Clojure. Not only do we get functional programming building blocks for little cost, we get a signifigant boost in performance when working with large datasets. </p><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-text"><i><em class="italic" style="white-space: pre-wrap;">Thanks for reading. Subscribe for the next one or follow me on twitter </em></i><a href="https://twitter.com/janetacarr?ref=blog.janetacarr.com"><i><em class="italic" style="white-space: pre-wrap;">@janetacarr</em></i></a><i><em class="italic" style="white-space: pre-wrap;"> , or don&apos;t </em></i>&#xAF;\_(&#x30C4;)_/&#xAF; <i><em class="italic" style="white-space: pre-wrap;">. I might write about creating transducers next. You can also join the discussion about this post on twitter, hackernews, or reddit if you think I&apos;m wrong. I&apos;m sure some of you will.</em></i></div></div>]]></content:encoded></item><item><title><![CDATA[Model-View-Controller, a classic architectural pattern in Clojure]]></title><description><![CDATA[<p>I&apos;m sure for some of you Model-View-Controller (MVC) resembles more of an anti-pattern than something to reach for when writing Clojure, but I think it&apos;s a great example of what architecture should accomplish, especially what can be accomplished in Clojure.</p><p>MVC decouples state, state changes, and</p>]]></description><link>https://blog.janetacarr.com/model-view-controller-a-classic-architectural-pattern-in-clojure/</link><guid isPermaLink="false">6420d77ce2b1c3003db25f9a</guid><dc:creator><![CDATA[Janet A. Carr]]></dc:creator><pubDate>Mon, 27 Mar 2023 15:39:47 GMT</pubDate><media:content url="https://blog.janetacarr.com/content/images/2023/03/carbon-35.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.janetacarr.com/content/images/2023/03/carbon-35.png" alt="Model-View-Controller, a classic architectural pattern in Clojure"><p>I&apos;m sure for some of you Model-View-Controller (MVC) resembles more of an anti-pattern than something to reach for when writing Clojure, but I think it&apos;s a great example of what architecture should accomplish, especially what can be accomplished in Clojure.</p><p>MVC decouples state, state changes, and state usage. One way to compose this architecture uses three classic software design patterns: Strategy as our controller to update the model, observer to notify the view and controller, and composite as our view hierarchy. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.janetacarr.com/content/images/2023/03/MVC-for-Clojure-stuff---Page-1-2-1.png" class="kg-image" alt="Model-View-Controller, a classic architectural pattern in Clojure" loading="lazy" width="1322" height="1063" srcset="https://blog.janetacarr.com/content/images/size/w600/2023/03/MVC-for-Clojure-stuff---Page-1-2-1.png 600w, https://blog.janetacarr.com/content/images/size/w1000/2023/03/MVC-for-Clojure-stuff---Page-1-2-1.png 1000w, https://blog.janetacarr.com/content/images/2023/03/MVC-for-Clojure-stuff---Page-1-2-1.png 1322w" sizes="(min-width: 720px) 720px"><figcaption>MVC diagram</figcaption></figure><p>If we want to do this in Clojure, we can use the <a href="https://blog.janetacarr.com/software-design-patterns-in-clojure/">Clojure design pattern analogs</a>. Let&apos;s use a higher-order functions for our strategy; a watch for our observer (watching an atom or ref); and <a href="https://github.com/clj-commons/seesaw?ref=blog.janetacarr.com">seesaw</a> components for our composite, we can build ourselves a simple desktop application: an adder.</p><h3 id="the-controller">The Controller </h3><p>Since for the purposes of this example we&apos;ll pretend we&apos;re purists, our <a href="https://blog.janetacarr.com/fix-your-clojure-code-clojure-comes-with-design-patterns-part-2/#strategy">strategy</a> will be a couple higher-order functions (no protocols). &#xA0;So let&apos;s create a couple <em>delegate</em> functions to update our model. </p><pre><code class="language-clojure">;; Higher-order functions as our &quot;strategy delegates&quot;.
(defn change-display
  &quot;Takes an atom `model` and a string `input`, and updates
  `model` by appending `input` to the currently displayed
  text in our calculator.&quot;
  [model input]
  (swap! model update :display #(apply str (concat % input))))

(defn solve
  [model]
  (swap! model update :display #(apply + (mapv (fn [s]
                                                 (Integer/parseInt s))
                                               (string/split % #&quot;\+&quot;)))))</code></pre><p>I understand in the land of YAGNI, this seems more like set dressing with code complexity than something useful, but it has a usefulness in a bigger code base as we&apos;re about to see how it decouples state changes from the using the state.</p><h3 id="the-view">The View</h3><p>I never wrote about the composite pattern in Clojure (not yet anyway, subscribe for design patterns part 3). To summarize, the composite pattern creates an interface for building hierachies with the intent that children in the hierarchy will follow the interface and propagate changes down the tree. We can do this pretty easy in Clojure using higher-order functions (again) or protocols, but for now we&apos;ll rely on Seesaw, a wrapper around Java&apos;s Swing components. &#xA0; </p><pre><code class="language-clojure">;; A very simple view hierarchy using a few seesaw components.
(defn create-view-children
  [display state change-fn solve-fn]
  (let [display-label (s/label :text display)
        plus-button (s/button :text &quot;+&quot;
                              :listen [:action (fn [e]
                                                 (change-fn state &quot;+&quot;))])
        equal-button (s/button :text &quot;=&quot;
                               :listen [:action (fn [e]
                                                  (solve-fn state))])
        keypad-buttons (mapv (fn [n]
                               (s/button :text (str n)
                                         :listen [:action (fn [e]
                                                            (change-display state (str n)))]))
                             (range 9))
        keypad (s/grid-panel :rows 3
                             :columns 3
                             :items keypad-buttons)
        panel (s/grid-panel :rows 1
                            :columns 2
                            :items [plus-button equal-button])]
    (s/border-panel
     :items [[panel :south] [display-label :north] [keypad :center]])))

(defn create-view
  [children]
  (s/frame :title &quot;Positive Integer Adder&quot;
           :visible? true
           :content children
           :on-close :exit
           :width 400
           :height 300))</code></pre><p>For our view, we use <code>map</code> to programmatically create our number buttons in the &#xA0;hierarchy as well as directly creating plus and equals buttons. Storing them in a couple panels to describe the layout of the adder&apos;s UI. We will pass these components to our view factory function <code>create-view</code> which will set up the Swing frame for us. Now all we need to do is update our view everytime the model&apos;s state changes to update our <code>display-label</code>.</p><h3 id="the-model">The Model</h3><p>Lastly, we see our model and it&apos;s <a href="https://blog.janetacarr.com/software-design-patterns-in-clojure/#observer">observer</a> are pretty simple. Just an atom and a watch. I added the state-logger function to help debug the output, but we could add any number of responses to the state changes here without affecting the view (unless, of course, we removed or changed update-view). </p><pre><code class="language-clojure">;; We can add many &quot;observers&quot; to change other view state/composition
;; or even change the strategy used by the buttons to add the numbers now
;; that we&apos;ve decoupled all three.
(defn update-view
  [view state]
  (fn [_ _ _ new-state]
    (let [display (:display new-state)]
      (s/config! view :content (create-view-children display
                                                     state
                                                     change-display
                                                     solve)))))

(defn state-logger
  [_ _ _ new-state]
  (println &quot;State changed to: &quot; new-state))

(defn -main
  [&amp; args]
  (let [;; Our model, diligently keeping track of our state
        state (atom {:display &quot;&quot;})

        ;; The root of our view hierachy
        view (create-view (create-view-children 0 state change-display solve))]

    ;; Observe
    (add-watch state :update-view (update-view view state))
    (add-watch state :logger state-logger)

    ;; Start the app
    (s/native!)
    (s/invoke-now (fn [] (s/show! (s/pack! view))))))
</code></pre><p>As the comments suggest, we can even change the controller or view we want to use. Then, we put it all together in <code>-main</code>, creating our model (atom), view (seesaw), and start watching the show unfold.</p><h3 id="putting-it-all-together">Putting it all together</h3><p>I&apos;m guessing you&apos;ve already put all the code examples together, but let me help you out by doing just that.</p><pre><code class="language-clojure">(ns janetacarr.mvc-adder
  (:require [seesaw.core :as s]
            [clojure.string :as string])
  (:gen-class))

;; Higher-order functions as our &quot;strategy delegates&quot;.
(defn change-display
  &quot;Takes an atom `model` and a string `input`, and updates
  `model` by appending `input` to the currently displayed
  text in our calculator.&quot;
  [model input]
  (swap! model update :display #(apply str (concat % input))))

(defn solve
  [model]
  (swap! model update :display #(apply + (mapv (fn [s]
                                                 (Integer/parseInt s))
                                               (string/split % #&quot;\+&quot;)))))

;; A very simple view hierarchy using a few seesaw components.
(defn create-view-children
  [display state change-fn solve-fn]
  (let [display-label (s/label :text display)
        plus-button (s/button :text &quot;+&quot;
                              :listen [:action (fn [e]
                                                 (change-fn state &quot;+&quot;))])
        equal-button (s/button :text &quot;=&quot;
                               :listen [:action (fn [e]
                                                  (solve-fn state))])
        keypad-buttons (mapv (fn [n]
                               (s/button :text (str n)
                                         :listen [:action (fn [e]
                                                            (change-display state (str n)))]))
                             (range 9))
        keypad (s/grid-panel :rows 3
                             :columns 3
                             :items keypad-buttons)
        panel (s/grid-panel :rows 1
                            :columns 2
                            :items [plus-button equal-button])]
    (s/border-panel
     :items [[panel :south] [display-label :north] [keypad :center]])))

(defn create-view
  [children]
  (s/frame :title &quot;Positive Integer Adder&quot;
           :visible? true
           :content children
           :on-close :exit
           :width 400
           :height 300))

;; We can add many &quot;observers&quot; to change other view state/composition
;; or even change the strategy used by the buttons to add the numbers now
;; that we&apos;ve decoupled all three.
(defn update-view
  [view state]
  (fn [_ _ _ new-state]
    (let [display (:display new-state)]
      (s/config! view :content (create-view-children display
                                                     state
                                                     change-display
                                                     solve)))))

(defn state-logger
  [_ _ _ new-state]
  (println &quot;State changed to: &quot; new-state))

(defn -main
  [&amp; args]
  (let [;; Our model, diligently keeping track of our state
        state (atom {:display &quot;&quot;})

        ;; The root of our view hierachy
        view (create-view (create-view-children 0 state change-display solve))]

    ;; Observe
    (add-watch state :update-view (update-view view state))
    (add-watch state :logger state-logger)

    ;; Start the app
    (s/native!)
    (s/invoke-now (fn [] (s/show! (s/pack! view))))))</code></pre><p>If we run this code with our Clojure CLI, we&apos;ll see this window pop up:</p><figure class="kg-card kg-image-card"><img src="https://blog.janetacarr.com/content/images/2023/03/Screenshot-2023-03-15-at-12.36.16-PM.png" class="kg-image" alt="Model-View-Controller, a classic architectural pattern in Clojure" loading="lazy" width="936" height="736" srcset="https://blog.janetacarr.com/content/images/size/w600/2023/03/Screenshot-2023-03-15-at-12.36.16-PM.png 600w, https://blog.janetacarr.com/content/images/2023/03/Screenshot-2023-03-15-at-12.36.16-PM.png 936w" sizes="(min-width: 720px) 720px"></figure><p>Hitting equals at this point will call our <code>solve</code> strategy, updating the model to contain the string &quot;22&quot; and, of course, the display in the application will also show 22 instead of 11+11.</p><h3 id="conclusion">Conclusion</h3><p>I understand coding an MVC app under one hundred lines of code seems a bit trite, but we can bridge the mental gap here to something like Rails or other web frameworks by replacing our seesaw components with serving HTML fairly easily. Don&apos;t be so quick to dismiss the potential of a little state and some higher-order functions. </p><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-text"><em>Thanks for reading. Subscribe for the next one or follow me on twitter </em><a href="https://twitter.com/janetacarr?ref=blog.janetacarr.com"><em>@janetacarr</em></a><em> , or don&apos;t </em>&#xAF;\_(&#x30C4;)_/&#xAF; <em>. You can also join the discussion about this post on twitter, hackernews, or reddit if you think I&apos;m wrong. I&apos;m sure some of you will.</em></div></div>]]></content:encoded></item><item><title><![CDATA[A Primer on Clojure Macros]]></title><description><![CDATA[<p>One day my squad mate at a Clojure startup committed a macro to the codebase, and I was quick to reprimand them for it as the same functionality could have been implemented with Clojure core functions. Peeling back the decision rationale, I discovered my colleague had never learned the first</p>]]></description><link>https://blog.janetacarr.com/a-primer-on-clojure-macros/</link><guid isPermaLink="false">63bc46ed8498ef003d5276b8</guid><dc:creator><![CDATA[Janet A. Carr]]></dc:creator><pubDate>Sun, 29 Jan 2023 18:12:08 GMT</pubDate><media:content url="https://blog.janetacarr.com/content/images/2023/01/carbon-14-.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.janetacarr.com/content/images/2023/01/carbon-14-.png" alt="A Primer on Clojure Macros"><p>One day my squad mate at a Clojure startup committed a macro to the codebase, and I was quick to reprimand them for it as the same functionality could have been implemented with Clojure core functions. Peeling back the decision rationale, I discovered my colleague had never learned the first and second rule of Clojure macros: Don&apos;t talk about Clojure macros. Just kidding, the real rule is you should only reach for a macro if Clojure doesn&apos;t already support something you need (or if you need to stop evaluation, but that&apos;s another story).</p><p>So what is a macro anyways? A macro is code that operates on other code, and typically they return code as their result. But what do all the tildes, at-symbols, pound (#), and back ticks mean? </p><h3 id="data-is-beautiful-and-so-is-code">Data is beautiful, and so is code?</h3><p>It&apos;s no coincidence Clojure forms (function calls) share a similar syntax to Clojure&apos;s list type. Clojure forms are lists! Every Clojure developer has made this mistake (and, some tired days, many times): </p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">user&gt; (1 2 3)
Execution error (ClassCastException) at user/eval79101 (dev.clj:82).
class java.lang.Long cannot be cast to class clojure.lang.IFn (java.lang.Long is in module java.base of loader &apos;bootstrap&apos;; clojure.lang.IFn is in unnamed module of loader &apos;app&apos;)                                                                          
user&gt; &apos;(1 2 3)                                                                                  
(1 2 3)</code></pre><figcaption>Clearly, not your dad&apos;s parens</figcaption></figure><p>Since Clojure forms are just lists, we can treat Clojure code like data because <em>it is data</em>. What happens if we use that little quote <code>&apos;</code> on a function? Check it out:</p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">user&gt; &apos;(defn hello-world [] (println &quot;Hello, data! Or code??&quot;))
(defn hello-world [] (println &quot;Hello, data! Or code??&quot;))
user&gt; (eval &apos;(defn hello-world [] (println &quot;Hello, data! Or code??&quot;)))
#&apos;user/hello-world
user&gt; (hello-world)
Hello, data! Or code??
nil
user&gt; </code></pre><figcaption>A list evaluating a list of lists, List-ception</figcaption></figure><p>We get a list! Specifically, we get a list starting with two symbols, <code>defn</code> and <code>hello-world</code>, followed by an empty vector, trailing with another list containing the symbol <code>println</code> and a string. With such a list, we can pass it to <code>eval</code> to get our function. <code>eval</code> evaluates its input into something useful, whether it&apos;s a map or a function. This reveals the heart of our macro, we simply return code to be evaluated and used. </p><p>But there&apos;s a problem with the previous code though. We can&apos;t really manipulate Clojure code like this because all the contents of the list get evaluated on their own. If we want to operate on code, we have to do it before the Clojure compiler evaluates our code.</p><h3 id="all-the-cool-compilers-read">All the cool compilers Read</h3><p>A lisp compiler has a stage before evaluation called reading. A program called the reader reads the code from source files and then evaluates it. Lucky for us we can manipluate code before evaluation with a macro! In this sense, macros are like special functions for the reader, and Clojure provides us with a special form for creating macros called <code>defmacro</code>. </p><p>Using <code>defmacro</code>, the <code>def-</code> macro below returns a list of symbols and lists, so evaluation can turn it into a handy form that binds a symbol to <code>decls</code> with the private metadata flag set to true so functions outside this namespace can&apos;t access the symbol&apos;s value.</p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">(defmacro def-
  &quot;same as defn-, yielding non-public def&quot;
  [name &amp; decls]
  (list* `def
         (with-meta name
           (assoc (meta name) :private true))
         decls))</code></pre><figcaption>Keep your hands off my def</figcaption></figure><p>Notice the backtick in front of <code>def</code> in our <code>def-</code> macro? Backtick in Clojure is called Syntax Quote, and works like the quote but will fully resolve symbols for us. In other words, it&apos;ll find the symbol&apos;s namespace for us. For example, <code>`def</code> yields <code>clojure.core/def</code> . Without syntax quote our <code>def</code> is just a plain symbol devoid of any value in the symbol table to the Clojure reader. </p><pre><code class="language-clojure">user&gt; `(defn hello-world [] (println &quot;Hello, data! Or code??&quot;))
(clojure.core/defn
  user/hello-world
  []
  (clojure.core/println &quot;Hello, data! Or code??&quot;))
user&gt; </code></pre><p>So to tell the reader, &quot;hey look here for this thing&quot;, we need to give it directions to something already in the symbol table by using the fully qualified symbol (a symbol with a namespace prefix). &#xA0;We have to fully qualify our symbols in macros because namespace aliases don&apos;t exist to the reader. Normally an alias might look like using <code>(:require [foo.bar :as foob])</code> at the top of your Clojure source file. Because the Clojure compiler automatically imports all of <code>clojure.core</code> to every source file, we still have to account for it as an alias in the form <code>(:require [clojure.core :refer :all])</code> .</p><h3 id="your-favorite-unquote">Your favorite Unquote?</h3><p>You&apos;ll almost always see Syntax Quote close to <code>~</code>, or unquote, in Clojure macros. We can think of it as an operator to evaluate just this one thing. Similarly, we&apos;ll see <code>~@</code> , or unquote splice, and we can think of unquote splice as an operator to pull data out of a list. This example from the Clojure documentation demonstrates the use of syntax quote, unquote, and unquote splicing pretty well:</p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">user=&gt; (def x 5)
user=&gt; (def lst &apos;(a b c))
user=&gt; `(fred x ~x lst ~@lst 7 8 :nine)
(user/fred user/x 5 user/lst a b c 7 8 :nine)</code></pre><figcaption>from <a href="https://clojure.org/reference/reader?ref=blog.janetacarr.com#syntax-quote">https://clojure.org/reference/reader#syntax-quote</a></figcaption></figure><p>Unquote and unquote splice are instrumental to writing macros where we can add our own features to Clojure as these give us the ability to have values, and unfurl lists. So putting those together, we can get the gist of something like <code>when-let</code> :</p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">(defmacro when-let
  &quot;bindings =&gt; binding-form test
  When test is true, evaluates body with binding-form bound to the value of test&quot;
  {:added &quot;1.0&quot;}
  [bindings &amp; body]
  (assert-args
     (vector? bindings) &quot;a vector for its binding&quot;
     (= 2 (count bindings)) &quot;exactly 2 forms in binding vector&quot;)
   (let [form (bindings 0) tst (bindings 1)]
    `(let [temp# ~tst]
       (when temp#
         (let [~form temp#]
           ~@body)))))</code></pre><figcaption>from <a href="https://github.com/clojure/clojure/blob/clojure-1.10.1/src/clj/clojure/core.clj?ref=blog.janetacarr.com#L1861">clojure.core</a>, under license of course</figcaption></figure><p>Looking at <code>when-let</code> , we can see this macro takes a vector of <code>bindings</code> and <code>body</code> of forms in a multivariant argument list. The first <code>let</code> takes the first and second values out of the bindings, just like we&apos;d expect from a <code>let</code> but then passes the second binding, <code>tst</code> to syntax quoted <code>let</code>, setting it to a temporary binding called <code>temp#</code> . <code>temp#</code> gets used as the test for our <code>when</code> macro where <code>temp#</code> gets bound again to the first value (a simple symbol) in our original bindings. Finally, <code>body</code> gets unquote spliced to take out all the forms in the list <code>body</code> is and passed to an implicit <code>do</code> in the closest <code>let</code> . The implicit <code>do</code> is very important as we&apos;d just be returning a list of forms again. If there wasn&apos;t an implicit one, you&apos;d have to use an explicit one.</p><p>We can expand our use of <code>when-let</code> using <code>macroexpand-1</code> and <code>macroexpand</code> to see the first step and all steps in macro expansion, respectively.</p><pre><code class="language-clojure">user&gt; (macroexpand-1 &apos;(when-let [cool &quot;hi&quot;] (println cool)))
(clojure.core/let
    [temp__5804__auto__ &quot;hi&quot;]
  (clojure.core/when
      temp__5804__auto__
    (clojure.core/let [cool temp__5804__auto__] (println cool))))
user&gt; (macroexpand &apos;(when-let [cool &quot;hi&quot;] (println cool)))
(let*
    [temp__5804__auto__ &quot;hi&quot;]
  (clojure.core/when
      temp__5804__auto__
    (clojure.core/let [cool temp__5804__auto__] (println cool))))
user&gt; </code></pre><p>Hey wait, what the hell is <code>temp__5804__auto__</code>? Remember early when I talked about how the reader has no concept of aliasing? If we want to use simple (unqualified) symbols, we also have the potential for symbols having the same names (symbol collision), where ever the macro is used. To avoid symbol collision the hash used at the end of <code>temp#</code> in a macro tells the reader to generate a symbol for us. The hash will only generate one unique symbol though. If we wanted to have a <em>recursive macro</em> with a unique symbol for each <em>recursive call</em>, we call the <code>gensym</code> function to generate a unique symbol each call.</p><h3 id="too-long-didnt-read">Too long; didn&apos;t read</h3><p>Macros are a cool, powerful feature of Clojure. While they are great fun to write, they are often discouraged in codebases because of the complexity of using code to manipulate other code. Often, this makes macros a nightmare to maintain and debug. The goal of this post is to give you the confidence and tools to read and understand macros as Clojure macros have been the subject of whole books. </p><p>A quick summary:</p><ul><li>Macros are code that operates on other code, and are used in the read stage</li><li>Clojure forms are really just lists</li><li>Get a list with simple symbols by prefixing our function call with <code>quote</code> or <code>&apos;</code></li><li>Get a list with fully qualified symbols by prefixing our function or list with a syntax quote &#xA0;<code>`(defn hello-world ...)</code> </li><li>Evaluate something using unquote or <code>~</code> in a macro</li><li>Pull out the contents of a list using unquote splicing or <code>~@</code></li><li>A symbol postfixed with a <code>#</code> will yield a unique symbol by the syntax reader</li><li>If you need a unique symbol for each recursive macro expansion, use the <code>gensym</code> function.</li></ul><p>And that&apos;s it, I hope you learned enough to feel confident working with macros.</p>]]></content:encoded></item><item><title><![CDATA[Clojure Frameworks: opinions are features, not bugs]]></title><description><![CDATA[Ever since I wrote Clojure needs a Rails, folks reach out to ask for my opinion on their web framework for Clojure. What's clear from these discussions is a lot of software developers have no idea what a framework is.]]></description><link>https://blog.janetacarr.com/clojure-frameworks-opinions-are-features-not-bugs/</link><guid isPermaLink="false">63729ddd3016ac003d5d2e44</guid><category><![CDATA[clojure]]></category><category><![CDATA[clojurescript]]></category><category><![CDATA[computer programming]]></category><category><![CDATA[functional programming]]></category><category><![CDATA[software development]]></category><category><![CDATA[software engineering]]></category><dc:creator><![CDATA[Janet A. Carr]]></dc:creator><pubDate>Sat, 03 Dec 2022 16:51:45 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1465829235810-1f912537f253?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDJ8fGZyYW1ld29ya3xlbnwwfHx8fDE2Njg1NjA2Nzk&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<blockquote>Dear Janet, we decided to build our own Clojure(script) framework called Enjure because none of the existing options suited our needs. We&apos;re committed to the success of Enjure, but our investors think we&apos;re distracted from our core business. Can you help us figure out how we can sell our investors on building something we can&apos;t sell? Thanks, Jimmy James CTO of SuperREEL. </blockquote><img src="https://images.unsplash.com/photo-1465829235810-1f912537f253?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDJ8fGZyYW1ld29ya3xlbnwwfHx8fDE2Njg1NjA2Nzk&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Clojure Frameworks: opinions are features, not bugs"><p>Ever since I wrote <a href="https://blog.janetacarr.com/clojure-needs-a-rails/">Clojure needs a Rails</a>, folks reach out to ask for my opinion on their web framework for Clojure. What&apos;s clear from these discussions is a lot of software developers have no idea what a framework is. Frameworks follow a principle called &quot;Inversion of Control&quot;, where developers delegate crucial decisions for their application to the framework maintainers, allowing the developers to deliver the application faster. It is not a project template, a new paradigm, or module system. </p><h3 id="more-decisions-more-problems">More Decisions, More Problems</h3><p>Often, developers suffer from decision paralysis and excessive engineering prowess. I understand why developers are like this. I was like this too (see my <a href="https://blog.janetacarr.com/software-design-patterns-in-clojure/">design patterns posts</a> for years of pent up engineering hubris). Unfortunately, we are in the business of solving problems and making money with those solutions, so the sooner the better. We get there sooner by <em>not</em> bothering with things like architecture, databases, configuration, convention, and tooling, in other words, we can just get on with the coding.</p><h3 id="architecture">Architecture </h3><p>Arguably, the most important decision delegated to your framework is the software architecture, and many consider it the defining feature of a Software Framework, otherwise, you might just be using a software developer kit (SDK), bundle of libraries, or some toolkit. All of those are fine to use, but I doubt they&apos;ll be your <em>next Rails</em>. &#xA0;</p><h3 id="database">Database</h3><p>How frameworks handle databases tell me if you mean business. I don&apos;t care about how it gets done, honestly. I want a <code>defentity</code> macro (or something) and through the power of macro magic we get CRUD handlers (controllers?) for this entity, a dashboard to manipulate them, and hooks to control access. The core idea here being abstraction, why do we have to write the same queries over and over again? Most databases can be abstracted away in a data-mapper or ORM, I know those are dirty words to the Clojure community, but something truly great would give us the same powerful abstraction to create database <em>things</em> while allowing us to choose our database with an opinated plugin. </p><h3 id="tooling">Tooling</h3><p>Our toolchain and libraries fit the mould, our opinated MySQL or Datomic plugin just works, because it&apos;s made by the framework maintainers, and allows the same macro magic to create our entities. Notice how these plugins don&apos;t have the caveat of &#xA0;&quot;you can just replace the whole thing with modules/plugins!&quot;, if I wanted to do something like that, I would, yet again, start a project from scratch with<code>deps.edn</code> and the Clojure CLI. A bundle of libraries and glue code can masquerade as a framework without direction or purpose, so beware, you might end up configuring your whole stack anyways.</p><h3 id="configuration">Configuration</h3><p>EDN files, database migrations, environment variables, feature flags, software versioning, docker compose, <em>what the hell are we doing with our time</em>. Ask any Site Reliability Engineer(ing specialist for legal purposes), and she or he will tell you that configuration mishaps are responsible for a vast majority of incidents and outages, and we&apos;re still writing them all by hand over and over again. One snake_case name, where it should have been kebab-case, and now VP of Engineering is breathing down our Zoom call necks. </p><h3 id="convention">Convention</h3><p>Thanks to Clojure&apos;s dependence on camelCase virtual machines and their libraries, sometimes our conventions breaks. Hell, sometimes developers just don&apos;t care, yet developers make decisions every second of writing code and rely on those conventions to ship a functioning product. The cognitive overhead of using the REPL to dig into a software rotted library to see they keywordized the camelCase keys from JSONland not bothering to transform them to our beloved kebab-case (or worse, mixing them) causes bugs and slowdown. </p><h3 id="opinions-are-good-actually">Opinions are good, actually</h3><p>If the past several paragraphs were any indication, opinions are good. They might not be scalable to every project, but I think there will be opinions to fill the void at some point. I&apos;m writing this article because I see an awful lot of scoffing at the idea of something opinionated in the Clojure community. If you don&apos;t want something opinated, that&apos;s fine. Personally, I do not have the ego to say I&apos;m smarter than every other developer, so let me rewrite everything that has ever been written once again. So let me ask you dear reader, does this really command the pay of an expensive, paren wielding, high-value producing, knowledge worker? &#xA0;</p><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-text">Thanks for reading. If you like this post, subscribe for the next one or follow me on Twitter <a href="https://twitter.com/janetacarr?ref=blog.janetacarr.com">@janetacarr</a> , or don&apos;t &#xAF;\_(&#x30C4;)_/&#xAF; . Since I&apos;m sure people will have <em>strong opinions</em> on this subject, you can yell at me on Twitter or Reddit or wherever.&#xA0;</div></div>]]></content:encoded></item><item><title><![CDATA[My Guest Spot on Cognitect's podcast]]></title><description><![CDATA[<figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://cognitect.com/cognicast/172?ref=blog.janetacarr.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Janet A Carr - Cognicast Episode 172</div><div class="kg-bookmark-description">In this episode, Christian talks to Janet A Carr about her career, writing, and life as a Clojure Consultant.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://cognitect.com/android-icon-192x192.png" alt><span class="kg-bookmark-author">Cognitect.com</span><span class="kg-bookmark-publisher">Jaret Binford</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://s3.amazonaws.com/cognicast/covers/cognicast-172-janet.jpg" alt></div></a></figure>]]></description><link>https://blog.janetacarr.com/guest-spot-on-cognitects-podcast/</link><guid isPermaLink="false">637b9773e9bb1b003da1a493</guid><dc:creator><![CDATA[Janet A. Carr]]></dc:creator><pubDate>Mon, 21 Nov 2022 15:27:43 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://cognitect.com/cognicast/172?ref=blog.janetacarr.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Janet A Carr - Cognicast Episode 172</div><div class="kg-bookmark-description">In this episode, Christian talks to Janet A Carr about her career, writing, and life as a Clojure Consultant.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://cognitect.com/android-icon-192x192.png" alt><span class="kg-bookmark-author">Cognitect.com</span><span class="kg-bookmark-publisher">Jaret Binford</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://s3.amazonaws.com/cognicast/covers/cognicast-172-janet.jpg" alt></div></a></figure>]]></content:encoded></item><item><title><![CDATA[Clojure's typing "problem"]]></title><description><![CDATA[we can ship production code with Clojure. A strange bit of grumbling I hear from developers directs their angst toward not having "compile time type checking errors" ]]></description><link>https://blog.janetacarr.com/clojure-typing-problem/</link><guid isPermaLink="false">635a881976f1b1003d6f86f0</guid><category><![CDATA[clojure]]></category><category><![CDATA[clojurescript]]></category><category><![CDATA[computer programming]]></category><category><![CDATA[functional programming]]></category><category><![CDATA[software development]]></category><category><![CDATA[software engineering]]></category><dc:creator><![CDATA[Janet A. Carr]]></dc:creator><pubDate>Wed, 16 Nov 2022 14:32:06 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1463171379579-3fdfb86d6285?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDN8fHR5cGluZyUyMHByb2JsZW18ZW58MHx8fHwxNjY3NzUzMjYw&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<blockquote>Hi Janet, we&apos;re using clojure.spec, plumatic schema, and core.typed to get rid of that pesky dynamic typing Clojure has, but we find ourselves writing the same functions for each different type! We&apos;re slow and missing our agile deadlines, but we&apos;re unsure of how to manage our large codebase without all of spec&apos;s horrible errors. What do you suggest ? Jimmy James, Co-founder and CTO of SuperREEL</blockquote><h3 id="heres-the-thing">Here&apos;s the thing,</h3><img src="https://images.unsplash.com/photo-1463171379579-3fdfb86d6285?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDN8fHR5cGluZyUyMHByb2JsZW18ZW58MHx8fHwxNjY3NzUzMjYw&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Clojure&apos;s typing &quot;problem&quot;"><p>I see this a lot from clients, employers, hackers, lovers, and haters. <strong>Clojure&apos;s dynamic typing is a feature, not a bug.</strong> If you&apos;ve ever written a Python script, you know what I&apos;m talking about, but Clojure takes it much further, giving us rare occasion to check types. We can ship code without static typing, we can provide guard rails for our programs, and we can do it without an alpha version.</p><h3 id="programs-get-built">Programs get built</h3><p>Yes, we can ship production code with Clojure. A strange bit of grumbling I hear from developers directs their angst toward not having &quot;compile time type checking errors&quot; when using Clojure, leading them to simply chalk up Clojure to being unusable (?). Clojure ships with a lot similar data structures as Java, for example, you can still shoot yourself in the foot with a <code>java.util.HashMap</code> as the <code>get(key)</code> method still returns null if the value doesn&apos;t exist. Now, if you&apos;re one of those static programming language developers opting to use something more familiar like &#xA0;a class/struct/union/process, <em>Congratulations</em>. I think you&apos;ll find a degree of rigidity not present in Clojure. Rigidity = friction and friction = lower velocity. I like to ship code, and I&apos;m usually pretty confident my Clojure code will work because I have the REPL and an endless amount of parameter checking libraries.</p><h3 id="we-all-have-boundaries">We all have boundaries</h3><p>I&apos;m not talking about those boundaries! (although, do respect them, please). I&apos;m talking about system boundaries. It&apos;s no secret I dislike the over zealous use of Clojure.spec and friends, and I hate the friction it adds development. So in the past<a href="https://blog.janetacarr.com/write-clojure-for-other-developers/"> I&apos;ve recommended using it on your system boundaries</a>, if you must. Lately, for my web apps, I&apos;ve been using <a href="https://github.com/metosin/malli?ref=blog.janetacarr.com">Malli</a> as the type checking and coercion for RESTful APIs routed with <a href="https://github.com/metosin/reitit?ref=blog.janetacarr.com">Reitit</a>. It&apos;s great. After that, the gloves come off, because spending the overhead of &apos;specing&apos; on top of REPLing and testing Clojure code, I find Clojure.spec doesn&apos;t add much value for the time cost. Lucky for us, we get some goodies from Clojure to help with type woes. Clojure&apos;s collections, vectors, maps, and sets (and nil?), all support the same handful of functions. I&apos;ve talked about how a <a href="https://blog.janetacarr.com/software-design-patterns-in-clojure/#null-object">type or interface is really a bag of functions</a>. Replacing an indexed value in a Clojure vector is a surprisingly annoying task, but I think most developers don&apos;t realize you can actually call <code>assoc</code> on a vector using the index as a key (or at least I don&apos;t see it in my Clients&apos; codebases much). </p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">user&gt; (assoc (vec (range 10)) 3 5)
[0 1 2 5 4 5 6 7 8 9]
user&gt; (defn replace-i [v i value] (into (conj (vec (take i v)) value) (drop (inc i) v)))
#&apos;user/replace-i
user&gt; (replace-i (vec (range 10)) 3 5)
[0 1 2 5 4 5 6 7 8 9]</code></pre><figcaption>Brilliant.</figcaption></figure><p>I&apos;m sure some people will see this as just function overloading, but I want you to know that they&apos;re<em> god damned liars</em>. I like to think of this as the &quot;do nothing&quot; option, and I have never experienced serious typing problems with Clojure. I have experienced issues with Clojure.spec itself though because Clojure.spec suffers from terminal alpha versioning.</p><h3 id="the-versioning">The versioning</h3><p>Since its inception, Clojure.spec remains in alpha. I&apos;ll admit the stability of Clojure.spec is relatively good since it&apos;s debut. However, I do think this a sore spot, implying Clojure.spec should not be used in production, even though everyone does. </p><p>We can ship production code with Clojure, and we don&apos;t need a compiler to tell us to write our code. (But we might need one for Clojurescript ;)</p><blockquote><em>Thanks for reading. Usually this is where I invite people to discuss what I&apos;ve written here, but honestly I felt like this post was a bit of a dump of half-baked ideas and passion for my Clojure flow state, so maybe just subscribe for the next one, &#xA0;follow me on twitter </em><a href="https://twitter.com/janetacarr?ref=blog.janetacarr.com"><em>@janetacarr</em></a><em> , or don&apos;t </em>&#xAF;\_(&#x30C4;)_/&#xAF; <em>. </em></blockquote>]]></content:encoded></item><item><title><![CDATA[Fix your Clojure code: Clojure comes with design patterns (Part 2)]]></title><description><![CDATA[<div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-text">This post is the second in a series. You can find the first post in the series <a href="https://blog.janetacarr.com/software-design-patterns-in-clojure/">here</a> where I covered Null Object, Singleton, Command, Observer, State, Visitor, and Iterator.</div></div><h3 id="patterns">Patterns</h3><ul><li><a href="#our-story-continues">Preamble</a></li><li><a href="#builder">Builder</a></li><li><a href="#chain-of-responsibility">Chain of Responsibility</a></li><li><a href="#proxy">Proxy</a></li><li><a href="#adapter">Adapter</a></li><li><a href="#template-method">Template Method</a></li><li><a href="#flyweight">Flyweight</a></li><li><a href="#strategy">Strategy</a></li></ul><h3 id="our-story-continues">Our story continues</h3><p>Edmund, a bright, awkward young</p>]]></description><link>https://blog.janetacarr.com/fix-your-clojure-code-clojure-comes-with-design-patterns-part-2/</link><guid isPermaLink="false">63063b46b4cc93003d7dccc7</guid><dc:creator><![CDATA[Janet A. Carr]]></dc:creator><pubDate>Fri, 09 Sep 2022 16:58:01 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1476357471311-43c0db9fb2b4?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fHNvZnR3YXJlJTIwZGVzaWduJTIwbGFuZ3VhZ2V8ZW58MHx8fHwxNjYyNTA0NTAw&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-text">This post is the second in a series. You can find the first post in the series <a href="https://blog.janetacarr.com/software-design-patterns-in-clojure/">here</a> where I covered Null Object, Singleton, Command, Observer, State, Visitor, and Iterator.</div></div><h3 id="patterns">Patterns</h3><ul><li><a href="#our-story-continues">Preamble</a></li><li><a href="#builder">Builder</a></li><li><a href="#chain-of-responsibility">Chain of Responsibility</a></li><li><a href="#proxy">Proxy</a></li><li><a href="#adapter">Adapter</a></li><li><a href="#template-method">Template Method</a></li><li><a href="#flyweight">Flyweight</a></li><li><a href="#strategy">Strategy</a></li></ul><h3 id="our-story-continues">Our story continues</h3><img src="https://images.unsplash.com/photo-1476357471311-43c0db9fb2b4?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fHNvZnR3YXJlJTIwZGVzaWduJTIwbGFuZ3VhZ2V8ZW58MHx8fHwxNjYyNTA0NTAw&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Fix your Clojure code: Clojure comes with design patterns (Part 2)"><p>Edmund, a bright, awkward young man with a masters degree from a prestigious University, loves functional programming, but his views are too pure for Suzi&apos;s taste. He always drones on about how we don&apos;t need to think about any of those design patterns things because &quot;that&apos;s only for object-oriented programming&quot;. </p><p>However, Edmund&apos;s latest project with an intern, a load testing application, was taking far too long, like most projects at StartupAI. Despite the mythical (wo)man-month, Suzi&apos;s manager asks her to join the project, and she agrees. </p><p>&quot;We see the heart of this project as state machine&quot; Edmund says, during a code walk through.</p><p>To Suzi surprise, she sees a dense <code>case</code> form. &quot;Uh oh&quot; thinking to herself. </p><p>Next Edmund shows her the dozens of functions created to manufacture types to kick start the state machine. Of course, whenever they have to change these functions, they have to change the state machine and vise-versa. To top it all off, they&apos;re using Clojure futures to generate the load tests, attempting to coordinate all the futures and their requests. Lucky for Suzi, she knows why they&apos;re not progressing on the project, and why it doesn&apos;t work at all. </p><p>&quot;I have an idea, why don&apos;t you replace this <code>case</code> form with a state pattern, and these functions with a builder?&quot; &#xA0;Suzi says gently presenting the idea.</p><p>&quot;Oh, I just prefer not to do those kind of things in functional programming.&quot; He replies.</p><p>&quot;Right, but it would decouple the state machine from the this namespace, and you can decouple your functions here from this code down here.&quot; She says while pointing with her pen at the functions on the screen from earlier, and gesturing downward at the state machine. Continuing, &quot;And, you can ditch this whole futures thing. Just use core.async&quot;.</p><p>&quot;What&apos;s core.async?&quot; Edmund asks no one in particular while typing &apos;clojure core async&apos; into the browser search bar.</p><p>&quot;Communicating Sequential Processes in Clojure. It handles thread pooling and everything, all we have to do is dispatch work to the &apos;go loops&apos;.&quot; Suzi answers. </p><p>Oh.</p><h3 id="builder">Builder</h3><blockquote>Separate the construction of a complex object from its representation so that the same construction process can create different representations.</blockquote><p>A lot of patterns become thinking about, and structuring of, the flow of higher-order functions and their composition. While the functions may seem vague, we need to keep in mind our function&apos;s <em>intent</em>. With the builder pattern we want to delegate object (or function) construction (composition) .</p><!--kg-card-begin: markdown--><h6 id="when-to-use-it">When to use it</h6>
<p>When you want to decouple the construction of a complex object from the context it&apos;s used in.</p>
<h6 id="clojure-analogue">Clojure analogue</h6>
<ul>
<li><code>partial</code> or <code>fn</code> and <code>comp</code> - Most design patterns are a response to missing features from functional programming. The command pattern address the lack of higher order functions in Object Oriented programming languages. So in this respect, the builder pattern addresses the lack of <a href="https://en.wikipedia.org/wiki/Currying?ref=blog.janetacarr.com">currying</a>. Unfortunately, Clojure also doesn&apos;t support currying, but we can get a close approximation with partial function composition using <code>partial</code> or <code>fn</code> and <code>comp</code>.</li>
<li><code>cond-&gt;</code> and <code>assoc</code> and related map functions - In practice most &quot;builders&quot; are really just methods to set some kind of member values rather than delegating object construction. We see this a lot in something like Go where a struct has receivers that return a new struct, allowing for chaining of call like <code>MyCoolStruct.WithFun(&quot;stuff&quot;).WithHydration(&quot;Water&quot;).WithCode(&quot;Clojure&quot;)</code>. If you&apos;re idea of a builder looks like this, you can probably get pretty far with threading macros and map functions like <code>assoc</code>, <code>update</code>, <code>merge</code> since they all take a hash map as an argument and return a hash map, or just make up your own functions!</li>
</ul>
<h6 id="keep-in-mind">Keep in mind</h6>
<ul>
<li>Partial function composition can get hairy since you can&apos;t name the function produced by either <code>partial</code> or <code>comp</code>.</li>
<li>When using <code>partial</code> and <code>comp</code>, take care to remember that transducers exist. Depending on your use case composing a transform from transducers (<code>map</code>, <code>filter</code>, etc) will be much more performant than creating partial functions over them.</li>
</ul>
<h6 id="sample-code">Sample code</h6>
<pre><code class="language-clojure">;; builder
;; now we can delegate our map construction to this
;; function.
(defn build-s3-client
  [mock-creds ssl default-bucket sts]
  (let [if-fn (fn [cond f] (if cond f identity))]
    (comp
     (if-fn (not (empty? creds))
       #(let [secret (s/gen :specs/client-secret)
              access-key (s/gen :specs/access-key)]
          (merge % {:client-secret (g/generate secret)
                    :access-key (g/generate access-key)})))

     (if-fn ssl #(assoc % :ssl true))

     (if-fn (and (string? default-bucket)
                 (not (empty? default-bucket)))
       #(assoc % :default-bucket default-bucket))

     (if-fn (and (string? sts)
                 (not (empty? sts))
                 (some? (re-matches #&quot;.&quot; sts)))
       #(assoc % :sts-grant sts)))))
   
(def s3-client 
  (build-s3-client {} false &quot;my-bucket&quot; &quot;real-token&quot;))

;; Chaining technique
(defn -&gt;s3-client
  []
  (let [{:keys [aws-secret-key
                aws-access-key]} env]
    {:client-secret client-secret
     :access-key access-key}))

(defn with-ssl
  [m]
  (assoc m :ssl true))

(defn with-default-bucket
  [m bucket]
  (assoc m :default-bucket bucket))

(defn with-sts
  [m token]
  (assoc m :sts-grant token))

(defn with-mock-credentials
  [m]
  (let [secret (s/gen :specs/client-secret)
        access-key (s/gen :specs/access-key)]
    (merge m {:client-secret (g/generate secret)
              :access-key (g/generate access-key)})))

(defn build-s3-client
  [bucket]
  (-&gt; (-&gt;s3-client)
      (with-ssl)
      (with-default-bucket bucket)))

(defn mock-s3-client
  [bucket]
  (-&gt; (-&gt;s3-client)
      (with-mock-credentials)
      (with-bucket bucket)))
</code></pre>
<!--kg-card-end: markdown--><hr><h3 id="chain-of-responsibility">Chain of Responsibility </h3><blockquote>Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.</blockquote><p>The structure of this pattern seems similar to the builder, but our intent for our functions is different. And, If I&apos;m being honest, the only Chain of Responsibility I&apos;ve ever seen, even outside of Clojure, is the middleware chain in ring applications.</p><!--kg-card-begin: markdown--><h6 id="when-to-use-it">When to use it</h6>
<p>When you want to decouple a request from its handler.</p>
<h6 id="clojure-analogue">Clojure analogue</h6>
<ul>
<li><code>-&gt;</code> or <code>-&gt;&gt;</code> and <code>fn</code> - Using the thread macro through lambdas that have the same function signature, creating closures over closures until its final form.</li>
</ul>
<h6 id="keep-in-mind">Keep in mind</h6>
<ul>
<li>Chain of Responsibility in Clojure has the same caveats as the command pattern from the <a href="https://blog.janetacarr.com/software-design-patterns-in-clojure/#command">last post</a>. Be sure to name your <code>fn</code> forms because the stack traces from the Chain of Responsibility are challenging to debug as the chain can sometimes be quite long.</li>
<li>Like all threading macros, If the chain order matters, you will have to structure your handlers in reverse order. For example, in the case of ring middleware you want the function returned by <code>wrap-authentication</code> to evaluate before the function returned by <code>wrap-authorization</code>.</li>
</ul>
<h6 id="sample-code">Sample code</h6>
<p>Ring middleware gives us the best and most prevalent example of a Chain of Responsibility in Clojure. In this example <a href="https://github.com/funcool/buddy-auth/blob/ec454fecd3a84746c8e7b9e3af942cb1a692fdbd/src/buddy/auth/middleware.clj?ref=blog.janetacarr.com#L53"><code>wrap-authentication</code></a> and <a href="https://github.com/funcool/buddy-auth/blob/ec454fecd3a84746c8e7b9e3af942cb1a692fdbd/src/buddy/auth/middleware.clj?ref=blog.janetacarr.com#L103"><code>wrap-authorization</code></a> are adapted from buddy.auth.</p>
<pre><code class="language-clojure">(defn wrap-authentication
  &quot;Ring middleware that enables authentication for your ring
  handler. When multiple `backends` are given each of them gets a
  chance to authenticate the request.&quot;
  [handler &amp; backends]
  (fn authentication-handler
    ([request]
     (handler (apply authentication-request request backends)))
    ([request respond raise]
     (handler (apply authentication-request request backends) 
              respond 
              raise))))
    
;; lots of code in between. Just pretend it&apos;s here for
;; the sake of this example.

(defn wrap-authorization
  &quot;Ring middleware that enables authorization
  workflow for your ring handler.
  The `backend` parameter should be a plain function
  that accepts two parameters: request and errordata
  hashmap, or an instance that satisfies IAuthorization
  protocol.&quot;
  [handler backend]
  (fn authorization-handler
    ([request]
     (try (handler request)
          (catch Exception e
            (authorization-error request e backend))))
    ([request respond raise]
     (try (handler request respond raise)
          (catch Exception e
            (respond (authorization-error request e backend)))))))
     
;; In another namespace:
;; Middleware usage
(def app
  (-&gt; compojure-routes
      (wrap-authorization jwe)
      (wrap-authentication jwe)
      (wrap-cors :access-control-allow-origin [#&quot;.*&quot;]
                 :access-control-allow-methods [:get :post])
      (wrap-json-response {:pretty false})
      (wrap-json-body {:keywords? true})
      (wrap-accept {:mime [&quot;application/json&quot; :as :json
                           &quot;text/html&quot; :as :html]})
      (wrap-cookies)
      (wrap-params)))
</code></pre>
<!--kg-card-end: markdown--><hr><h3 id="proxy">Proxy</h3><blockquote>Provide a surrogate or placeholder for another object to control access to it.</blockquote><p>Unlike the only Chain of Responsibility I&apos;ve seen, <em>I have</em> seen a proxy once or twice. Usually developers don&apos;t use the <code>proxy</code> form, rather opting to wrap a function in another function to restrict access, lazy typing, or virtualization. </p><!--kg-card-begin: markdown--><h6 id="when-to-use-it">When to use it</h6>
<p>The Gang of Four quote is pretty legible on this one. Use a proxy as a &apos;middleman&apos; for (controlling) access to another object. You can also use it for creating a lazily loaded object if a <code>LazySeq</code> doesn&apos;t do it for you.</p>
<h6 id="clojure-analogue">Clojure analogue</h6>
<ul>
<li><code>proxy</code> - Clojure ships with a whole set of proxy-related functions. They are seldom used as developers typically prefer to use <code>reify</code>(and related forms). Unlike <code>reify</code>, <code>proxy</code>can be used to instantiate Java classes, not just interfaces and protocols.</li>
<li>You could use higher-order <code>fn</code> to have a proxy too, but at this point the idea is getting repetitive, so I&apos;m just going to keep it to the quirky, interesting stuff.</li>
</ul>
<h6 id="keep-in-mind">Keep in mind</h6>
<ul>
<li>The proxy functions <code>proxy</code>, <code>proxy-super</code>, <code>init-proxy</code>, <code>update-proxy</code>, <code>construct-proxy</code>, <code>get-proxy-class</code>, and <code>proxy-mapping</code> are old (Clojure 1.0) and reminiscent of Object-oriented programming. If you didn&apos;t know what a proxy was, you might end up doing double the work of plain old interop when using <code>proxy</code>.</li>
<li>Some of the proxy functions like <code>proxy-super</code> expand to use reflection on their <code>this</code> argument unless <a href="https://blog.janetacarr.com/how-clojure-works-for-you/#type-hinting">type hinted</a>.</li>
<li>Like all extensibility on the JVM, <code>proxy</code> can&apos;t inherit from a <code>final class</code> which also means no proxies to Clojure records.</li>
<li>You can&apos;t proxy a proxy, meaning you can&apos;t use <code>proxy</code> on something that already implements Clojure&apos;s <code>IProxy</code> interface. If you could, that&apos;d be OOP. This isn&apos;t <em>Common Lisp</em>.</li>
</ul>
<h6 id="sample-code">Sample code</h6>
<pre><code class="language-clojure">(defn access-controlled-input-stream
  &quot;Returns an access controlled InputStream&quot;
  [user]
  (proxy [java.io.InputStream] []
    (read
      ([]
       (if (allowed? user)
         (let [^java.io.InputStream this this]
           (proxy-super read))
         (throw (ex-info &quot;Unauthorized&quot;
                         {:user user}))))
      ([^bytes b]
       (if (allowed? user)
         (let [^java.io.InputStream this this]
           (proxy-super read b))
         (throw (ex-info &quot;Unauthorized&quot;
                         {:user user}))))
      ([^bytes b off len]
       (if (allowed? user)
         (let [^java.io.InputStream this this]
           (proxy-super read b off len))
         (throw (ex-info &quot;Unauthorized&quot;
                         {:user user})))))))
</code></pre>
<!--kg-card-end: markdown--><hr><h3 id="adapter">Adapter</h3><blockquote>Convert the interface of a class into a another interface clients expect. Adapter lets classes work together that couldn&apos;t otherwise because of incompatible interfaces.</blockquote><p>You don&apos;t need to always use a function to wrap something, you can also use an adapter. Adapters are the ultimate glue code and de facto polymorphism (protocols) in Clojure. If we consider a type an interface (or bag of functions&#x2122;), any library or API could be considered a interface, so we can wrap it in an adapter for core business logic for when we want to swap it out<a href="#paa"><sup>1</sup></a>. Or not, if you&apos;re an &quot;aren&apos;t going to need it&quot; person.</p><!--kg-card-begin: markdown--><h6 id="when-to-use-it">When to use it</h6>
<p>When you want to use an implementation with a different interface. Also called a <em>wrapper</em>.</p>
<h6 id="clojure-analogue">Clojure analogue</h6>
<ul>
<li>protocols - Any Clojure type can be extended to support a particular protocol using <code>extend-type</code>.</li>
</ul>
<h6 id="keep-in-mind">Keep in mind</h6>
<ul>
<li>Using an adapter can be a symptom of a leaky abstraction.</li>
</ul>
<h6 id="sample-code">Sample code</h6>
<pre><code class="language-clojure">;; Shamelessly using protocols example from last post

;; our expect interface
(defprotocol MoneySafe
  &quot;A type to convert other money type to bigdec&quot;
  (make-safe [this] &quot;Coerce a type to be safe for money arithmetic&quot;))

;; our conversions, could also extend Java objects here.
(extend-protocol MoneySafe
  java.lang.Number 
  (make-safe [this] (bigdec this))

  java.lang.String
  (make-safe [this]
    (try
      (-&gt; this
          (Double/parseDouble)
          (bigdec))
      (catch NumberFormatException nfe
        (println &quot;String must be string of number characters&quot;))
      (catch Exception e
        (println &quot;Unknown error converts from string to money&quot;)
        (throw e))))

  clojure.lang.PersistentVector
  (make-safe [this]
    (try
      (let [num-bytes (-&gt;&gt; this (filter int?) (count))]
        (if (= (count this) num-bytes)
          (-&gt;&gt; this
               (map char)
               (clojure.string/join)
               (Double/parseDouble)
               (bigdec))
          (throw (ex-info &quot;Can only convert from vector of bytes&quot;
                          {:input this}))))
      (catch NumberFormatException nfe
        (println &quot;Vector must be bytes representing ASCII number chars&quot;)
        (throw nfe))
      (catch Exception e
        (println &quot;Error converting from vector of bytes to money&quot;)
        (throw e)))))

;; our client
(defn -&gt;money
  [x]
  (make-safe x))
</code></pre>
<!--kg-card-end: markdown--><hr><h3 id="template-method">Template Method</h3><blockquote>Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine steps of an algorithm without changing the algorithm&apos;s structure.</blockquote><p>Yet lots of people need template methods (functions?) since I&apos;ve seen plenty of template functions in Clojure codebases over the years. Template functions get pretty hairy when the delegate functions get spread out over the codebase, doubly so if unamed lambdas are used. If you need to write functions across the vast expanse of your namespaces, use a <a href="#strategy">strategy</a> instead. </p><!--kg-card-begin: markdown--><h6 id="when-to-use-it">When to use it</h6>
<p>Use a template method when you want to decouple primitives or subroutines of an algorithm from the overaching structure.</p>
<h6 id="clojure-analogue">Clojure analogue</h6>
<ul>
<li>Variodic function arguments with function composition - We could call this a template function rather than a template method. Variodic functions will give us the ability to define defaults as well as mandatory implementations.</li>
<li><code>do-template</code> - <code>do-template</code> evaluates an expression, grouping and feeding it&apos;s arguments into the template. It&apos;s good for a &quot;template method&quot; where the overrides are primitives or all &quot;subtypes&quot; of the template method/function are evaluated in the same client.</li>
</ul>
<h6 id="keep-in-mind">Keep in mind</h6>
<ul>
<li>Template methods are very similar to the strategy pattern, but tightly couple the subtypes to the template, implying function definition locality is your friend.</li>
<li>Depending on how important isolation of your variodic arguments is, You can swap out traditional variodic arguments for variodic keyword arguments in Clojure 1.11. For example, in our sample code below if we want to change the implementation of build-windows without changing build-foundation:</li>
</ul>
<h6 id="sample-code">Sample code</h6>
<pre><code class="language-clojure">;; our template defaults
(defn- build-foundation-default
  []
  (println &quot;Building foundation with cement iron rods and sand&quot;))
  
(defn- build-windows-default
  []
  (println &quot;Building glass windows&quot;))

;; The &quot;template&quot;
(defn build-house-template
  ([build-pillars build-walls]
   (build-house-template build-pillars
                         build-walls
                         build-foundation-default
                         build-windows-default))
  ([build-pillars build-walls build-foundation]
   (build-house-template build-pillars
                         build-walls
                         build-foundation
                         build-windows-default))
  ([build-pillars build-walls build-foundation build-windows]
   (build-foundation)
   (build-pillars)
   (build-walls)
   (build-windows)
   (println &quot;House is built.&quot;)))

(defn wooden-house
  []
  (build-house-template #(println &quot;Building pillars with wood coating&quot;)
                        #(println &quot;Building wooden walls&quot;)))

(defn glass-house
  []
  (build-house-template #(println &quot;Building pillars with glass coating&quot;)
                        #(println &quot;Building glass walls&quot;)))

;; our client
(defn house-builder
  [build-house]
  (build-house))
</code></pre>
<!--kg-card-end: markdown--><hr><h3 id="flyweight">Flyweight</h3><blockquote>Use sharing to support large numbers of fine-grained objects efficiently.</blockquote><p>Naturally, the Strategy pattern would follow from the template function, but I decided to do flyweight next. Flyweight is basically a cache. If you want to get fancy, you can use the Clojure core.cache library where you get a cache protocol, conveinence macros, and eviction algorithms. <em>Real caching</em>. If you need to share some good ol&apos; intrinsic state, here is a couple flyweight ideas for you.</p><!--kg-card-begin: markdown--><h6 id="when-to-use-it">When to use it</h6>
<p>Use a Flyweight when you have overlapping object usage between clients. Flyweights typically destinguish between extrinsic state and intrinsic state where the extrinsic state is context dependend and intrinsic is context <em>independent</em>. So, the intrinsic state gets shared between client contexts.</p>
<h6 id="clojure-analogue">Clojure analogue</h6>
<ul>
<li><code>memoize</code>  - <code>memoize</code> will store the return value of a function mapped to it&apos;s arguments, conflating the two parts of the flyweight, the flyweight factory and operation, into one single <code>memoize</code> call.</li>
<li><code>fn</code> over an <code>atom</code> - We might not necessarily want to use our <em>extrinsic state</em> as our <em>factory function key</em>. In normal dev speak, that means we might not necessarily want our function arguments to determine what state gets shared between clients.</li>
</ul>
<h6 id="keep-in-mind">Keep in mind</h6>
<ul>
<li>Introducing state (not the pattern) into your application means you have the potential to introduce certain bugs you wouldn&apos;t otherwise have. Use a <a href="https://blog.janetacarr.com/software-design-patterns-in-clojure/#observer">watch</a> to keep track of state changes if you&apos;re concerned about it.</li>
<li>Using the <code>atom</code> version of the -&gt;flyweight can be use in a local binding, but it will create a new atom, so be mindful of that.</li>
</ul>
<h6 id="sample-code">Sample code</h6>
<pre><code class="language-clojure">(defprotocol Sprite
  &quot;Describes a totally real sprite type&quot;
  (draw! [this x y height width]
    &quot;draw something to the screen.&quot;))

(deftype PlayerSprite [sprite-sheet x y height width]
  Sprite
  (draw! [this x y height width]
    &quot;Drew the player on the screen.&quot;))

(deftype EnemySprite [sprite-sheet x y height width]
  Sprite
  (draw! [this x y height width]
    &quot;Drew the enemy on the screen.&quot;))

;; Our &quot;flyweights&quot;
;; could store anything in memoize.
(def player-sprite
  (memoize #(-&gt;PlayerSprite (slurp &quot;./spritesheet.png&quot;)
                            {:x 0 :y 0 :height 32 :width 32})))

(def enemy-sprite
  (memoize #(-&gt;EnemySprite (slurp &quot;./spritesheet.png&quot;)
                           {:x 33 :y 33 :height 32 :width 32})))


;; Atom example
;; our flyweight function is similar to the body of memoize
;; except we want to use a keyword to get value instead
(defn -&gt;flyweight
  []
  (let [mem (atom {})
        player-coords {:x 0 :y 0 :height 32 :width 32}
        enemy-coords {:x 33 :y 33 :height 32 :width 32}
        sprites {:player #(-&gt;PlayerSprite (slurp &quot;./spritesheet.png&quot;)
                                          player-coords)
                 :enemy #(-&gt;EnemySprite (slurp &quot;./spritesheet.png&quot;)
                                        enemy-coords)}]
    (fn [k &amp; args]
      (if-let [e (find @mem k)]
        (val e)
        (when-let [f (get sprites k)]
          (let [ret (apply f args)]
            (swap! mem assoc k ret)
            ret))))))

(def flyweight (-&gt;flyweight))
</code></pre>
<!--kg-card-end: markdown--><hr><h3 id="strategy">Strategy</h3><blockquote>Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.</blockquote><p>There&apos;s no official Clojure library for Strategy though. This is kind of a boring pattern in Clojure because it&apos;s just a lambda, so I&apos;m including it completeness, but what blog post doesn&apos;t have fluff.</p><!--kg-card-begin: markdown--><h6 id="when-to-use-it">When to use it</h6>
<p>Use a Strategy when you need to decouple algorithms from where they&apos;re being used.</p>
<h6 id="clojure-analogue">Clojure analogue</h6>
<ul>
<li><code>fn</code> (again) - This time you&apos;ll have think real hard about the input and output of the higher-order functions you&apos;re passing around. <code>sort-by</code> allows you to pass in a key-fn as a strategy for getting the values to pass to the compare operation (or would that be a template method? Hmm....).</li>
</ul>
<h6 id="keep-in-mind">Keep in mind</h6>
<ul>
<li>The usual stuff with <code>fn</code>. Name your <code>fn</code> for debugging and recursion. I suppose you could name them <code>blah-blah-strategy</code>, but you might get flak for saying the pattern name in the code.</li>
</ul>
<h6 id="sample-code">Sample code</h6>
<pre><code class="language-clojure">;; I&apos;m not going to type out the sorts because I haven&apos;t
;; been in a CS classroom for years.
(defn quick-sort
  [coll])

(defn merge-sort
  [coll])

(defn radix-sort
  [coll])

(defn find-key
  &quot;Performs a binary search on coll after calling
  sort-fn on coll.&quot;
  [key coll sort-fn]
  (find (sort-fn coll) key))
  
;; client somewhere
(find-key :fun-key (get-list) radix-sort)
</code></pre>
<!--kg-card-end: markdown--><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-text"><em>Thanks for reading. As I said earlier, this is the second post in a series, and I think there might be one or two more, so subscribe for the next one or follow me on twitter </em><a href="https://twitter.com/janetacarr?ref=blog.janetacarr.com"><em>@janetacarr</em></a><em> , or don&apos;t </em>&#xAF;\_(&#x30C4;)_/&#xAF; <em>. You can also join the discussion about this post on twitter, hackernews, or reddit if you think I&apos;m wrong.</em></div></div><!--kg-card-begin: html--><p>
    <a name="paa">1.</a> Some people call this ports and adapters architecture.
    <br>
    <a name="digitalocean">2.</a>The template method example was inspired by <a href="https://www.digitalocean.com/community/tutorials/template-method-design-pattern-in-java?ref=blog.janetacarr.com">this Digital Ocean blog post</a>.
</p><!--kg-card-end: html-->]]></content:encoded></item><item><title><![CDATA[Fix your Clojure code: Clojure comes with design patterns (Part 1)]]></title><description><![CDATA[Clojure either directly supports, or easily supports the use of common design patterns like singleton, command, observer, visitor]]></description><link>https://blog.janetacarr.com/software-design-patterns-in-clojure/</link><guid isPermaLink="false">625ec6c46919b4003da77def</guid><category><![CDATA[clojure]]></category><category><![CDATA[clojurescript]]></category><category><![CDATA[computer programming]]></category><category><![CDATA[functional programming]]></category><category><![CDATA[software development]]></category><category><![CDATA[software engineering]]></category><dc:creator><![CDATA[Janet A. Carr]]></dc:creator><pubDate>Thu, 18 Aug 2022 14:52:13 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1573166364266-356ef04ae798?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDh8fHNvZnR3YXJlJTIwZGVzaWdufGVufDB8fHx8MTY2MDQ4NDU4Mg&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-text">This post will be part of a series since there are few dozen software design patterns I want to cover, but writing about all of them in one post will take ages.</div></div><h3 id="patterns">Patterns</h3><ul><li><a href="#a-motivational-story">Preamble</a></li><li><a href="#were-speaking-the-same-language">Protocols</a></li><li><a href="#null-object">Null Object</a></li><li><a href="#singleton">Singleton</a></li><li><a href="#command">Command</a></li><li><a href="#observer">Observer</a></li><li><a href="#state">State</a></li><li><a href="#visitor">Visitor</a></li><li><a href="#iterator">Iterator</a></li></ul><h3 id="a-motivational-story">A motivational story</h3><img src="https://images.unsplash.com/photo-1573166364266-356ef04ae798?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDh8fHNvZnR3YXJlJTIwZGVzaWdufGVufDB8fHx8MTY2MDQ4NDU4Mg&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Fix your Clojure code: Clojure comes with design patterns (Part 1)"><p>Suzi, after busting her ass at her first Clojure job, lands her second Clojure job at StartupAI. This company moved her half-way across the country to the Big City&#x2122;, filling her with naive excitement. When she finishes company on-boarding, Suzi submits her first pull request after several days of staggering through the code. While the code is the same Clojure she has always known and loved, the repository gives her stress headaches<em>. </em></p><p>The persistence namespace, the one with all the database queries, has eight different functions to get the same data using same query. Next, a minuscule change in the application layer causes dozens unit tests to fail, and to top it off, it takes three weeks to a pull request to get approved for the change.</p><p>&quot;I moved across the country for <em>this</em>?!&quot;. </p><h3 id="here-we-go-again">Here we go again</h3><p>Although I&apos;m sure <em>some people</em> will say it is, Suzi&apos;s dilemma isn&apos;t unique. Large Clojure codebases sometimes suffer from a lack proper care and abstraction. I suspect a lot of people rely too heavily on the pure function. Functions are great, but over time they create a codebase laden with high coupling and low cohesion. So, how do we help Suzi create a codebase satisfying our desired &quot;ilities&quot;? Lucky for Suzi, <strong>Clojure</strong> either <strong>directly supports</strong>, or easily supports <strong>design patterns</strong> like singleton, command, observer, visitor, and iterator. Before we get into those patterns though, we need to get little more abstract than the pure function.</p><h3 id="were-speaking-the-same-language">We&apos;re speaking the same language</h3><p>Let&apos;s start with the abstraction just above the function: <strong>Protocols</strong>. Protocols are Clojure&apos;s analogue to the interface. At a higher level, we can call a bag of function inputs and their outputs (or <em>function signatures) </em>an interface. Without diving into full-blown type theory, when something satisfies the interface, we can also say that something is a type of that interface. I&apos;ll even argue that we don&apos;t need a formal programming construct to achieve this &quot;typehood&quot;. On a basic level, by definition, every Clojure sequence supports the functions <code>cons</code> ,<code>first</code> ,<code>rest</code> , and &#xA0;<code>count</code>. Does that mean we should go out and create our own collection types? Not likely, the built-in types are quite good, but we do have few handy constructs for creating or extending types if we want. </p><figure class="kg-card kg-code-card"><pre><code class="language-clojure">(defprotocol MoneySafe
  &quot;A type to convert other money type to bigdec&quot;
  (make-safe [this] &quot;Coerce a type to be safe for money arithmetic&quot;))

(extend-protocol MoneySafe
  java.lang.Number
  (make-safe [this] (bigdec this))

  java.lang.String
  (make-safe [this]
    (try
      (-&gt; this
          (Double/parseDouble)
          (bigdec))
      (catch NumberFormatException nfe
        (println &quot;String must be string of number characters&quot;))
      (catch Exception e
        (println &quot;Unknown error converts from string to money&quot;)
        (throw e))))

  clojure.lang.PersistentVector
  (make-safe [this]
    (try
      (let [num-bytes (-&gt;&gt; this (filter int?) (count))]
        (if (= (count this) num-bytes)
          (-&gt;&gt; this
               (map char)
               (clojure.string/join)
               (Double/parseDouble)
               (bigdec))
          (throw (ex-info &quot;Can only convert from vector of bytes&quot;
                          {:input this}))))
      (catch NumberFormatException nfe
        (println &quot;Vector must be bytes representing ASCII number chars&quot;)
        (throw nfe))
      (catch Exception e
        (println &quot;Error converting from vector of bytes to money&quot;)
        (throw e)))))

(defn -&gt;money
  [x]
  (make-safe x))
  
;; (+ (-&gt;money &quot;0.1&quot;) (-&gt;money 0.1) (-&gt;money [0x30 0x2E 0x31])) =&gt; 0.3M</code></pre><figcaption>Dispatching on Protocols</figcaption></figure><p>While we could define types with functions like sequence, we would lose the biggest benefit of the protocol construct, Polymorphism.</p><hr><h2 id="null-object">Null Object</h2><blockquote>Create an empty implementation for an interface.</blockquote><p>By my &quot;interface is a bag of functions&quot; reasoning, <code>nil</code> makes a good Null Object for sequences, collections, and maps (or maybe<code>nil</code> <em>is</em> a sequence, collection, and map, but I&apos;ll leave that to the Philosophers of Computer Science ;).</p><!--kg-card-begin: markdown--><h5 id="when-to-use-it">When to use it</h5>
<p>When simulating the behaviour of a type without affecting the process.</p>
<h5 id="clojure-analogue">Clojure analogue</h5>
<p><code>nil</code> - Clojure sequence, collection, and map operations all support <code>nil</code> as their input sequence, collection, and map, respectively, either returning an empty sequence, collection, map, or <code>nil</code>.</p>
<h5 id="keep-in-mind">Keep in mind</h5>
<p>Not everything supports <code>nil</code>, and <code>nil</code> is different than Java&apos;s null pointer reference, yet some gotchas with <code>nil</code> can throw <code>NullPointerExecption</code>, so some defensive programming with <code>if</code> or <code>some-&gt;</code>/<code>some-&gt;&gt;</code> might be needed to avoid pitfalls.</p>
<h5 id="sample-code">Sample Code</h5>
<p>Repl output:</p>
<pre><code class="language-clojure">user&gt; (:keyword nil)
;; nil
user&gt; (get nil :hi)
;; nil
user&gt; (assoc nil :hi &quot;bye&quot;)
;; {:hi &quot;bye&quot;}
user&gt; (first nil)
;; nil
user&gt; (rest nil)
;; ()
user&gt; (next nil)
;; nil
user&gt; (count nil)
;; 0
user&gt; (nth nil 10)
;; nil
user&gt; (pop nil)
;; nil
user&gt; (peek nil)
;; nil
user&gt; (println &quot;You get the idea.&quot;)
You get the idea.
;; nil
</code></pre>
<!--kg-card-end: markdown--><hr><h2 id="singleton">Singleton</h2><blockquote>Ensure a class has one instance, and provide a global point of access to it.</blockquote><p>A less philosophical pattern, the singleton appears a lot in Clojure codebases. Thanks to software transactional memory, we don&apos;t have to worry about non-atomic operations, but it&apos;s still an anti-pattern because one piece of client code may update the atom with something another piece of client code doesn&apos;t expect, causing a hard-to-debug error. </p><!--kg-card-begin: markdown--><h5 id="when-to-use-it">When to use it</h5>
<p>Just don&apos;t.</p>
<h5 id="clojure-analogue">Clojure analogue</h5>
<p><code>defonce</code> macro and an atom/agent</p>
<h5 id="keep-in-mind">Keep in mind</h5>
<p>Global state is best to be avoided unless absolutely necessary. Global configuration, database connection, and web servers are arguably important enough objects to use this, since they&apos;re the stateful sole instance and must stick around for the process runtime, but most Clojurians go in for a state management library or framework like Component, Mount, or Integrant.</p>
<h5 id="sample-code">Sample Code</h5>
<pre><code>(defonce web-server (atom nil))

(defn start-server
  []
  (if @web-server
    (log/warn &quot;Server is already running!&quot;)
    (reset! webserver (run-jetty routes {:port (parse-int (:port config))
                                         :join? false}))))

</code></pre>
<!--kg-card-end: markdown--><hr><h2 id="command">Command</h2><blockquote>Encapsulate a request as an object, thereby letting users parameterize clients with different requests, queue or log requests, and support undoable operations.</blockquote><p>The errors from functions are a lot easier to debug though because of stack traces. Our command pattern, the object-oriented version of callbacks, can be implemented in Clojure via higher-order functions (obviously).</p><!--kg-card-begin: markdown--><h5 id="when-to-use-it">When to use it</h5>
<p>When you need to decouple the execution of a block of code from when it needs to be called.</p>
<h5 id="clojure-analogue">Clojure analogue</h5>
<p>Higher-order functions. All functions in Clojure can be passed around as arguments, and support closures.</p>
<h5 id="keep-in-mind">Keep in mind</h5>
<p>If you&apos;re passing around lambdas a lot, use the <code>fn</code> form and give it a name to help with debugging. The road to callback hell is paved with <code>#(...)</code> lambdas.</p>
<p>State with Callbacks are typically considered an anti-pattern, but JavaScript promises are a thing, so pick your poison.</p>
<h5 id="sample-code">Sample Code</h5>
<pre><code class="language-clojure">;; Trivial example
(defn fire
  &quot;fire!!!&quot;
  []
  (println &quot;Fire the gun&quot;))

(defn jump
  &quot;jump!!!&quot;
  []
  (println &quot;Jump&quot;))

(defn run
  &quot;run!#!#&quot;
  []
  (println &quot;Run enabled&quot;))

(defn diagonal-aim
  &quot;Shoot things on the walls&quot;
  []
  (println &quot;Aiming diagionally&quot;))

(defn remap-button
  &quot;Remap a player&apos;s button to a function.
  Can be used on the remap menu screen, or
  for temporary game mechanics.&quot;
  [player button f]
  (swap! player assoc-in [:controls button] f))

;; (remap-button player :a-button fire)

(defn do-buttons!
  &quot;Execute the button actions assigned to the
  players controller map.&quot;
  [button-pressed controllor-map]
  (let [{:keys [a-button
                b-button
                y-button
                x-button]} controller-map]
    (case button-pressed
      &quot;A&quot; (a-button) ;; &quot;Execute&quot; the command!
      &quot;B&quot; (b-button)
      &quot;X&quot; (x-button)
      &quot;Y&quot; (y-button))))

</code></pre>
<h6 id="doing-redoing-and-undoing">Doing, redoing, and undoing</h6>
<p>Because I know people will say it, here is an example of the command pattern supporting undo with all the previously made edits. Supporting redo will be left as an exercise for the reader.</p>
<pre><code class="language-clojure">(defn do-undo
  &quot;Create a command and undo over a pure function&quot;
  [f]
  (let [state (atom nil)]
    {:exec (fn execute!
             [&amp; args]
             (let [v (apply f args)]
               (swap! state conj v)
               v))
     :undo (fn undo!
             []
             (swap! state pop)
             (peek @state))}))

(defn change-cell
  &quot;A supposedly pure function&quot;
  [s coord]
  (assoc sheet coord s))

(let [{:keys [exec undo]} (do-undo change-cell)]
  (def change-cell-cmd exec)
  (def change-cell-undo undo))
</code></pre>
<!--kg-card-end: markdown--><hr><h2 id="observer">Observer</h2><blockquote>Define a one-to-many dependency between objects so that when one object changes state, all the dependents are notified and updated automatically.</blockquote><p>I see a lot of functions written to watch for something to happen. Typically, developers will use a <code>loop</code> over a function until some state changes or &quot;event&quot; transpires. This works, but couples the event to the event reaction. Object-oriented programming addresses this with the Observer pattern, but we can address it with a Clojure watch.</p><!--kg-card-begin: markdown--><h6 id="when-to-use-it">When to use it</h6>
<p>When you want to decouple changes in state from what the state affects, also known as a publish/subscribe pattern.</p>
<h6 id="clojure-analogue">Clojure analogue</h6>
<p>There are two ways to do this in Clojure:</p>
<ul>
<li>Clojure watches. You can add a watch to any atom, agent, var, or ref with <code>add-watch</code> and remove it with <code>remove-watch</code>.</li>
<li>core.async&apos;s <code>pub</code> and <code>sub</code>. <code>pub</code> creates a channel from a existing channel with optional topic, and then other channels can <code>sub</code> to the pub channel.</li>
</ul>
<h6 id="keep-in-mind">Keep in mind</h6>
<p>When the watch target (the var/atom/agent/ref) changes, all the watch functions will be called syncronously even if multiple threads are manipulating the watch target. So, it&apos;s best to use the <code>new-state</code> argument in all your watch functions.</p>
<h6 id="sample-code">Sample Code</h6>
<pre><code class="language-clojure">(defn unlock
  &quot;Unlocks the achiement given&quot;
  [player k]
  (when-not (unlocked? player k)
      (do-unlock! player k)))

(defn on-bridge?
  &quot;predicate to see if player is on the bridge&quot;
  [player]
  (is-colliding? (get @entities :bridge) @player))

(defn achievement-toaster
  [k]
  (let [a (get achievements :player-fell-achievement)]
      (when a
        (swap! entities :current-toaster a))))

(defn unlock-achievement
  [key player old-state new-state]
  (case (:last-event new-state)
    :player-fell (when (on-bridge? new-state)
                   (unlock player :player-fell-achievement)
                   (achievement-toaster :player-fell-achievement))))

(defn watch-actions
  [player]
  (add-watch player :achievements unlock-achievement))
</code></pre>
<!--kg-card-end: markdown--><hr><h2 id="state">State</h2><blockquote>Allow an object to alter its behavior when its internal state changes. The object will appear to change it&apos;s class.</blockquote><p>We might not care about reacting to the state change though. Heck, we might not even care how the state happens, we just care about the results. A state pattern can give use a nice function to conceal our messy state transitions, so we don&apos;t have to write giant <code>cond</code> statements.</p><!--kg-card-begin: markdown--><h6 id="when-to-use-it">When to use it</h6>
<p>The real thing to remember here is that we want to model a finite state machine (FSM) with our functions.</p>
<h6 id="clojure-analogue">Clojure analogue</h6>
<ul>
<li><code>(atom f)</code> - An atom over a function is the simplist version of the state pattern.</li>
<li><code>(loop [state (init-state data)] (recur (state data)))</code> - Alternatively, the the current state could be re-bound a loop binding since the current state function always returns the next state.</li>
</ul>
<p><a href="http://mishadoff.com/blog/clojure-design-patterns/?ref=blog.janetacarr.com#episode-3-state">This take</a> uses a multimethod over an atom. This certainly models an FSM, but we kind of lose our ability to decouple the state from the context.</p>
<h6 id="keep-in-mind">Keep in mind</h6>
<ul>
<li>
<p>The current state will always return the next state in the machine. Modeling state this way can be tricky, but can be super helpful if you find yourself with many nested <code>case</code> or <code>cond</code> forms. You&apos;ll have to decide of the cyclomatic complexity is worth the trade-off.</p>
</li>
<li>
<p>When your state transition returns one state, this method is fine. If you need more functions in a single &apos;state&apos;, I&apos;d consider using protocols to create states. I intentionally left this out of the sample code because it was huge.</p>
</li>
<li>
<p>If you need a history for your state machine, like a push-down automata, you can <code>conj</code> each state function to a vector and <code>peek</code> at the top.</p>
</li>
<li>
<p>The atom-free state pattern with loop bindings can be problematic if the current state needs to modify the binding itself. Use the atom version instead.</p>
</li>
</ul>
<h6 id="sample-code">Sample Code</h6>
<pre><code class="language-clojure">(defn play-game
  [game]
  (let [{:keys [components player]} game]
    (do
      (doseq [component components]
        (update! component))
      (draw-game game)
      (if (= :paused (:action @player))
        pause-menu
        play-menu))))

(defn start-menu
  [game]
  (let [{:keys [menu player]} game]
    (do
      (draw-game game)
      (if (= :affirm (:action @player))
        (when-let [menu-item (collision player)]
          (cond ;; our state transition
            (= menu-item :start-game) play-game
            (= menu-item :options) options-menu
            (= menu-item :quit-game) quit-game
            :else start-menu))))))

(let [game-state (atom start-menu)]
  (defn start-game
    [game]
    (reset! game-state (@game-state game))))
    
(defn main
  []
  (let [game-engine (game-engine)]
    (loop [quit? (:quit game-engine)]
      (when-not quit?
        (start-game game-engine)
        (recur (:quit game-engine))))))
                   
;; or stateless &apos;state&apos;
(defn stateless-start-game
  [game]
  (start-menu game))

(defn stateless-main
  []
  (let [game-engine (game-engine)]
    (loop [game-state (start-game game-engine)]
      (when-not (:quit game-engine)
        (recur (game-state game-engine))))))
</code></pre>
<!--kg-card-end: markdown--><hr><h2 id="visitor">Visitor</h2><blockquote>Represent an operation to be performed on elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.</blockquote><p>Giant <code>case</code> statements are sometimes addressed with multimethods. That&apos;s a valid strategy, but multimethods give us multiple dispatch for free.</p><!--kg-card-begin: markdown--><h6 id="when-to-use-it">When to use it</h6>
<p>When you want to create new functionality without changing the existing code structure.</p>
<h5 id="clojure-analogue">Clojure analogue</h5>
<p>multimethods. Clojure&apos;s multimethods offer dynamic dispatch functionality right out of the box, so we can put a multimethod inside of a multimethod to get the double dispatch functionality.</p>
<h6 id="keep-in-mind">Keep in mind</h6>
<p>Multimethods have a performance penalty. You&apos;re unlikely to experience it, but it is there, so just be mindful of it in performance sensitive applications. If you need fast dispatching, consider dispatch on protocols instead.</p>
<h6 id="sample-code">Sample Code</h6>
<pre><code class="language-clojure">(defrecord Equipment [elements])
(defrecord Sword [name])
(defrecord QuestItem [name])
(defrecord Armor [name])

(defmulti visit (fn [f x y] [(class x) (class y)]))

(defmethod visit :default [f x y])

(defmethod visit [Equipment Object] [f equipment other]
  (let [{:keys [elements]} equipment]
    (doseq [element elements]
      (f element other))))

(defmulti do-stuff (fn [x y] [(class x) (class y)]))

(defmethod do-stuff :default [x y]
  (println (format &quot;You sit there bewildered, unable to understand what to do with %s and %s&quot; x y)))

(defmethod do-stuff [Sword Long] [x y]
  (println (format &quot;Swing your sword %s does %d damage&quot; (:name x) y)))

(defmethod do-stuff [Sword String] [x y]
  (println (format &quot;Using your sword %s, you make a noble gesture %s&quot; (:name x) y)))

(defmethod do-stuff [Armor Long] [x y]
  (println (format &quot;Your armor %s has prevented %d damage&quot; (:name x) y)))

(defmethod do-stuff [Armor String] [x y]
  (println (format &quot;You remove armor %s as a noble gesture %s&quot; (:name x) y)))

(defmulti store-stuff (fn [x _] (class x)))

(defmethod store-stuff :default [x y]
  (println &quot;You stored: &quot; x))
</code></pre>
<p>Repl output:</p>
<pre><code class="language-clojure">user&gt; (def equipment (-&gt;Equipment [(-&gt;Sword &quot;Excalibur&quot;) (-&gt;Sword &quot;Gramr&quot;) (-&gt;Sword &quot;Zulfiqar&quot;) (-&gt;Sword &quot;Durendal&quot;) (-&gt;QuestItem &quot;dungeon key&quot;) (-&gt;Armor &quot;Achilles&quot;)]))
;; #user/equipment
user&gt; (visit store-stuff equipment 10)
You stored:  #user.Sword{:name Excalibur}
You stored:  #user.Sword{:name Gramr}
You stored:  #user.Sword{:name Zulfiqar}
You stored:  #user.Sword{:name Durendal}
You stored:  #user.QuestItem{:name dungeon key}
You stored:  #user.Armor{:name Achilles}
;; nil
user&gt; (visit store-stuff equipment nil)
;; nil
user&gt; (visit do-stuff equipment 50)
Swing your sword Excalibur does 50 damage
Swing your sword Gramr does 50 damage
Swing your sword Zulfiqar does 50 damage
Swing your sword Durendal does 50 damage
You sit there bewildered, unable to understand what to do with user.QuestItem@bb0c2cb0 and 50
Your armor Achilles has prevented 50 damage
;; nil
</code></pre>
<!--kg-card-end: markdown--><hr><h2 id="iterator">Iterator</h2><blockquote>Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.</blockquote><p>Like our Visitor pattern, the Iterator doesn&apos;t really reveal anything special. We can use it without any extra effort which makes this section fluff. Enjoy!</p><!--kg-card-begin: markdown--><h6 id="when-to-use-it">When to use it</h6>
<p>When you want to have an ordered, sequential container for other objects which sounds an awful lot like a sequence or collection.</p>
<h6 id="clojure-analogue">Clojure analogue</h6>
<p>Lists and Vectors - Clojure list and vector types are sequence and collection, respectively, and support arbitrary typed elements. They have a rich set of functions for operating on them like <code>doseq</code> <code>for</code> <code>map</code> <code>filter</code> etc.</p>
<h6 id="keep-in-mind">Keep in mind</h6>
<p>Make sure you use <code>doseq</code> for side-effects. Some sequences (and transforms from collections) are Chunked, and can create strange behavior if using side-effects with <code>map</code> or <code>filter</code>.</p>
<p>A Java Iterator (supporting the java.util.Iterator interface) is not a sequence in Clojure. If you are working with a Java Iterators, be sure to call the <code>iterator-seq</code> function on your Java Iterator to get a (chunked) sequence. Some Java types do return <em>collections</em> though, and those should be fine in <code>map</code> or <code>filter</code> since Clojure collections inherit from the Java collections.</p>
<h6 id="sample-code">Sample code</h6>
<pre><code class="language-clojure">(-&gt;&gt; (range 1000) ;; Range gives us a list of numbers
     (filter even?) ;; Plugs into 
     (map inc))
</code></pre>
<!--kg-card-end: markdown--><hr><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-text"><em>I&apos;ve want to write this series for posts for years, but never got around to it, so thanks for reading. I think you&apos;ll enjoy the stuff I plan to write in the future, my next post will be Part 2 of this series. Subscribe for the next post or follow me on twitter </em><a href="https://twitter.com/janetacarr?ref=blog.janetacarr.com"><em>@janetacarr</em></a><em> , or don&apos;t </em>&#xAF;\_(&#x30C4;)_/&#xAF; <em>. You can also join the discussion about this post on twitter, hackernews, or reddit if you think I&apos;m wrong.</em></div></div><!--kg-card-begin: html--><p>
    <a name="gpp">1.</a> Because it&apos;s my favorite book on this subject, the inspiration for this post by and large came from <a href="http://gameprogrammingpatterns.com/?ref=blog.janetacarr.com">Game Programming Patterns (print)</a>. The sample code for Command and Observer, as well as each pattern&apos;s section structure, was adapted for this post&apos;s theme.
    <br>
    <a name="mishadoff">2.</a> This post is also largely a rebuttle to <a href="http://mishadoff.com/blog/clojure-design-patterns?ref=blog.janetacarr.com">mishadoff&apos;s Clojure design patterns.</a>
    <br>
    
    <a name="gof">3.</a> Except for the Null Object, all quotes underneath pattern names come directly from Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison Wesley. ISBN 0-201-63361-2.
    <br>
</p><!--kg-card-end: html-->]]></content:encoded></item><item><title><![CDATA[Clojure needs a Rails, but not for the reason you think]]></title><description><![CDATA[I think there's another reason this problem persists in Clojure. There's no Rails for Clojure. ]]></description><link>https://blog.janetacarr.com/clojure-needs-a-rails/</link><guid isPermaLink="false">62e545746d3425003dae0962</guid><category><![CDATA[clojure]]></category><category><![CDATA[computer programming]]></category><category><![CDATA[software development]]></category><category><![CDATA[software engineering]]></category><category><![CDATA[functional programming]]></category><dc:creator><![CDATA[Janet A. Carr]]></dc:creator><pubDate>Sat, 30 Jul 2022 16:56:29 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1523427373578-fa4bbfc4389a?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDV8fHJhaWxzfGVufDB8fHx8MTY1OTE5OTk5OQ&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<h3 id="first-a-quick-story">First, a quick story</h3><img src="https://images.unsplash.com/photo-1523427373578-fa4bbfc4389a?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDV8fHJhaWxzfGVufDB8fHx8MTY1OTE5OTk5OQ&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Clojure needs a Rails, but not for the reason you think"><p>Suzi, a software engineer of suitable caliber, loves writing Clojure. At her polyglot employer, she often uses her technical freedom to bat for Clojure every chance she gets. One day her manager taps her for an opportunity, the company wants to build a scrappy, lean internal tooling team to build tools for sales, marketing, and so on. &#xA0;Perfect. </p><p>One the first day of the tooling team, the marketing team wants to move the website to something custom and use Stripe for payments from the lower segment customers. No problem. Clojure&apos;s web stack is very mature and will be sinch to whip-up this project for marketing. The website was easy enough to tackle, a little ring here, a little hiccup there, and presto! She has her website after just a couple of weeks of coding. </p><p>Next on her docket was the Stripe payment integration. Should be the same thing as the website. Suzi sees there are a number of Stripe Clojure libraries to choose from. </p><p>&quot;Perfect&quot; Suzi thinks to herself as she were in developer heaven. </p><p>Upon her first test with the repl, she gets an exception. She inspects her Stripe library by looking at the master branch on Github: <strong>Last commit 7 years ago. </strong>F**k. It&apos;s just some simple requests with clj-http and cheshire. Next library. <strong>Last commit 3 years ago. </strong></p><p><strong>&quot;</strong>Okay, looking better&quot; Suzi thinks to herself as she lets out a sigh of relief. </p><p>This library is almost the same thing as the last one, simple and only covering a fraction the API. Unsure if this new library actually keeps with the current API contract, no support for lazy pagination like the Java SDK, and it suffers from the Log4j vulnerability. <em>Fantastic, so much for that estimate. </em>The next day during stand up, Suzi explains to her colleagues that the project is going to take a bit longer because she didn&apos;t anticipate having to update libraries and implement features the Java crowd gets for free. </p><p>Fast forward a couple months. After the marketing website hurdles, a new project from IT is requested. They want a syslog relay for SOC2 monitoring stuff. That doesn&apos;t really sound like SOC2 compliance to Suzi, but she has her Clojure hammer and a good salary, so she gets to work. Once she finishes the requirements, she begins researching to give an estimate of how long the project will take, only to find there is no syslog server library for Clojure that she can find. She will have to write one herself. During stand up the next day, Suzi delivers the estimate to her team with her line manager, Sam, present. </p><p>&quot;It&apos;ll probably take two months to build this relay because there&apos;s no syslog server library for Clojure.&quot; she says.</p><p>&quot;Oh wow, I didn&apos;t think it would take <em>that long</em>.&quot; Sam says.</p><p>Dillion, a colleague in the standup, says &quot;Go has great syslog server library and even supports Rsyslog! Maybe you could use that&quot;. </p><p>&quot;That&apos;s probably a good idea, Suzi can estimate how long it&apos;ll take using Go?&quot; Sam replies.</p><p>Later that day, Suzi estimates the project with Go instead. The business case for Go is very strong now. Sh*t.</p><h3 id="strange-yet-familiar">Strange yet familiar </h3><p>If Suzi&apos;s story resonated with you, you&apos;re like me and dozens of other Clojure developers. Clojure suffers from missing or rotting software libraries<em> a lot</em>. Developers love writing code, but it&apos;s really hard to sell management on building an entire library when another language has so many batteries built in.</p><p>In a perfect world of open-source software, companies would give back to the community by building libraries they need and licensing them in the wild. While some software companies do this, in my experience, it&apos;s usually the opposite that happens, most companies don&apos;t give back, but I think there&apos;s another reason this problem persists in Clojure. <strong>There&apos;s no Rails for Clojure. </strong></p><h3 id="railing-against-rails">Railing against Rails</h3><p>Because there is no Rails for Clojure, a lot of open-source software efforts in the Clojure community go towards developing web frameworks, libraries, toolkits, and so on, trying to fill this &quot;Rails for Clojure&quot; vacuum. Yet, the web stack for Clojure is very mature. </p><figure class="kg-card kg-code-card"><pre><code class="language-text">- Ring (server)
- Compojure (router)
- Edge (framework)
- Bidi (router)
- Yada (library, bidi + aleph)
- Aleph (server)
- Reitit (router)
- Luminus (many libraries)
- Kit (framework)
- Pedestal (many libraries)
- Selmer (templates)
- Hiccup (HTML DSL)</code></pre><figcaption>Non-exhaustive list of Clojure web stuff in no particular order</figcaption></figure><p>Every time I see Clojure on the front page of Hacker News, it&apos;s a post talking about a new <strong>web</strong> framework, library, toolkit, or abstraction for Clojure, and (usually) the maintainer has abandoned the project since revealing it to the world. My theory is, this causes a lack of effort expended on mundane libraries. It&apos;s not the most fun thing to build. I get it. Really, I do, but lack of these API-wrapping and protocol-handling libraries put Clojure at a significant disadvantage in the business of software.</p><h3 id="interop-for-the-mundane">Interop for the mundane</h3><p><em>Why not just use Java and Javascript interop for the mundane, everyday libraries, is there something wrong with that?</em> </p><p>It&apos;s possible, but interop comes with caveats.</p><ul><li>Interop can be frustrating with big frameworks. </li><li>Interop relies heavily on reflection, and may require type hinting once it becomes a performance problem. </li><li>Interop implies the use of side-effects since we&apos;re relying on Java objects. </li><li>Java sequences and Collections may require a <code>clojure.walk/postwalk</code> and <code>zipmap</code> with coercion to get a good Clojure container/sequence/collection.</li><li>No variodic arguments to <code>deftype</code> or <code>defprotocol</code> for technical reasons, meaning overloading isn&apos;t happening when extending Java types.</li></ul><p>If we used interop for everything mundane, Clojure would really just be an S-expression shaped husk over Java code. Not a very good solution. </p><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">A lot of the mundane Clojure libraries do actually wrap a Java SDK, giving us a clean, functional interface to work with. I think this is fine, but tough to keep up with if the right abstractions aren&apos;t used. Amazonica, a Clojure library for AWS, does this quite well by using macros to intern new Clojure functions that wrap Java methods, transforming types between Clojure and Java land. It takes a single function call to turn a new AWS package into a set of usable libraries.</div></div><h3 id="rallying-on-the-tracks">Rallying on the tracks</h3><p>Other programming languages have their definitive web framework. Ruby has Rails, Python has Django, Java has Play, Elixir has Pheonix. I know there are other web framework, libraries, toolkit, and so on for each of these programming languages, but their communities always seems to rally around each of these projects. Even a language as niche as Elixir, has it&apos;s own &quot;Rails&quot; (so to speak). &#xA0;</p><p>Why doesn&apos;t Clojure do this? From my observation, the Clojure community seems a bit more de-centralized and laid back. It&apos;s awesome, but can we please just get together at the next <a href="http://2019.clojure-conj.org/?ref=blog.janetacarr.com">Conj</a> conference decide what our &quot;Rails&quot; is going to be? That way we can get down to business. </p><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-text"><em>As always, You can also join the discussion about this post on twitter, Hacker News, or reddit if you think I&apos;m wrong. If you like what I have to say, subscribe for the next post, follow me on twitter <a href="https://twitter.com/janetacarr?ref=blog.janetacarr.com">@janetacarr</a> , or don&apos;t </em>&#xAF;\_(&#x30C4;)_/&#xAF; <em>.</em></div></div>]]></content:encoded></item></channel></rss>