<?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:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[hacks all the way down]]></title><description><![CDATA[Trying to build useful things for ourselves and others, humanizing software in the process.]]></description><link>https://hatwd.com</link><image><url>https://substackcdn.com/image/fetch/$s_!ndKM!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc13b808-fdf4-4787-8f5b-1091754c87ac_1024x1024.png</url><title>hacks all the way down</title><link>https://hatwd.com</link></image><generator>Substack</generator><lastBuildDate>Wed, 29 Apr 2026 11:51:05 GMT</lastBuildDate><atom:link href="https://hatwd.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Thane Thomson]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[thanethomson@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[thanethomson@substack.com]]></itunes:email><itunes:name><![CDATA[Thane Thomson]]></itunes:name></itunes:owner><itunes:author><![CDATA[Thane Thomson]]></itunes:author><googleplay:owner><![CDATA[thanethomson@substack.com]]></googleplay:owner><googleplay:email><![CDATA[thanethomson@substack.com]]></googleplay:email><googleplay:author><![CDATA[Thane Thomson]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[LLMs will never be alive or intelligent]]></title><description><![CDATA[And "agents" will never know and cater to our every need]]></description><link>https://hatwd.com/p/llms-will-never-be-alive-or-intelligent</link><guid isPermaLink="false">https://hatwd.com/p/llms-will-never-be-alive-or-intelligent</guid><dc:creator><![CDATA[Thane Thomson]]></dc:creator><pubDate>Sat, 03 Jan 2026 18:26:15 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/c4465af5-2033-4655-af7a-ca67c197b1f9_1920x1282.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Over the holiday I thought I&#8217;d try my hand again at finding a way to, as automatically as possible, map my personal banking transactions (exported to a CSV file) to named accounts in my accounting system to help speed up the process of tracking my finances.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></p><p>This led me down a rabbit hole of trying to understand various approaches, algorithms and data structures that happen to also power modern AI systems (<a href="https://www.ibm.com/think/topics/vector-embedding">embedding</a>; <a href="https://en.wikipedia.org/wiki/Supervised_learning">supervised learning algorithms</a> like k-nearest neighbours, support vector machines, logistic regression, etc.; <a href="https://arxiv.org/abs/1706.03762">transformers</a>; etc.).<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a></p><p>While my little sojourn into this territory and my playing around with some of the popular LLMs by no means makes me an expert in any way on the algorithms themselves, I&#8217;ve come to a few assessments so far:</p><ol><li><p>LLMs are, as I&#8217;d initially suspected, ultimately just probabilistic token predictors (i.e. they predict words, symbols, etc.). This may sound obvious to anyone familiar with the space, but I had to verify my intuitions. They&#8217;re very impressive token predictors, of course, and it&#8217;s quite a marvel that we can get anything useful out of them at all, but token predictors nonetheless.</p></li><li><p>&#8220;Garbage in, garbage out&#8221; still applies to LLMs. This is probably why LLMs won&#8217;t be killing software development any time soon:</p><ol><li><p>There&#8217;s so much garbage software out there today and it seems highly unlikely to me that LLMs are only trained on the highest quality software available.</p></li><li><p>We software developers generally spend our time doing fairly novel things, for which it&#8217;s highly unlikely there&#8217;s existing training data for solving the exact problem we&#8217;re facing. So while I&#8217;m sure that breaking down the problem into steps where there <em>is</em> relevant training data might help, humans still need to break down those problems and then put the LLMs&#8217; recommendations together in a sane and manageable way. And it&#8217;ll probably stay that way for as long as we need to build novel things.</p></li><li><p>What about all the proprietary code out there that LLMs will never be able to be trained on? While that code may not be the best quality, it could represent solutions to entire classes of problems that LLMs will never be able to holistically predict.</p></li></ol></li><li><p>Even if it&#8217;s not &#8220;garbage in&#8221;, and an LLM is only trained on the highest quality software there is, there are so many ways to still get garbage out of an LLM depending on how its parameters are tweaked.</p></li><li><p>LLMs are not alive or intelligent, and never will be.</p></li><li><p>The promise of robotic/computer &#8220;agents&#8221; (especially ones based on LLMs) eventually being able to cater to your every need is dead on arrival.</p></li><li><p>The security and privacy implications of the push for agents to have deeper and deeper integration in our everyday lives are pretty scary.</p></li></ol><p>I&#8217;ll go into a little more depth on how I currently reason about points 4 and 5, and will link to other more knowledgeable folks&#8217; insights on 6.</p><h2>LLMs are not alive or intelligent</h2><p>As token predictors, LLMs are certainly not &#8220;alive&#8221; or &#8220;intelligent&#8221;, and they never will be. We can argue about technical definitions of &#8220;life&#8221; and &#8220;intelligence&#8221; but those arguments usually lead nowhere because we really don&#8217;t have good definitions of those terms at this time.</p><p>Life and intelligence seem to me to require the ability of an entity to at least <em>sense</em> what would be &#8220;better&#8221;, but generally also <em>move</em> or <em>act</em> in that direction.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a></p><p>Even the simplest of biological life can detect and act in the direction of &#8220;better&#8221;, like how single-celled organisms propel themselves in the direction of food sources and enact behaviours that protect them from harmful substances or environments.</p><p>As some of the most complex living organisms of which we currently know, humans have the ability to mentally map out paths of action potentially many steps ahead. In some cases, these paths may initially seem &#8220;worse&#8221; but ultimately result in &#8220;better&#8221; circumstances for the person (e.g. deliberately exercising to eventually become healthier, acting frugally to save up and make a big purchase, or invest time and effort into relationships or learning new skills). This ability to act in ways that result in better conditions for the being in the future seems to be what we intuitively associate with &#8220;intelligence&#8221; (and the more steps out into the future we&#8217;re able to plan and successfully execute, the greater the &#8220;intelligence&#8221;).</p><p>Token prediction to articulate multiple steps in solving a problem might <em>look</em> like intelligence, but it really isn&#8217;t. It&#8217;s the probabilistic output of a machine that&#8217;s acting on encodings of language that have been painstakingly articulated by humans over centuries. LLMs have no inherent notion of or ability to act towards &#8220;better&#8221;.</p><p>Even if you do look at their winning predictions (i.e. the ones they output to their users) as having been produced from some pre-encoded notion of &#8220;better&#8221;, this speaks more to the notions of &#8220;better&#8221; defined by the people facilitating the training of the underlying models than any notion of &#8220;better&#8221; that the models themselves hold.</p><p>One could argue that the <em>ecosystems</em> surrounding LLMs (the software developers, businesspeople, customers, etc.) can detect and move towards &#8220;better&#8221;, but the LLMs themselves cannot. This would mean that LLMs could possibly get progressively better over time at predicting the right tokens to be useful by people in the ecosystem, but the moment they stop being useful in the ecosystem we&#8217;d stop paying for them and nobody would run them. Or we&#8217;d only really use them in specific, niche circumstances where they could reliably predict the right tokens.</p><h2>The promise of &#8220;agents&#8221; is DOA</h2><p>The idea that a robotic/computational &#8220;agent&#8221; will eventually know and tend to your needs before you do is utter nonsense. Even more so if they leverage token predictors under the hood, as probabilistic failures compound in a multiplicative and potentially exponential ways.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a></p><p>Even if machines could detect &#8220;better&#8221;, they certainly would not be able to detect better <em>on your behalf</em>. We humans can&#8217;t even detect better on behalf of other humans, which is why even in healthy, long-term relationships and friendships we still need to communicate about what we need and want. We can only really detect &#8220;better&#8221; on behalf of ourselves, and even then we often struggle. What hubris to think that we could automate a process that we ourselves can&#8217;t even understand or execute manually!</p><p>If we built machines that could detect &#8220;better&#8221; for <em>themselves</em>, we would most likely end up with <a href="https://en.wikipedia.org/wiki/Skynet_(Terminator)">Skynet</a>. Doesn&#8217;t seem to me like a risk worth taking, especially in light of all the other problems humanity faces right now.</p><p>This doesn&#8217;t even begin to cover the security and privacy concerns introduced by modern agents being pushed progressively lower down in the stack to the OS level. As if gaining more &#8220;context&#8221; by spying on your every move will somehow allow an agent to detect your intentions, needs and ultimately detect &#8220;better&#8221; on your behalf. This is, in my opinion, probably a combination of magical thinking, enormous stupidity<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a> when it comes to security, and possibly even a ruse to trick people into allowing themselves to be spied on to an even greater degree than they already are.</p><h2>Security and privacy implications of &#8220;agent&#8221; integration</h2><p>I&#8217;ll leave the more detailed discussion of the security and privacy implications of attempting to integrate agents into the OS layer to the vastly more knowledgeable folks at Signal.</p><div id="youtube2-0ANECpNdt-4" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;0ANECpNdt-4&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/0ANECpNdt-4?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://hatwd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading hacks all the way down! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>Why spend a few hours every week/month doing something that you can spend weeks failing to automate, right? /s</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>My current aim with my personal finances is to try out k-nn to facilitate mapping of transactions (descriptions and amounts) to accounts. Still very much a WIP, as I&#8217;m still working on figuring out the right embedding process.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p>This perspective is heavily influenced by Robert Pirsig&#8217;s <a href="https://app.thestorygraph.com/books/f3158a48-cb26-4887-a8df-9b8cae6cc377">Zen and the Art of Motorcycle Maintenance</a>. </p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p>As an example, let&#8217;s say an LLM is correct 95% of the time (0.95) in predicting the &#8220;right&#8221; tokens to drive tools that power an &#8220;agent&#8221; to accomplish what you&#8217;ve asked of it. Each step the agent has to take therefore has a probability of being 95% correct. For a task that takes 2 steps, that&#8217;s a probability of 0.95^2 = 0.9025 (90.25%) that the agent will get the task right. For a task that takes 30 steps, we get 0.95^30 = 0.2146 (21.46%). Even if the LLMs were right 99% of the time, a 30-step task would only have a probability of about 74% of having been done correctly.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p>I use Krishnamurti&#8217;s definition of &#8220;stupidity&#8221; to mean &#8220;wrong values&#8221;.</p><p></p></div></div>]]></content:encoded></item><item><title><![CDATA[On politics and software]]></title><description><![CDATA[Being political is part of being human, but it's not healthy as a primary fixation.]]></description><link>https://hatwd.com/p/on-politics-and-software</link><guid isPermaLink="false">https://hatwd.com/p/on-politics-and-software</guid><dc:creator><![CDATA[Thane Thomson]]></dc:creator><pubDate>Wed, 05 Feb 2025 13:08:16 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/3e53c87b-38e6-4f06-a55e-8f15ae65a1d9_4000x6000.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>While talking politics is totally avoidable in social and work settings, <em>being</em> <em>political</em> is most certainly not.</p><p>What I mean by &#8220;being political&#8221; is effectively something like, &#8220;consciously or unconsciously navigating interpersonal trust/power dynamics&#8221;. Any time two or more people interact, there are trust/power dynamics at play in their interactions. With <a href="https://hatwd.com/p/software-is-mostly-made-of-people">social interaction being critical for building and maintaining good software</a>, software development cannot be free of such political dynamics.</p><p>Why does it feel so gross, even immoral, to talk about trust/power dynamics though? Maybe it&#8217;s just me, but I&#8217;ve always felt that way. How do we deal with those trust/power dynamics in a healthy way when working with others? And how does one think of and navigate such trust/power dynamics in the tech space specifically?</p><p>There&#8217;s a philosophical paradigm I picked up in my journey that I find quite valuable in helping answer these questions.</p><h2>The Metaphysics of Quality</h2><p>This paradigm comes from two of my favourite books: <a href="https://www.goodreads.com/book/show/629.Zen_and_the_Art_of_Motorcycle_Maintenance">Zen and the Art of Motorcycle Maintenance</a> and its lesser-known sequel <a href="https://www.goodreads.com/book/show/31093.Lila">Lila</a>, by Robert Pirsig.</p><p>From my own reading of it, the central thesis of ZAMM appears to be that what we call &#8220;quality&#8221; (or &#8220;value&#8221;) is all that there really is - it&#8217;s the only thing that can be considered a <em>noun</em> in the universe. It&#8217;s our name for the intuitive sense we have for that which is the driving force behind evolution. It&#8217;s not just an attribute of objects or a perception by subjects - it is the force that progressively gives rise to subjects and objects over time.</p><p>Pirsig then goes further to develop the beginnings of a &#8220;metaphysics of Quality&#8221; in Lila, where Quality can be broken down into:</p><ul><li><p><strong>Dynamic Quality</strong>, which Pirsig equates with the Tao from the <a href="https://www.goodreads.com/book/show/67896.Tao_Te_Ching">Tao Te Ching</a> (&#8220;The Tao that can be named is not the eternal Tao.&#8221;). It is the &#8220;bleeding edge&#8221; of the here-and-now. By the time you talk about it, it&#8217;s already moved on, so nothing can ever be said about it and it can only be experienced by &#8220;I&#8221; (see <a href="https://en.wikipedia.org/wiki/%27I%27_and_the_%27me%27">Mead&#8217;s &#8220;I and me&#8221;</a>).</p></li><li><p><strong>Static Quality</strong>, which is all the &#8220;stuff&#8221; in the universe. It is only ever temporarily stable before collapsing back into dynamic Quality. One can think of static Quality as, for example, ripples in water. Pirsig talks about there being at least four &#8220;levels&#8221; to the patterning in static Quality:</p><ul><li><p><strong>Inorganic patterns</strong>, like electromagnetic waves, elementary particles, molecules and ultimately inorganic matter like stars and rocks, water and air.</p></li><li><p><strong>Organic patterns</strong>, like cells, tissues and organisms. Between inorganic patterns and organic ones lies the transition between what we call death and life. Organic patterns can only arise from inorganic patterns (one cannot have cells without molecules), so inorganic patterns form a substrate for organic ones.</p></li><li><p><strong>Social patterns</strong>, which emerge when organisms interact with one another. Organic patterns form a substrate for social patterns (one cannot have social patterning without organisms). This is where trust and power/influence dynamics come into play, along with all forms of signalling that organic entities perform to each other (i.e. communication).</p></li><li><p><strong>Intellectual patterns</strong>, which arise when other patterns are &#8220;internalized&#8221; by sufficiently complex social + organic organisms. Social + organic patterns form a substrate for intellectual patterns. Concepts and ideas are effectively intellectual patterns.</p></li></ul></li></ul><h2>Morality</h2><p>Pirsig then goes further to say that we intuitively understand this movement from inorganic through to intellectual patterns as what we call &#8220;moral&#8221;. Life is more moral than death, so we invented medicine to pursue life. Healthy social dynamics are more moral than unhealthy isolation. Prioritizing the dissemination of good ideas (intellectual patterns) over politics (social patterns) is what we&#8217;d consider to be &#8220;moral&#8221;. Stories throughout human history are full of dramatizations of the undesirable outcomes when we prioritize the &#8220;lower&#8221; levels over the &#8220;higher&#8221; ones.</p><p>From what I can tell so far in my personal experience, too much of a fixation on lower levels of patterning generally results in an unhealthy life. For instance, if you fixate on taking care of your body at the expense of your personal relationships, you and those around you suffer. Similarly, if you fixate on power and influence at the expense of the adoption/implementation of the best possible ideas, you and those around you also suffer.</p><h2>Is it true, unique, complete?</h2><p>Is Pirsig&#8217;s framework &#8220;true&#8221;? In other words, does reality really work like this? I have no idea. It does seem to be a fairly useful lens through which to look at the world though, at least in terms of its explanatory powers.</p><p>Is it unique? Most likely not. Pirsig was heavily influenced by both Western and Eastern philosophy in developing his framework. He himself was a student of philosophy before deciding to leave formal academia.</p><p>Is it complete? Certainly not - Pirsig himself wrote in Lila about how others would need to expand/refine his framework in future work. It&#8217;s also not the only useful lens through which to look at the world, but I find it fairly comprehensive so far due to its simplicity. I also find it helpful to supplement this paradigm with those proposed by others, some of which I may cover in future posts.</p><h2>How is it useful?</h2><p>I say it&#8217;s a useful lens in that it explains and gives structure to a bunch of things for me, including this feeling I have around why focusing too much attention on politics and power dynamics feels gross, even immoral.</p><p>Politics and trust/power dynamics are a lower level of patterning that, just like our bodily dynamics, are a substrate and necessary prerequisite for human social life. But how much attention do they deserve? Just as better bodily health facilitates better social patterning and thinking, so does our social patterning need to be kept <em>healthy</em> in order to help facilitate the &#8220;higher&#8221; level patterns.</p><h2>Power and trust</h2><p>What does it mean to have healthy social dynamics though? Psychologists and sociologists have written volumes on this, and perhaps I&#8217;ll try exploring some of their ideas in future posts.</p><p>In the meantime, I&#8217;ve found it far more useful to think of social dynamics using a lens of <em><strong>trust</strong></em> than <em>power.</em> It places the locus of control back within the sphere of the individual, whereas the notion of <em>power</em> places it outside of the individual on those who must be controlled or influenced - not a healthy situation for anyone involved. Ultimately, adopting an <a href="https://en.wikipedia.org/wiki/Locus_of_control">internal locus of control</a> seems to result in a healthier, happier life, so it seems like a better paradigm to adopt.</p><h2>Trust and software development</h2><p>How is this relevant to software development? Again, since software development is generally a highly social activity, I find it worth occasionally reflecting on <em>trust</em> dynamics between people with whom I interact.</p><p>Especially the question of: <em>how much trust do I give others?</em> Generally, if I&#8217;m not dealing with a narcissist, the more I give the more I get in return. I always try to trust that people have good intentions, regardless of outcomes. This ultimately leads to a healthier work/social environment.</p><p>Then there&#8217;s also the question of: <em>whose idea ends up being implemented?</em> Is it mine because I&#8217;m the person in charge, or is it that of the junior engineer who just joined the team because their idea is better than mine? If I have decision-making authority, I try to prioritize the best idea, regardless of from whom it came. This sort of valuing of the best ideas, the best person for the job, etc. seems to generally work well for society when valued as such. Other approaches, like nepotism or cronyism, tend to result in suboptimal outcomes for society.</p><p>There&#8217;s much more to be said about trust and influence in the work context, especially the relationship between formal and informal influence, but I&#8217;ll leave those explorations for future posts.</p><h2>The flow of ideas</h2><p>More broadly, this paradigm also has interesting implications for the flow of ideas in society. Applying it, I hypothesize that ideas flow along lines carved out by trust/influence dynamics between people. Healthy lines of trust/influence facilitate the dissemination of good ideas far and wide, whereas unhealthy ones stem that flow. Sometimes healthy lines of trust/influence can also facilitate the dissemination of unhelpful or even harmful ideas, which is ultimately unhealthy for society.</p><p>I don&#8217;t have any strong recommendations as to how to fix an unhealthy flow of ideas. It&#8217;s a hard problem to solve. In recent years many have tried to stem the flow of misinformation, for example, but that still comes from a place of trying to control people as opposed to empower them to distinguish for themselves - a sign, for me, of an external locus of control, and acting from an unhealthy place like that rarely results in healthy outcomes for others.</p><p>The best (and healthiest) thing, I believe, that we can do in the face of constant misinformation and disinformation is empower people with the appropriate tools (psychological and technological) to discern for themselves what&#8217;s worth paying attention to and what&#8217;s worth disseminating to others.</p><h2>Conclusion</h2><p>Pirsig&#8217;s &#8220;metaphysics of Quality&#8221;, for me, provides a useful lens through which to look at the world. It shines a light on how <em>being political</em> is part of our human reality, but also that <em>being political</em> is not the end goal, nor should it be our primary fixation - in fact, it&#8217;s innately and intuitively <em>immoral</em> to do so. It helps me ask questions that I&#8217;ve found to be quite impactful in my life, and in the work context as a software engineer, team lead and engineering manager.</p><p>It&#8217;s certainly not the only useful lens out there, but it&#8217;s one that I personally like to use quite frequently, supplemented by those of others whose paradigms I&#8217;ve found to be useful.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://hatwd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading hacks all the way down! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[Software is mostly made of people]]></title><description><![CDATA[Code is just one of many critical ingredients to cultivating value.]]></description><link>https://hatwd.com/p/software-is-mostly-made-of-people</link><guid isPermaLink="false">https://hatwd.com/p/software-is-mostly-made-of-people</guid><dc:creator><![CDATA[Thane Thomson]]></dc:creator><pubDate>Fri, 03 Jan 2025 13:59:49 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/3b076e23-fc95-461b-ad0b-4ef779c47f1d_5472x3648.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Speaking with a colleague of mine the other day, I came to what I feel is an even deeper realization of how organic a working, value-producing software application really is.</p><p>We were talking about how it was difficult to understand some of the idiosyncrasies of one of the parts of our system that&#8217;s owned by another team &#8212; all of whom were on vacation at the time. Fortunately we could wait until they were back from vacation for us to ask them.</p><p>It did, however, make me realize that without all these people working together, collaborating and communicating frequently, the software really wouldn&#8217;t have the positive impact in the world that it does. Reflecting on it further, I&#8217;d go as far as to say that in general, <em><strong>value-producing software is first people, and then the code that they produce</strong></em>.</p><h2>From tech- to people-centred</h2><p>This perspective stands in stark contrast to my own perspective when I was much younger. I (foolishly) aimed to build software that would just take care of itself &#8212; build it once (perfectly, without bugs, LOL), users would flock to use my software and give me money, and I&#8217;d never need to look at it again. Kind of like publishing an award-winning book and then watching the royalties flow into my bank account. It was a misguided perspective that put the machine and the code at the centre of my paradigm as opposed to all the humans who were there in the background the whole time, but whom my paradigm wouldn&#8217;t allow me to see. It also vastly overestimated my powers of intuition to really know what users wanted or needed.</p><p>Over the years I&#8217;ve encountered so many developers who, like me, put technology at the centre of their paradigms &#8212; folks who have the &#8220;build it and they will come&#8221;, or &#8220;build it and we&#8217;ll worry about users, operations, maintenance, support, etc. later&#8221; mentality that I used to have. This post is an encouragement to people with such a paradigm to try to look at their craft from a different perspective.</p><h2>Software is primarily made of people</h2><p>When I write of &#8220;software&#8221; here, I&#8217;m referring to <em>running</em>, <em>value-producing</em> software &#8212; the kind that people use to make their lives better in some way. This sort of software is so much more than just code:</p><ul><li><p>For software to exist in the first place, it needs <em>developers</em>.</p></li><li><p>For software to run, it needs to run somewhere and someone needs to ensure that it&#8217;s working optimally: it needs <em>operators</em>.</p></li><li><p>For software to produce value, someone needs to use it, and get value from using it: it needs one or more <em>users</em>. Even software libraries, which aren&#8217;t ever run directly, have users: <em>other developers</em>.</p></li><li><p>For software to <em>continue</em> to produce value over time, someone needs to adapt it to users&#8217; evolving needs and its environment: it needs <em>maintainers</em>.</p></li><li><p>When software fails to provide the value it&#8217;s supposed to, users need someone to whom they can reach out and ask for help: it needs <em>support</em>.</p></li></ul><p>The code of the application is just a thin layer of technology facilitating value-producing interactions between all of these people: consumers and cultivators, to put it another way. It&#8217;s a crucial part of that set of interactions, of course, but it&#8217;s by no means all-encompassing.</p><p><a href="https://en.m.wikipedia.org/wiki/Conway%27s_law">Conway&#8217;s Law</a>, which is just as relevant in 2025 as it was back in the 1960s when the idea was introduced, illustrates how people-centric just the development process is:</p><blockquote><p>[O]rganizations which design systems (in the broad sense used here) are constrained to produce designs which are copies of the communication structures of these organizations.</p></blockquote><p>Martin Fowler even speaks of an <a href="https://martinfowler.com/bliki/ConwaysLaw.html">inverse Conway&#8217;s manoeuvre</a> (originally from <a href="https://jonnyleroy.com/2011/02/03/dealing-with-creaky-legacy-platforms/">this article</a> by Jonny LeRoy and Matt Simons), where if you want to change the overall structure of a large software application you first restructure your organization to reflect the desired high-level software structure and let natural communication patterns do the rest.</p><h2>Implications</h2><p>One of the biggest implications from this paradigm shift for me was in how I now think about building and running software-based businesses.</p><p>When I was younger, I focused exclusively on the technology and assumed that everything else would fall into place. In recent years, however, when thinking about software-based business ideas (ones where there&#8217;s a real user need first), I think to myself: what kind of team would I need to make this a reality, and what kind of environment do we need to cultivate for that team to encourage healthy engagement with each other and our users?</p><p>There are other implications for this paradigm shift, of course, largely relating to the influence of individual and group psychology on the way that software is built and evolves over time. I hope to write about my experiences and observations along these lines in the coming months.</p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://hatwd.com/p/software-is-mostly-made-of-people?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading <strong>hacks all the way down</strong>! This post is public so feel free to share it.</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://hatwd.com/p/software-is-mostly-made-of-people?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://hatwd.com/p/software-is-mostly-made-of-people?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div>]]></content:encoded></item><item><title><![CDATA[An imperative programmer tries to learn Haskell]]></title><description><![CDATA[A tale of struggle and resignation.]]></description><link>https://hatwd.com/p/an-imperative-programmer-tries-to</link><guid isPermaLink="false">https://hatwd.com/p/an-imperative-programmer-tries-to</guid><dc:creator><![CDATA[Thane Thomson]]></dc:creator><pubDate>Wed, 18 Dec 2024 13:48:25 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/c06aed23-90fa-4961-ad11-d41fe3956299_2560x1808.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a href="https://adventofcode.com">Advent of Code</a> usually seems to be a great way for me to learn a new programming language - something I&#8217;ve heard other developers do too. I had my first experiences with Go and Rust this way.</p><p>Given that I&#8217;d been working primarily with imperative languages for decades now, I thought I&#8217;d challenge myself to learn a functional programming language. Current and past colleagues and friends had spoken highly of Haskell, especially those who value the ideal of &#8220;only making valid program states representable in code&#8221;, so I thought I&#8217;d give it a try and document my experience.</p><p><strong>TL;DR:</strong> I don&#8217;t think I&#8217;ll be using Haskell or other pure functional languages for building anything meaningful any time soon. I suspect that, in all the years of using imperative programming languages, my brain&#8217;s adapted to that paradigm of human-computer interaction and it&#8217;d be far too much effort, for little or uncertain reward, to really become productive in a pure functional paradigm. YMMV though, of course - this is just my personal experience. And, I still don&#8217;t fully understand what a monad is.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://hatwd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading hacks all the way down! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h2>Setup</h2><p>Being used to the simple process of installing Go (<code>brew install go</code>) and Rust (via <a href="https://www.rust-lang.org/tools/install">Rustup</a>), I was a little taken aback at the complexity of the Haskell installation process. While it&#8217;s not insurmountable, and <a href="https://www.haskell.org/ghcup/">GHCup</a> seems to help here, it&#8217;s still odd to me that one would need to manually select specific versions of all the relevant tools necessary to get started (as though I know what I&#8217;m doing at this point, I mean really &#128516;).</p><p>Setting up my coding environment was fairly simple, although <a href="https://dev.to/bkataru/its-2024-so-why-not-setup-neovim-w-nvchad-for-haskell-2kj8">this article</a> sent me down a rabbit hole that made me realize I&#8217;d been using Neovim on hard mode for years now (I&#8217;ve been loving the simplicity of <a href="https://nvchad.com/">NvChad</a> and configuring it in Lua, especially with the Lua language server&#8217;s help). Several hours later, I had a freshly revamped Neovim setup and the Haskell language server installed, and was ready to start coding.</p><h2>Hello world</h2><p>Haskell advocates had previously pointed me to <a href="https://learnyouahaskell.github.io/">Learn You a Haskell</a> (LYAH), so I started learning the basics of the language there, playing around with <strong>GHCi</strong> - the interactive Haskell CLI. Only after writing my first &#8220;Hello world&#8221; application manually did I discover the existence of and how to use <a href="https://www.haskell.org/cabal/">cabal</a>, and how it would&#8217;ve made my life a little easier to initialize and build standalone Haskell applications. Although, I could&#8217;ve done with some simple way of adding dependencies via the CLI, because I couldn&#8217;t really figure out the <code>.cabal</code> file&#8217;s syntax.</p><p>It&#8217;s really odd to me that all the Haskell tutorials I could find didn&#8217;t start by describing the tooling and how to navigate the basics of building a standalone Haskell application. In fact, they seems to focus pretty much all of their attention on the language and its use via GHCi. Compare this to:</p><ul><li><p><a href="https://go.dev/doc/tutorial/getting-started">Go&#8217;s getting started tutorial</a></p></li><li><p><a href="https://www.rust-lang.org/learn/get-started">Rust&#8217;s installation instructions</a> (especially the direct link to the <code>cargo</code> instructions)</p></li></ul><p>Building software is so much more than just writing code. There&#8217;s also initializing and organizing your project, managing dependencies, configuring your tooling, building and running the application, writing and running tests, configuring CI, refactoring, etc. I have no interest in programming languages that are a dream to code in, but are a pain-in-the-ass to build, test or get working in CI. I want a glimpse of the whole end-to-end development experience up-front so I know what I&#8217;m getting myself into and whether it&#8217;s worth investing my limited time and energy.</p><h2>Advent of Code</h2><p>One of the things I loved about learning Go was that it was fairly easy to understand and to start being productive. In learning any new skill, it seems as though quick wins early on tend to be a natural motivator to continue learning.</p><p>Haskell, on the other hand, made me feel as though my brain was continuously straining to reach a shelf that was too high for someone of my stature. By day 2 of the Advent of Code challenges (which took me until about day 10 of AoC to complete), I felt pretty defeated.</p><p>From the complex setup process, to feeling like I was flailing when trying to craft an application, to trying to make heads or tails of the cryptic, esoteric warnings and errors generated by the LSP and compiler, it was a painful experience. Perhaps I&#8217;ve been spoiled by Go&#8217;s simplicity and the Rust compiler&#8217;s helpful, human-readable error messages and suggestions.</p><p>Don&#8217;t get me wrong, when I finally got my solutions to work they were incredibly concise and elegant. I just didn&#8217;t enjoy the process of getting there.</p><h2>Learning curve</h2><p>In the early stages of learning a new programming language, I&#8217;m aware that I&#8217;m solving problems at two levels:</p><ol><li><p>How do I help the user solve their problem using a computer?</p></li><li><p>How do I translate my mental model of a potential solution to (1) into this specific programming language and toolchain?</p></li></ol><p>It&#8217;s the second problem, the &#8220;learning curve&#8221;, that really tripped me up with Haskell. Interestingly, I had a similar experience with Rust, and this is also one of my biggest criticisms of Rust: for most of the time when I was learning and using the language, it felt like I was trying to solve language problems more than trying to address the user story - especially when I tried to do complex things in Rust&#8217;s <code>async</code> world. That&#8217;s fun for a while, but it eventually becomes tedious.</p><p>The most <em>enjoyable</em> programming languages, I&#8217;ve found, are ones that &#8220;get out of the way&#8221; and allow me to address the user story as quickly as possible. Maybe I&#8217;m getting old, or maybe I just get more of a kick out of seeing the user happy than solving programming language problems.</p><p>There are certainly people who just &#8220;click&#8221; with languages like Haskell - I&#8217;ve known a few of them personally. Their mental model of the world fascinates me because of how distinct it is to mine. All of them have been people who, to me at least, seem to hold a deep appreciation for the ideals embodied in mathematics and philosophy, and they generally tend to be somewhat disgusted by languages like Go. They also generally tend to be smarter than me, evidenced to me by how quickly they think and their high degree of verbal intelligence.</p><h2>The language of the machine</h2><p>I don&#8217;t understand that paradigm of mathematical and functional purity though in the context of computers.</p><p>It&#8217;s not that I&#8217;m against mathematics in any way - I did pretty well in math in high school and during my engineering studies, and particularly enjoyed using differential equations and stochastic processes in the realm of telecommunications. I also know that, without that math, computers wouldn&#8217;t even exist.</p><p>In my paradigm, however, computer chips just don&#8217;t work in a functionally pure manner. When you look at the language of a modern CPU (see, for example, the <a href="https://developer.arm.com/documentation/ddi0602/2021-12/Base-Instructions?lang=en">ARMv9 base instruction set</a>), every part of it is an <em>instruction</em> to do something - i.e. an imperative mode of execution.</p><p>Maybe I misunderstand what functional programmers are aiming to do, but the functional paradigm seems to me like an attempt to express an ideal of some kind on top of that fundamentally imperative mode of execution. Never mind the fact that computers themselves, elegant as they can be nowadays, are mathematically imperfect machines that are subject to operating ranges, manufacturing tolerances and are replete with all kinds of hidden workarounds at various levels of their architecture so their various makers could meet their deadlines.</p><h2>The great, and not-so-great</h2><p>Okay, enough rambling, let&#8217;s get to the lists.</p><p>There are certainly a few things that I found pretty great about Haskell and its ecosystem:</p><ol><li><p>One can express solutions to certain classes of problems very concisely. I do like the look of this elegance. While this elegance is obvious in solutions to the Advent of Code-style problems, I haven&#8217;t yet had enough experience with Haskell to know if this translates well to your everyday garden variety problems (e.g. building CRUD applications).</p></li><li><p>Its type system is far more expressive than other languages I&#8217;ve used. This is a big one - while I haven&#8217;t personally experienced it, I&#8217;m starting to see how its type system lends itself to better compile-time correctness, allowing one to eliminate certain classes of bugs at compile time.</p></li><li><p>The existence of <a href="https://hoogle.haskell.org/">Hoogle</a> blew my mind. Who knew one could build a search engine that allowed you to look up packages and function documentation just from a function signature? For example, I used it to find a function to split a string by newlines, where my query was just: <code>String -&gt; [String]</code>, or &#8220;find me a function that takes a string, and returns a list or array of strings&#8221;.</p></li><li><p>The language server is pretty helpful, especially in terms of making your statements more concise.</p></li></ol><p>Things that I think will dissuade me, at least for now, from continuing to learn it or use it in any production system:</p><ol><li><p><a href="https://survey.stackoverflow.co/2024/technology#most-popular-technologies-language-prof">It&#8217;s still a relatively unpopular programming language in 2024</a>. This, to me, indicates that very few companies will actually use it for production code, and it&#8217;ll be hard to find developers to build teams, making the sustainability of such solutions questionable.</p></li><li><p>The learning curve just seems too great. My software development paradigm would need to undergo a far more substantial adaptation than I&#8217;d initially anticipated, and it&#8217;s unclear to me what the benefit would be to incur such pain at this stage of my career. Especially given Haskell&#8217;s relatively unpopular status as a programming language.</p></li></ol><p>And finally, a couple of small things that really irk me:</p><ol><li><p>The fact that <a href="https://hackage.haskell.org/package/containers-0.7/docs/Data-Set.html#g:6">set membership querying</a> and <a href="https://hackage.haskell.org/package/containers-0.4.0.0/docs/Data-Map.html#g:3">map element lookups</a> are <em>O(log n)</em> as opposed to <em>O(1)</em>. Like, why?</p></li><li><p>I still can&#8217;t fully wrap my head around what a <em>monad</em> is, even after apparently using it for years now. After reading many definitions, examples and having it explained to me by functional programming advocates, I feel like that understanding is about to dawn on me. It is, however, still very much night time for me when it comes to monads, and category theory more generally. Given the nature of the language, until I understand category theory better, I have this feeling I won&#8217;t really be able to wield it effectively.</p></li></ol><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://hatwd.com/p/an-imperative-programmer-tries-to?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading hacks all the way down! This post is public so feel free to share it.</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://hatwd.com/p/an-imperative-programmer-tries-to?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://hatwd.com/p/an-imperative-programmer-tries-to?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><p></p>]]></content:encoded></item><item><title><![CDATA[Things I love about Golang]]></title><description><![CDATA[Having written software in a wide variety of programming languages over the past 30 years, I have to say that I&#8217;ve really been enjoying using in Go when building server-side or CLI applications.]]></description><link>https://hatwd.com/p/things-i-love-about-golang</link><guid isPermaLink="false">https://hatwd.com/p/things-i-love-about-golang</guid><dc:creator><![CDATA[Thane Thomson]]></dc:creator><pubDate>Sun, 01 Dec 2024 13:46:58 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/f53d459c-4452-4321-8da9-1f6c324a582d_1634x2224.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Having written software in a wide variety of programming languages over the past 30 years, I have to say that I&#8217;ve really been enjoying using in Go when building server-side or CLI applications.</p><p>Some of the things I love about it:</p><ul><li><p>It&#8217;s a fairly simple language, providing a relatively compact toolbox with which you can accomplish a wide variety of things.</p></li><li><p>You can get really far by just using the standard library. It&#8217;s rare these days that I find myself genuinely <em>needing</em> to import some specific dependency. And anyways, a <a href="https://www.youtube.com/watch?v=PAAkCSZUG1c&amp;t=568s">little copying is better than a little dependency</a> in many cases.</p></li><li><p>Applications compile really quickly compared to other programming languages. If they&#8217;re built reasonably well, they run really quickly too.</p></li><li><p>Go&#8217;s dependency management approach of not having a centralized registry in which artifacts are stored, in my mind, potentially offers greater supply chain attack resiliency than other languages where the artifact in their registry need not match any code at any particular commit in a publicly accessible repository.</p></li><li><p>Its <a href="https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/">colorless</a> concurrency model makes it really ergonomic to build concurrent systems.</p></li><li><p>The Go team&#8217;s conservative approach to backward-compatibility provides a really stable platform on which to build applications that could last a long time. This makes it a good candidate for building &#8220;enterprise software&#8221;.</p></li><li><p>It&#8217;s maintained by a pretty large company who seems to have a vested interest in its success. This gives me a degree of peace of mind that applications I build today could possibly still be compiled in 10 years&#8217; time. This strengthens the case for its use in &#8220;enterprise software&#8221;, since such software can often exceed hundreds of thousands of lines of code and would be very expensive to rewrite.</p></li></ul><p></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://hatwd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading <strong>hacks all the way down</strong>! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[It's all hacks, all the way down]]></title><description><![CDATA[Imperfect, but good enough.]]></description><link>https://hatwd.com/p/its-all-hacks-all-the-way-down</link><guid isPermaLink="false">https://hatwd.com/p/its-all-hacks-all-the-way-down</guid><dc:creator><![CDATA[Thane Thomson]]></dc:creator><pubDate>Sun, 01 Dec 2024 00:22:34 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/b47ee0a1-0eae-4209-8caf-ecf34b1d2cdf_1024x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>For the longest time in my career I&#8217;ve been plagued by a fear that perhaps I&#8217;m missing the perfect solution to a given problem. Well, the fear is that I&#8217;ll miss the &#8220;best&#8221; solution and inadvertently blow something up, with catastrophic consequences for my career and life.</p><p>But what if, in fact, every pragmatic, valuable solution is an imperfect one? A <em>hack</em>, if you will.</p><p>An idea&#8217;s been brewing in the back of my mind for some time now: what if reality is filled with these sorts of hacks all the way down to the finest levels of detail? For example, what if atoms are &#8220;hacks&#8221; of a sort, which are &#8220;hacked&#8221; together into cells, which are &#8220;hacked&#8221; together into humans, who hack hardware and software solutions together?</p><p>At almost every level of detail I can think of examples of how reality has facilitated structures or processes that work well under certain conditions, but fall apart fairly quickly outside of those conditions. When some smaller structures or processes are &#8220;stable&#8221; enough, others are built on top of them or by composing them. None of these composed structures, however, could be considered &#8220;perfect&#8221; because outside of their workable conditions they can become a house of cards.</p><p>What makes me think there is such a thing as a &#8220;perfect&#8221; software solution to a given problem in the first place? Maybe the only practical solutions are necessarily imperfect.</p><p>Imperfect, but <em>good enough</em>.</p><p></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://hatwd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading <strong>hacks all the way down</strong>! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item></channel></rss>