<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Thomas Cothran, Software Developer</title>
    <link>https://thomascothran.tech/</link>
    <description>Recent content on Thomas Cothran, Software Developer</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <copyright>2023, Thomas Cothran</copyright>
    <lastBuildDate>Mon, 07 Apr 2025 00:00:00 +0000</lastBuildDate>
    
        <atom:link href="https://thomascothran.tech/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Avoid with-redefs in tests</title>
      <link>https://thomascothran.tech/2025/04/avoid-with-redefs/</link>
      <pubDate>Mon, 07 Apr 2025 00:00:00 +0000</pubDate>
      
      <guid>https://thomascothran.tech/2025/04/avoid-with-redefs/</guid>
      <description>&lt;p&gt;Advice to avoid &lt;code&gt;with-redefs&lt;/code&gt; often focuses on the wrong things. It is true that &lt;code&gt;with-redefs&lt;/code&gt; can cause &lt;a href=&#34;https://cognitect.com/blog/2016/9/15/works-on-my-machine-understanding-var-bindings-and-roots&#34;&gt;race conditions&lt;/a&gt; in your test suite. And that functions can be captured in closures, leading to them &lt;a href=&#34;https://stackoverflow.com/questions/48371596/with-redefs-not-binding-certain-functions-clojure&#34;&gt;not being redefined&lt;/a&gt; as one might expect. And that &lt;code&gt;with-redefs&lt;/code&gt; doesn&amp;rsquo;t &lt;a href=&#34;https://stackoverflow.com/questions/23166716/clojure-with-redefs-doesnt-work-with-clojure-core-functions&#34;&gt;redefine inlined functions&lt;/a&gt;. And that &lt;code&gt;with-redefs&lt;/code&gt; can cause problems with type-hinted functions. And that they cause problems when used with &lt;a href=&#34;https://ask.clojure.org/index.php/4614/with-redefs-used-on-macro-permanently-changes-it-to-function&#34;&gt;macros&lt;/a&gt;. And that mutating the global environment is something functional programmers should know is a bad practice. Etc., etc.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>What do I want from a codebase?</title>
      <link>https://thomascothran.tech/2024/11/what-do-i-want-from-a-codebase/</link>
      <pubDate>Wed, 27 Nov 2024 00:00:00 +0000</pubDate>
      
      <guid>https://thomascothran.tech/2024/11/what-do-i-want-from-a-codebase/</guid>
      <description>&lt;p&gt;Carson Gross&amp;rsquo; &lt;a href=&#34;https://htmx.org/essays/codin-dirty/&#34;&gt;&amp;ldquo;Codin&amp;rsquo; Dirty&amp;rdquo;&lt;/a&gt; essay is designed to provoke controversy. Although I will critique the essay, I want to make it clear that I am (on this Thanksgiving eve) grateful for Carson Gross&amp;rsquo;s work.&lt;/p&gt;
&lt;p&gt;Gross writes:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I’m &amp;hellip; not trying to convince you to code dirty with this essay. Rather, I want to show that it is possible to write reasonably successful software this way and, I hope, offer some balance around software methodology discussions.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Bthreads: A Simple and Easy Paradigm for Clojure</title>
      <link>https://thomascothran.tech/2024/10/a-new-paradigm/</link>
      <pubDate>Wed, 30 Oct 2024 00:00:00 +0000</pubDate>
      
      <guid>https://thomascothran.tech/2024/10/a-new-paradigm/</guid>
      <description>&lt;p&gt;Asynchronous programs are hard to reason about. But is this intrinsic to asynchrony? Or might we be using the wrong paradigms?&lt;/p&gt;
&lt;p&gt;Behavioral programming is a programming paradigm that aims to make asynchronous, event-driven systems both simple &lt;em&gt;and&lt;/em&gt; easy by using a system centered on behavioral threads (bthreads). In my &lt;a href=&#34;https://thomascothran.tech/2024/09/in-clojure/&#34;&gt;previous article&lt;/a&gt;, I introduced the idea of behavioral programming in Clojure.&lt;/p&gt;
&lt;p&gt;In this article, we dive deeper. I hope to convince you that, compared to the alternatives:&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Behavioral Programming in Clojure</title>
      <link>https://thomascothran.tech/2024/09/in-clojure/</link>
      <pubDate>Tue, 24 Sep 2024 00:00:00 +0000</pubDate>
      
      <guid>https://thomascothran.tech/2024/09/in-clojure/</guid>
      <description>&lt;p&gt;Behavioral Programming is a relatively new programming paradigm that excels at isolating and composing behaviors in event driven system. It is unrelated to behavior driven development.&lt;/p&gt;
&lt;p&gt;Behavioral programming was invented by David Harel, who also &lt;a href=&#34;https://www.sciencedirect.com/science/article/pii/0167642387900359&#34;&gt;invented statecharts in 1987&lt;/a&gt;. It uses independent units of behavior, called bthreads, which are coordinated in a pub-sub protocol.&lt;/p&gt;
&lt;h2 id=&#34;how-does-it-work&#34;&gt;How does it work?&lt;/h2&gt;
&lt;p&gt;A behavioral program will first collect the bids from all of its bthreads. A bid can do three things:&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>The Ocelot Game</title>
      <link>https://thomascothran.tech/2024/09/the-ocelot-game/</link>
      <pubDate>Wed, 11 Sep 2024 00:00:00 +0000</pubDate>
      
      <guid>https://thomascothran.tech/2024/09/the-ocelot-game/</guid>
      <description>&lt;p&gt;The ocelot game works like this: a developer has written a feature, and presents it to an ocelot.&lt;/p&gt;
&lt;p&gt;Not a real ocelot. Ocelots are playful. But they&amp;rsquo;re wild animals. Their claws easily poke holes in things. We want to poke holes in code.&lt;/p&gt;
&lt;p&gt;The ocelot is a role played by a developer who tries to poke holes in another developer&amp;rsquo;s code. Specifically, they try to change the code in such a way that the feature breaks while still passing the unit tests.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Top-Down Imperative Clojure Architectures</title>
      <link>https://thomascothran.tech/2024/07/top-down-imperative-clojure-architectures/</link>
      <pubDate>Mon, 22 Jul 2024 00:00:00 +0000</pubDate>
      
      <guid>https://thomascothran.tech/2024/07/top-down-imperative-clojure-architectures/</guid>
      <description>&lt;p&gt;When I first became interested in functional programming, a more experienced engineer told me: &amp;ldquo;you know functional programming doesn&amp;rsquo;t really amount to much more than procedural programming.&amp;rdquo; As I insisted on the benefits of &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt; and &lt;code&gt;reduce&lt;/code&gt;, he simply shook his head. &amp;ldquo;You&amp;rsquo;re thinking in the small. Go look at a large real-world application.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;It took some time for me to see what he meant. My preferred language, Clojure, is a functional language. But too often it is used to build top-down, imperative applications. This negates the value proposition of functional programming: isolating side effects, local reasoning, and system composition.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>MPAs vs SPAs: The False Dichotomy</title>
      <link>https://thomascothran.tech/2024/01/the-false-dichotomy-mpas-spas/</link>
      <pubDate>Sun, 28 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://thomascothran.tech/2024/01/the-false-dichotomy-mpas-spas/</guid>
      <description>&lt;p&gt;&lt;em&gt;This is the second post in the series &amp;ldquo;Have Clojure UIs Taken the Wrong Path?&amp;rdquo;. The first post is &lt;a href=&#34;https://thomascothran.tech/2023/11/clojure-uis-hypermedia-and-rpc-1/&#34;&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;How do we choose between building an application using a hypermedia approach versus the client-side SPA? This post won&amp;rsquo;t answer that question. But it will say how &lt;em&gt;not&lt;/em&gt; to make that choice.&lt;/p&gt;
&lt;p&gt;A common heuristic is the spectrum that stretches between old fashioned &amp;ldquo;Multi Page Apps&amp;rdquo; (MPAs) for basic use cases, to Single Page Applications for rich client interactivity.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Have Clojure UIs Taken the Wrong Path? Part 1</title>
      <link>https://thomascothran.tech/2023/11/clojure-uis-hypermedia-and-rpc-1/</link>
      <pubDate>Fri, 24 Nov 2023 00:00:00 +0000</pubDate>
      
      <guid>https://thomascothran.tech/2023/11/clojure-uis-hypermedia-and-rpc-1/</guid>
      <description>&lt;p&gt;The Clojure community has focused on React-based solutions for complex front-end clients such as Reagent, Rum, Om, Re-frame, and Fulcro.&lt;/p&gt;
&lt;p&gt;For all their differences, they follow a very similar architecture, making heavy use of client-side state and using RPC for client-server communication. We will call this the “React+” approach.&lt;/p&gt;
&lt;p&gt;But is this the right choice?&lt;/p&gt;
&lt;p&gt;I will suggest the answer may be negative. My suspicion is that as web UI libraries advance, the problems they solve are not essential. Rather, the problems are accidental; they are generated by the React+ architecture.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>The Wrong Kind of Readability</title>
      <link>https://thomascothran.tech/2023/11/readability/</link>
      <pubDate>Sun, 05 Nov 2023 00:00:00 +0000</pubDate>
      
      <guid>https://thomascothran.tech/2023/11/readability/</guid>
      <description>&lt;p&gt;In the Pragmatic Programmer, Andy Hunt and Dave Thomas tell us: “it’s critical that you write code that is readable and easy to reason about.” This seems uncontroversial; it is the rare point on which software engineers typically agree. Or do they?&lt;/p&gt;
&lt;p&gt;In fact, developers disagree about what “readability” means. &amp;ldquo;Readability&amp;rdquo; can be given two contrary meanings that we will call imperative readability (or readability-i) and declarative-readability (or readability-d).&lt;/p&gt;
&lt;h2 id=&#34;imperative-readability&#34;&gt;Imperative Readability&lt;/h2&gt;
&lt;p&gt;This form of readability focuses on how the code operates. It emphasizes a clear presentation of the implementation details, such as which libraries are used, how data sources are accessed, and how functions perform their tasks.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>The Library Locker - An Antipattern</title>
      <link>https://thomascothran.tech/2023/08/library-locker/</link>
      <pubDate>Sun, 20 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://thomascothran.tech/2023/08/library-locker/</guid>
      <description>&lt;p&gt;The &amp;ldquo;Library Locker&amp;rdquo; is a common anti-pattern for incorporating third party libraries into an application. The application wraps the library with its own function, which mixes concerns and makes the library more difficult to use.&lt;/p&gt;
&lt;p&gt;In this article, we will first consider the original problem the library locker is introduced to solve, then an example of the library locker, and then suggest better alternatives.&lt;/p&gt;
&lt;h2 id=&#34;the-problem&#34;&gt;The Problem&lt;/h2&gt;
&lt;p&gt;Suppose we have system of microservices that support astronomical applications. We locate our calls to our other microservices in a &lt;code&gt;service&lt;/code&gt; directory.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Brittle Clojure: Creating Legacy Clojure Systems</title>
      <link>https://thomascothran.tech/2023/07/brittle-clojure/</link>
      <pubDate>Sun, 23 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://thomascothran.tech/2023/07/brittle-clojure/</guid>
      <description>&lt;p&gt;This is the first in a multi-part series, &amp;ldquo;Brittle Clojure&amp;rdquo;. In this series, we will consider common patterns in Clojure which yield brittle systems, as well as methods to ensure robustness.&lt;/p&gt;
&lt;p&gt;None of the basic principles for building robust software are unique. Most literature, however, is focused on object-oriented systems. Our point of view will sometimes zoom in to Clojure &amp;ldquo;in the small&amp;rdquo;, and sometimes zoom out to distributed systems built with Clojure.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Distributed Merges and Continuous Integration</title>
      <link>https://thomascothran.tech/2023/07/distributed-merges/</link>
      <pubDate>Fri, 14 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://thomascothran.tech/2023/07/distributed-merges/</guid>
      <description>&lt;p&gt;Among DORA&amp;rsquo;s more controversial findings is that &lt;a href=&#34;https://dora.dev/devops-capabilities/technical/trunk-based-development/&#34;&gt;trunk based development&lt;/a&gt; is superior to feature branching.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Teams achieve higher levels of software delivery and operational performance (delivery speed, stability, and availability) if they follow these practices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Have three or fewer active branches in the application’s code repository.&lt;/li&gt;
&lt;li&gt;Merge branches to trunk at least once a day.&lt;/li&gt;
&lt;li&gt;Don’t have code freezes and don’t have integration phases.&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;
&lt;p&gt;Since we know &lt;a href=&#34;https://thomascothran.tech/2023/07/dont-be-cremonini/&#34;&gt;not to be Cremoninis&lt;/a&gt;, we won&amp;rsquo;t be distracted by whether trunk-based development meets the HN trendiness standard, and we&amp;rsquo;ll be skeptical of anectdotal appeals to experience&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Don&#39;t Be a Cremonini</title>
      <link>https://thomascothran.tech/2023/07/dont-be-cremonini/</link>
      <pubDate>Sun, 09 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://thomascothran.tech/2023/07/dont-be-cremonini/</guid>
      <description>&lt;p&gt;Differences of opinion about how we ought to write software have an air of the philosophical about them. Some prefer TDD and microservices, others may prefer monoliths and think that most testing is a waste of time. Or engineers may prefer to use continuous development methodologies, while businesses prefer a waterfall approach with decorative scrum ceremonies.&lt;/p&gt;
&lt;p&gt;Are we stuck with opinions? Must we be subjected to the obligatory &amp;ldquo;well, in my experience &amp;hellip;&amp;rdquo;? Are we simply expressing our personal feelings, or is there some truth to be had?&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Haskell&#39;s Triangle</title>
      <link>https://thomascothran.tech/2017/07/haskells-triangle/</link>
      <pubDate>Mon, 17 Jul 2017 00:00:00 +0000</pubDate>
      
      <guid>https://thomascothran.tech/2017/07/haskells-triangle/</guid>
      <description>&lt;p&gt;The polymath Blaise Pascal envisaged a triangle built of numbers. Pascal’s triangle — as it is usually called, despite the fact that its discovery predated Pascal by centuries — has the interesting property that each number is the sum of the two numbers directly above it.&lt;/p&gt;
&lt;p&gt;In this post we will use Pascal’s triangle to demonstrate how recursion (i.e., a procedure that invokes itself in its definition) can be used to make complex problems easily soluble, using examples written in both Haskell and JavaScript.
Wikipedia&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Recursion Made Simple with Roman Numerals</title>
      <link>https://thomascothran.tech/2017/07/recursion-with-roman-numerals/</link>
      <pubDate>Mon, 17 Jul 2017 00:00:00 +0000</pubDate>
      
      <guid>https://thomascothran.tech/2017/07/recursion-with-roman-numerals/</guid>
      <description>&lt;p&gt;A procedure is recursive if it invokes itself. Thus:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;const toInfinityAndBeyond = num =&amp;gt; toInfinityAndBeyond(num + 1);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course, &lt;code&gt;toInfinityAndBeyond&lt;/code&gt; is only useful if, rather than seeking an answer, you want to blow your call stack. But you see the point: we find &lt;code&gt;toInfinityAndBeyond&lt;/code&gt; in its own body. What possible use could this be?&lt;/p&gt;
&lt;p&gt;Recursion is often well suited to express the logic of a problem. Let’s take a simple problem: the conversion of Roman to Arabic numerals. One solution is this one:&lt;/p&gt;</description>
    </item>
    
  </channel>
</rss>
