<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>quickblog</title>
  <link href="https://github.com/borkdude/quickblog/atom.xml" rel="self"/>
  <link href="https://github.com/borkdude/quickblog"/>
  <updated>2026-05-29T22:46:13+00:00</updated>
  <id>https://github.com/borkdude/quickblog</id>
  <author>
    <name>Quick Blogger</name>
  </author>
  <entry>
    <id>https://github.com/borkdude/quickblog/2023-08-17.notes-on-design-in-practice.html</id>
    <link href="https://github.com/borkdude/quickblog/2023-08-17.notes-on-design-in-practice.html"/>
    <title>Think Twice, Write Once: Notes on Rich Hickey's "Design in Practice"</title>
    <updated>2023-08-17T23:59:59+00:00</updated>
    <content type="html"><![CDATA[<p>In the popular imagination, the software engineer is a romantic hero who sits down at a glowing screen, cracks their knuckles, and immediately starts typing lines of code at a furious pace. They don't think; they just <em>build</em>. </p><p>In the real world, this is a recipe for building a system that runs beautifully, passes its tests, and solves entirely the wrong problem. </p><p>Rich Hickey’s talks have long been a guide for developers trying to escape this trap. He is famous for advocating "hammock time"—the practice of stepping away from the keyboard, closing your eyes, and actually thinking about the problem before writing a single line of code. </p><p>Hickey’s talk, <em><a href='https://www.youtube.com/watch?v=c5QF2HjHLSE'>Design in Practice</a></em>, is a masterclass in how to formalize this process. It is the practical companion to his philosophical talks, offering a concrete structure for recording design decisions without drowning in corporate bureaucracy. It also serves as a beautiful elaboration on Architecture Decision Records (ADRs), a concept first popularized by <a href='https://www.cognitect.com/blog/2011/11/15/documenting-architecture-decisions'>Mike Nygard's 2011 post</a>, which I still reference regularly.</p><p>Here are my key takeaways and reflections on the talk.</p><h2>Why Design? (Or: The Cognitive Savings Account)</h2><p>If you ask the average developer why they don't write design documents, they'll tell you they don't have time. They need to ship features. </p><p>But design isn't about satisfying auditors or writing massive Word documents that no one reads. Design is a cognitive savings account. The goals of formalizing design are intensely practical:</p><ul><li><strong>Reducing Context-Switching Costs:</strong> We all have "hammock time," but when we wake up or get interrupted, how long does it take to rebuild that mental state? A good design record lets you return to your context in minutes instead of hours.</li><li><strong>Onboarding Others:</strong> It allows teammates to step into your mental frame without needing a three-hour whiteboard session.</li><li><strong>Smaller, More General Solutions:</strong> When you design on the fly, you write code for specific edge cases as you hit them. When you design upfront, you find general abstractions that solve entire classes of problems at once. The final code is almost always smaller.</li></ul><h2>The Power of the Socratic Method</h2><p>Hickey emphasizes that design is essentially a Socratic dialogue with yourself. It requires detaching your ego from your ideas. The goal isn't to prove your favorite solution is right; it's to discover the objective truth of the system.</p><p>He suggests framing your progress around four fundamental questions:</p><ol><li><strong>Where are you at?</strong> (Your current state and constraints).</li><li><strong>Where are you going?</strong> (The target objective).</li><li><strong>What do you know?</strong> (Your facts and assumptions).</li><li><strong>What do you need to know?</strong> (Your unknowns and research spikes).</li></ol><p>By continuously asking these questions, you engage in <em>reflective inquiry</em>—being aware of your own cognitive state. </p><p>Part of this discipline is linguistic precision. If two developers use the same word to mean different things, design fails. Hickey recommends compiling a <strong>glossary</strong> early in the process. Force yourself to define your terms. If you can't explain what a term means in two sentences, you don't understand it yet.</p><h2>The 6-Phase Lifecycle of Design</h2><p>To turn these philosophical ideas into practice, Hickey breaks the software design and development process into six distinct, sequential phases:</p><pre><code class="lang-mermaid">graph TD
    A&#91;1. Describe&#93; --&gt; B&#91;2. Diagnose&#93;
    B --&gt; C&#91;3. Delimit&#93;
    C --&gt; D&#91;4. Direction&#93;
    D --&gt; E&#91;5. Design&#93;
    E --&gt; F&#91;6. Dev&#93;
    E -.-&gt;|Backtrack if needed| C
</code></pre><h3>1. Describe (The What)</h3><p>Write down the situation as you hear it. Focus entirely on describing symptoms, not solutions. How big is the problem? What is the business impact? If a database is slow, don't say "we need Redis." Say "queries on the user table are taking 800ms, delaying checkout."</p><h3>2. Diagnose (The Why)</h3><p>Accumulate hypotheses. There is never just one reason for a bug or bottleneck. List them all and use the scientific method to test them one by one. Prove your hypotheses with data, not vibes.</p><h3>3. Delimit (The Scope)</h3><p>If you do steps 1 and 2 correctly, you will discover that you are facing a Hydra of multiple, interconnected problems. You cannot solve them all. Delimiting means drawing a hard boundary around the <em>single</em> problem you are going to solve right now. </p><h3>4. Direction (The Strategy)</h3><p>List high-level approaches and evaluate their trade-offs. Hickey suggests putting these in a decision matrix: columns are your approaches, and rows are your criteria (e.g., development time, operational cost, legal compliance). This is where bad ideas go to die, cheaply and quickly, before they cost a single line of code.</p><h3>5. Design (The Tactics)</h3><p>Once you have chosen a direction, map out the implementation path. Choose your libraries, database schemas, and API contracts. If you discover during this phase that your assumptions were wrong, backtrack. It is infinitely cheaper to rewrite a design document than to refactor a production database.</p><h3>6. Dev (The Execution)</h3><p>Actually write the code. If you did phases 1 through 5 correctly, this should be the easiest, most mechanical part of the entire process. You aren't guessing or exploring; you are simply executing a well-defined blueprint.</p><h2>The Takeaway</h2><p>Writing code is fun. Thinking is hard. </p><p>But as software systems grow in complexity, the developers who succeed are not the ones who type the fastest. They are the ones who know how to sit in the hammock, ask the right questions, and write their decisions down.</p><p><em>For more details, check out the <a href='https://www.youtube.com/watch?v=c5QF2HjHLSE'>video of the talk</a> or read the <a href='https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/DesignInPractice.md'>full transcript</a>.</em></p>]]></content>
  </entry>
  <entry>
    <id>https://github.com/borkdude/quickblog/2023-02-01.perfection-ism-induced-hiatus-complete.html</id>
    <link href="https://github.com/borkdude/quickblog/2023-02-01.perfection-ism-induced-hiatus-complete.html"/>
    <title>The NIH Hangover: Why I Abandoned My Custom Engine for Borkdude’s Quickblog</title>
    <updated>2023-02-01T23:59:59+00:00</updated>
    <content type="html"><![CDATA[<p>If you read my first two posts, you might remember my passionate, intellectual defense of technical self-reliance. I argued that dependencies are a trap, that building your own static site generator is a path to programming sovereignty, and that custom EDN-based rendering is the ultimate expression of data-driven design. </p><p>And then, I didn't publish a single post for over two years. </p><p>There is a delicious, painful irony here. The very system I built to liberate myself from the bloated abstractions of modern web development ended up silencing me. I fell victim to the classic NIH (Not Invented Here) hangover.</p><h2>The Cost of Sovereignty</h2><p>So, what happened? In the real world, things got busy. I started a new job. My wife and I welcomed our second child. My personal programming time, once a vast ocean of late-night hacking, shrunk to a few precious puddles of semi-conscious hours. </p><p>But the real reason for the silence was friction. </p><p>Every time I wanted to write a quick note, I had to open up custom Lisp files, copy-paste DSL templates, configure Aero tags, and manually structure layout vectors. If I wanted to tweak the design, I had to do major surgery on my custom engine's compiler passes. </p><p>I had wanted to take my custom DSL in a brand-new direction, but the sheer mental overhead of building and maintaining that tool started to exceed the utility of the blog itself. A blog's primary job is to be a communication tool—a record of thoughts. If the tool makes writing feel like work, you stop writing. </p><p>The ultimate developer trap is optimizing the shovel instead of digging the hole.</p><h2>The Pragmatic Pivot</h2><p>As a mid-career engineer, much of my value comes from guiding teams away from rabbit holes and engineering pitfalls. Yet, I had guided myself straight into one. </p><p>I needed to apply my own professional judgement to my personal projects. I sat down and asked: <em>What are my actual priorities?</em> If the priority is writing, then the engine needs to be as invisible as possible. The benefits of maintaining my own custom engine had run their course. It was time to outsource the plumbing.</p><p>I wanted something lightweight, built on a stack I loved, that handles the boring details while letting me write in plain Markdown. Enter <strong>quickblog</strong> by Michiel Borkent (affectionately known in the Clojure community as <code>@borkdude</code>). </p><p>Quickblog is built on Babashka—a fast, native Clojure scripting engine—and standard markdown parsing. It is clean, minimalist, and doesn't require a master's degree in language design to add a bulleted list. Porting my old posts and custom styles over took an afternoon of work, but the return on investment was immediate: the friction was gone.</p><h2>The Wisest 5-Year-Old in the Room</h2><p>This shift in priorities has made me reflect on a lesson I've been learning in parenting. </p><p>Lately, whenever my family is running late and I start rushing, my five-year-old daughter likes to look up and say, <em>"Daddy, remember the story of the tortoise and the hare? Slow and steady wins!"</em> </p><p>She is wiser than she knows. In software, as in parenting, rushing is almost always a trap. Trying to move quickly on an ineffective path (like building a custom layout engine just to write a blog post) is magnitudes slower than choosing an effective path and moving steadily. </p><p>I am no longer in the blog generator business. I am back in the writing business. And hopefully, you'll be reading more from me because of it.</p>]]></content>
  </entry>
  <entry>
    <id>https://github.com/borkdude/quickblog/2020-12-11.parsing-and-grammars.html</id>
    <link href="https://github.com/borkdude/quickblog/2020-12-11.parsing-and-grammars.html"/>
    <title>The Seductive Trap of the Hand-Written Parser</title>
    <updated>2022-12-11T23:59:59+00:00</updated>
    <content type="html"><![CDATA[<p>Every developer, at some point in their career, falls into the same seductive trap. You have some string input—maybe a custom config file format, a DSL for layout, or a set of nested parenthetical commands. You need to parse it. </p><p>You think: <em>"I don't need a heavy grammar engine. I'll just write a quick regular expression and a split loop. It'll take ten minutes."</em></p><p>And it does. And it works beautifully. You feel like a wizard. </p><p>But then, the requirements change. You need to support nested brackets. You need to handle escaped quotes. Suddenly, that "quick regex" turns into a recursive, state-holding, back-tracking monster. You spend your weekends stepping through 300 lines of nested <code>if/else</code> statements, muttering dark oaths under your breath. You are trapped by the sunk-cost fallacy, unwilling to throw away the subsystem you’ve spent weeks debugging.</p><p>A hand-written parser is a financial loan shark: it offers incredibly easy terms upfront, followed by ruinous interest rates later.</p><h2>Decomplecting the Problem</h2><p>If we want to build a better parser, we have to follow the classic Rich Hickey advice: <em>let's decomplect it</em>. We must untangle the three distinct duties that a parser implicitly performs:</p><ol><li><strong>Lexing (The Tokenizer):</strong> Slicing raw characters into meaningful words, or "tokens." For example, in Javascript, the characters <code>f</code>, <code>u</code>, <code>n</code>, <code>c</code>, <code>t</code>, <code>i</code>, <code>o</code>, <code>n</code> are recognized collectively as a single keyword token.</li><li><strong>Parsing (The Structurer):</strong> Taking the flat stream of tokens and arranging them into a hierarchical tree (an Abstract Syntax Tree, or AST) that reflects the recursive nature of the language.</li><li><strong>Evaluating (The Actor):</strong> Walking the AST and executing the actual logic or translating it into another format.</li></ol><p>Historically, computer scientists separated these concerns into specialized tools. In 1975, Mike Lesk and Eric Schmidt (who would later become the CEO of Google) wrote <strong>Lex</strong>, a lexical analyzer generator. It was typically paired with <strong>Yacc</strong> ("Yet Another Compiler-Compiler"), a parser generator. </p><p>For decades, CompSci students (including myself, fifteen years ago) were forced to learn these tools. It was dry, theoretical, and slightly painful. But the professors had a point: formal grammars are vastly superior to custom procedural parsing code.</p><h2>The Modern Alternative: ANTLR 4</h2><p>Today, we don't have to use Lex and Yacc. We have tools like <strong>ANTLR 4</strong> (Another Tool for Language Recognition), which combines lexer and parser definitions into a single, clean grammar file.</p><p>Here is a simple ANTLR 4 grammar for the ubiquitous CSV (comma-separated values) format:</p><pre><code class="lang-antlr">csvFile: hdr row+ ;
hdr    : row ;
row    : field &#40;',' field&#41;&#42; ' '? '\r'? '\n' ;
field  : TEXT
       | STRING
       |
       ;

TEXT   : &#126;&#91;, &quot;\r\n&#93;+ ;
STRING : '&quot;' &#40;'&quot;&quot;'|&#126;'&quot;'&#41;&#42; '&quot;' ;
</code></pre><p>In ANTLR, lexer rules (which define tokens) begin with an uppercase letter (<code>TEXT</code>, <code>STRING</code>), while parser rules (which define structure) begin with a lowercase letter (<code>csvFile</code>, <code>hdr</code>, <code>row</code>, <code>field</code>). </p><p>Look at how declarative this is. You don't write loops or search algorithms. You simply describe what a CSV file <em>is</em>. The generator takes this description and outputs highly optimized parsing code in Java, Clojure, Python, or JavaScript.</p><h2>The Ambiguity Cliff</h2><p>The trickiest part of designing your own language is <em>ambiguity</em>. An ambiguous language is one where a single string of characters can match more than one parser rule.</p><p>Consider this naive grammar for links:</p><pre><code class="lang-antlr">link: '&#91;&#91;' STRING '&#93;&#93;' ;
alias: '&#91;' STRING '&#93;&#40;' STRING '&#41;' ;
STRING: &#91;a-zA-Z0-9 &#93;+ ;
</code></pre><p>What happens if the parser encounters <code>&#91;&#91;alias&#93;&#40;target&#41;&#93;</code>? </p><p>Because both rules start with the open bracket <code>&#91;</code>, the parser has to guess which path to follow. Without sufficient lookahead, it may commit to the <code>link</code> rule, proceed to look for <code>&#93;&#93;</code>, fail to find it, and throw a syntax error.</p><p>To avoid this, you should design your language syntax to be structurally unambiguous from the start. If that isn't possible, you can resort to lookahead markers or design your parser rules to explicitly allow optional characters to resolve the conflict. For example, using lookahead checks like ANTLR’s semantic predicates to check what characters follow.</p><h2>Further Reading</h2><p>If you want to escape the cycle of hand-written parser grief, I highly recommend:</p><ul><li><strong><a href='https://www.antlr.org/'>ANTLR 4</a>:</strong> Extremely powerful, performant, and well-supported.</li><li><strong><a href='https://github.com/aphyr/clj-antlr'>clj-antlr</a>:</strong> A Clojure wrapper by @aphyr, who ran excellent performance comparisons against Instaparse.</li><li><strong><a href='https://pragprog.com/titles/tpantlr2/the-definitive-antlr-4-reference/'>The Definitive ANTLR 4 Reference</a>:</strong> The bible for language design.</li></ul>]]></content>
  </entry>
  <entry>
    <id>https://github.com/borkdude/quickblog/2020-11-29.static-site-generator.html</id>
    <link href="https://github.com/borkdude/quickblog/2020-11-29.static-site-generator.html"/>
    <title>Hiccups and Aerodynamics: The Architecture of a Custom Static Site Generator</title>
    <updated>2020-11-29T23:59:59+00:00</updated>
    <content type="html"><![CDATA[<p>Admitting to building your own static site generator is a bit like admitting you enjoy pressure-washing videos. People look at you with a mix of mild fascination and concern, wondering why you aren't doing something more productive. Yet here we are. In my previous post, I defended the philosophy of technical self-reliance. Now, let’s talk about how this beast actually functions.</p><p>Most modern static site generators are built on a premise I find fundamentally flawed: they exist to translate text-based markup languages (usually Markdown) into HTML and CSS. If you're a non-technical writer, this is a godsend. But if you already speak fluent HTML and CSS, Markdown is a leaky, restrictive abstraction. </p><p>I don't want to write Markdown. I want direct, programmatic access to the full expressiveness of the web's native formats. I need a tool that lets me manage the complexity of code re-use through simple composition, without burying me in a pile of YAML front-matter and nested templating engines.</p><h2>The Weapon of Choice: Code as Data</h2><p>To build this, I reached for Clojure. Clojure is uniquely suited for building domain-specific languages because of Lisp’s defining superpower: <em>homoiconicity</em> (the code is represented as data structures that the language itself can manipulate).</p><p>Instead of parsing string-based HTML templates, we can represent HTML elements and inline CSS directly as native Clojure vectors and maps. The Clojure ecosystem already has a brilliant library for this called <strong>Hiccup</strong>. Here is what Hiccup looks like in action:</p><pre><code class="lang-clojure">user=&gt; &#40;html &#91;:span {:class &quot;foo&quot;} &quot;bar&quot;&#93;&#41;
&quot;&lt;span class=\&quot;foo\&quot;&gt;bar&lt;/span&gt;&quot;
</code></pre><p>Notice how clean that is. There are no trailing slash errors, no closing tag syntax, and no string interpolation bugs. It is just structured data.</p><h2>Composition via Aerodynamics</h2><p>Once your markup is represented as data, the problem of templating resolves into a problem of data composition. </p><p>To manage our site's assets and configuration, I pulled in <strong>Aero</strong>, a small Clojure library for parsing configuration files (written in EDN, Clojure's data format). Aero is excellent because it allows you to define custom tag literals. In Lisp terms, think of tag literals as compiler hooks that evaluate data structures at read-time.</p><p>By using Aero, we can write our entire website's layout and pages in static <code>.edn</code> files, version them with Git, and guarantee absolute idempotency. The compiler reads the data, evaluates our custom tags, renders the Hiccup to HTML/CSS, and writes it to the disk.</p><p>Let’s look at the asset configuration for this website's home page:</p><pre><code class="lang-clojure">{
 :type :html
 :slug &quot;/index.html&quot;
 :content #template &#91;&quot;pages/index.edn&quot; &#91;:content&#93; {:path &quot;/&quot;}&#93;
}
</code></pre><p>The heart of our composition engine is the custom <code>#template</code> tag literal. When Aero's reader encounters <code>#template</code>, it treats it like a function call. It takes three arguments:</p><ol><li><strong><code>&quot;pages/index.edn&quot;</code></strong>: The path to the template definition.</li><li><strong><code>&#91;:content&#93;</code></strong>: A pull vector (similar to Clojure's <code>get-in</code>) to extract the exact portion of the evaluated data we want.</li><li><strong><code>{:path &quot;/&quot;}</code></strong>: A map of input variables passed into the template's rendering context.</li></ol><p>Here is a look inside <code>pages/index.edn</code>:</p><pre><code class="lang-clojure">{
 :color #include &quot;../styles/color.edn&quot;
 :content
   #template &#91;&quot;../components/layout.edn&quot;
              &#91;:content&#93;
              {:title &quot;home&quot;
               :body #ref &#91;:body&#93;}&#93;
 :body
   &#91;:div
     {:style
       #css {:display :flex
             :flex-direction :column
             :justify-content :flex-start
             :align-items :flex-start}}
   &#91;:div
     {:style
       #css {:font-size &quot;50px&quot;
             :font-weight 700
             :color #ref &#91;:color :yellow&#93;}}
   &quot;Hi. I'm Adam Tait.&quot;&#93;&#93;
}
</code></pre><p>Notice how we compose the layout. The <code>:content</code> key calls the layout template, passing the <code>:body</code> of our home page as an input variable via the <code>#ref</code> literal. The <code>#css</code> tag translates Clojure maps into inline style strings. It is simple, explicit, and lacks any magical "black box" behavior.</p><h2>Simplicity and Its Discontents</h2><p>In his famous talk, <em><a href='https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/AreWeThereYet.md'>Are We There Yet?</a></em>, Rich Hickey makes a crucial distinction between "simple" (unentangled) and "easy" (near at hand). </p><p>Most modern web frameworks are <em>easy</em>—you run <code>npx create-next-app</code> and you instantly have a working site. But they are not <em>simple</em>. They bring along a staggering amount of incidental complexity—Webpack configurations, Babel steps, node_modules folders the size of small planets—that you must eventually debug.</p><p>The mathematician Alfred North Whitehead once wrote:<blockquote><p> "Seek simplicity, and distrust it."  </p></blockquote>Our custom EDN/Hiccup approach does not hide complexity; it lays it bare. There is no magic under the hood. You have direct access to the raw building blocks of the web, structured as immutable data. </p><p>Is this a poor abstraction? For many, yes. It requires you to write Lisp syntax to build a webpage. But by building a tool that builds the generator, I created a system I deeply understand. When a bug occurs, I don't file a GitHub issue; I just fix my code.</p>]]></content>
  </entry>
  <entry>
    <id>https://github.com/borkdude/quickblog/2020-11-24.build-your-own-software.html</id>
    <link href="https://github.com/borkdude/quickblog/2020-11-24.build-your-own-software.html"/>
    <title>Build Your Own Software</title>
    <updated>2020-11-24T23:59:59+00:00</updated>
    <content type="html"><![CDATA[<p>The prevailing, unquestioned orthodoxy of modern software engineering is simple: <em>never build what you can buy, rent, or copy-paste from GitHub.</em> If you dare to suggest writing your own library, let alone your own static site generator, you will be met with the kind of looks usually reserved for people who suggest returning to the gold standard. </p><p>Yet, I built this blog using a completely custom, handcrafted static site generator. Why? Because I am deeply, unapologetically biased toward building my own software systems. </p><p>In this post, I want to mount a defense of what the industry disparagingly calls Not Invented Here (NIH) syndrome. The next post will cover the actual technical details of what I built. For now, let’s talk about the <em>why</em>.</p><h2>The Hidden Costs of Other People's Land</h2><p>In software, dependencies are like renting an apartment. It looks great on paper—someone else handles the plumbing and maintains the roof. But eventually, you discover the landlord has some deeply eccentric house rules, the plumbing is made of papier-mâché, and they can raise the rent or evict you on a whim. </p><p>My architectural thinking has been heavily shaped by <a href='https://github.com/matthiasn/talk-transcripts/tree/master/Hickey_Rich'>Rich Hickey's talks</a> (for a quick digest of his philosophy, Daniel Higginbotham’s <a href='http://www.flyingmachinestudios.com/programming/the-unofficial-guide-to-rich-hickeys-brain/'>unofficial guide</a> is fantastic). Hickey’s core lesson is that we should possess a healthy fear of systems we don't understand, written by people whose goals and biases we don't share.</p><p>Every time you pull in a heavy third-party framework or outsource a capability to a SaaS provider, you inherit their future roadmap, their bugs, and their licensing decisions. We’ve all been there: you invest weeks learning a complex new tool, only to hit a wall because its core abstraction makes your simple use-case incredibly difficult. Suddenly, instead of building your product, you're spelunking through the GitHub issues of a foreign repository, praying for a workaround.</p><p>With SaaS, the risks are even more immediate. You aren't just relying on their code; you're relying on their network stability, their database team, and their business model. When their server goes down, your system goes down with it, and you're left with no recourse but to refresh their status page.</p><h2>The Cognitive Trap (Or: This is Water)</h2><p>There is a deeper, more insidious risk to depending on other people's abstractions: they capture your mind.</p><p>In his famous graduation speech, <a href='https://fs.blog/2012/04/david-foster-wallace-this-is-water/'>"This is Water"</a>, David Foster Wallace tells the story of two young fish swimming along who meet an older fish. The older fish nods and says, "Morning, boys. How's the water?" The two young fish swim on for a bit, and then eventually one looks at the other and goes, "What the hell is water?"</p><p>The longer and deeper you submerge your mind in a specific framework or tool, the more your thinking begins to resemble the limits of that environment. If you only write React, every problem looks like a component lifecycle issue. If you only use static site generators built around markdown, you begin to accept markdown's limitations as the natural laws of web publishing. You forget that other classes of design and entirely different paradigms of simplicity even exist.</p><h2>Ken Thompson is Modern, Again</h2><p>At this stage in my career, I’ve stopped chasing the industry's flavor-of-the-month framework. Instead, I find myself returning to <a href='https://en.wikipedia.org/wiki/Unix_philosophy'>Ken Thompson's UNIX philosophy</a>: build small, sharp, reliable tools that do one thing well and compose together.</p><p>Earlier in my career, I wasted countless hours learning broad but shallow frameworks, chasing the latest hypetrain only to watch it derail a year later. Mastery doesn't come from memorizing the APIs of ephemeral libraries. Mastery comes from deep, compounding knowledge of fundamental principles. </p><p>Building your own small tools is slow in the short term, but it carries a massive long-term dividend. The more small tools you construct, the larger your mental library of design patterns and clean code becomes. You can compose these simple components to solve massive, complex problems without inheriting the incidental complexity of a monolithic framework.</p><p>Software mastery isn't about writing perfect code; it's about practicing the art of composition. And to compose effectively, you must understand the notes you're playing.</p><h2>Further Reading</h2><p>If you want to dive deeper into the intellectual foundations of this approach, I highly recommend:</p><ul><li><strong><a href='https://github.com/matthiasn/talk-transcripts/tree/master/Hickey_Rich'>Rich Hickey's Talk Transcripts</a>:</strong> A masterclass in software design, simplicity, and state.</li><li><strong><a href='http://www.flyingmachinestudios.com/programming/the-unofficial-guide-to-rich-hickeys-brain/'>The Unofficial Guide to Rich Hickey's Brain</a>:</strong> Daniel Higginbotham's excellent synthesis of Hickey's core philosophy.</li></ul>]]></content>
  </entry>
</feed>
