<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Software Development on Pauls Blog</title><link>https://prule.github.io/pauls-blog/page/software/</link><description>Recent content in Software Development on Pauls Blog</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://prule.github.io/pauls-blog/page/software/index.xml" rel="self" type="application/rss+xml"/><item><title>A Game Plan for Product and Software Development</title><link>https://prule.github.io/pauls-blog/page/software/game-plan/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/game-plan/</guid><description>&lt;h2 id="a-game-plan-for-product-and-software-development"&gt;A Game Plan for Product and Software Development&lt;/h2&gt;
&lt;h3 id="the-premise"&gt;The Premise&lt;/h3&gt;
&lt;p&gt;Most software problems are not technical. A team that consistently delivers working software, adapts to changing requirements, and maintains the capacity to keep improving over time is not doing so because they chose the right framework or the right database. They are doing so because they have internalised a coherent set of practices that compound — each one making the others more effective, and all of them together producing a system that remains comprehensible, changeable, and reliable over its lifetime.&lt;/p&gt;</description></item><item><title>A Pyramid Principle Structure - Software Engineering Excellence</title><link>https://prule.github.io/pauls-blog/page/software/software-engineering-excellence/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/software-engineering-excellence/</guid><description>&lt;blockquote&gt;
&lt;p&gt;This attempts to apply the McKinsey Pyramid Principle to these software development thoughts and practices.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="notice info"&gt;
 &lt;div class="notice-title"&gt;Amazon Affiliates Link&lt;/div&gt;
 &lt;div class="notice-content"&gt;
 Buy on Amazon &lt;a href="https://amzn.to/4uooYee" target="_blank" rel="noopener"&gt;The Pyramid Principle&lt;/a&gt;
 &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="software-engineering-excellence--a-pyramid-principle-structure"&gt;Software Engineering Excellence — A Pyramid Principle Structure&lt;/h2&gt;
&lt;p&gt;The McKinsey Pyramid Principle organises thinking from the top down: a single governing idea, supported by a small number of mutually exclusive and collectively exhaustive arguments, each supported by evidence and reasoning. What follows applies that structure to everything covered in this series.&lt;/p&gt;</description></item><item><title>Breaking Down Problems</title><link>https://prule.github.io/pauls-blog/page/software/breaking-down-problems/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/breaking-down-problems/</guid><description>&lt;h2 id="breaking-down-problems--decomposition-as-a-core-skill"&gt;Breaking Down Problems — Decomposition as a Core Skill&lt;/h2&gt;
&lt;h3 id="why-its-a-skill-not-a-step"&gt;Why It&amp;rsquo;s a Skill, Not a Step&lt;/h3&gt;
&lt;p&gt;Decomposition is often treated as a planning activity — something that happens in a refinement session, produces a list of tickets, and is then considered done. The tickets get handed to developers who implement them. This misses what decomposition actually is.&lt;/p&gt;
&lt;p&gt;Decomposition is a continuous cognitive skill exercised throughout development — in planning, yes, but also when sitting down to write a test, when deciding where a class boundary should be, when a piece of code resists being understood. The developer who can break a problem down well works differently at every level: they write smaller functions, cleaner interfaces, more focused tests, and smaller PRs. The skill compounds across every scale of work.&lt;/p&gt;</description></item><item><title>Clean Architecture</title><link>https://prule.github.io/pauls-blog/page/software/clean-architecture/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/clean-architecture/</guid><description>&lt;h2 id="clean-architecture"&gt;Clean Architecture&lt;/h2&gt;
&lt;h3 id="the-core-idea"&gt;The Core Idea&lt;/h3&gt;
&lt;p&gt;Clean Architecture, articulated by Robert C. Martin (Uncle Bob), is a way of organising code so that &lt;strong&gt;business logic is the centre of the system&lt;/strong&gt; and everything else — frameworks, databases, UIs, external services — is a detail that can be swapped out or tested independently.&lt;/p&gt;
&lt;p&gt;The central rule is the &lt;strong&gt;Dependency Rule&lt;/strong&gt;: source code dependencies can only point &lt;em&gt;inward&lt;/em&gt;. Outer layers know about inner layers; inner layers know nothing about outer layers.&lt;/p&gt;</description></item><item><title>Coding Tips — Principles in Practice</title><link>https://prule.github.io/pauls-blog/page/software/coding-tips/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/coding-tips/</guid><description>&lt;h2 id="coding-tips--principles-in-practice"&gt;Coding Tips — Principles in Practice&lt;/h2&gt;
&lt;p&gt;These tips are the everyday expression of everything covered in this series — the micro-decisions that, made consistently, produce code that is comprehensible, maintainable, and a pleasure to work in.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="control-flow"&gt;Control Flow&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Return early to reduce nesting.&lt;/strong&gt;
Every level of nesting is a level of context the reader must hold in working memory. Guard clauses that return or throw early eliminate the nesting that builds up around validation and precondition checks.&lt;/p&gt;</description></item><item><title>Cognitive Load</title><link>https://prule.github.io/pauls-blog/page/software/cognitive-load/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/cognitive-load/</guid><description>&lt;h2 id="cognitive-load--the-hidden-cost-of-complexity"&gt;Cognitive Load — The Hidden Cost of Complexity&lt;/h2&gt;
&lt;h3 id="what-it-is"&gt;What It Is&lt;/h3&gt;
&lt;p&gt;Cognitive load is the amount of mental effort required to hold and process information at any given moment. The concept comes from educational psychology — John Sweller&amp;rsquo;s work in the 1980s on how people learn — but it maps directly onto software development, where the primary activity is understanding complex systems well enough to change them safely.&lt;/p&gt;
&lt;p&gt;Working memory is the bottleneck. Humans can hold roughly four to seven distinct pieces of information in working memory simultaneously. When that limit is exceeded, comprehension degrades, mistakes increase, and progress slows. The developer who can&amp;rsquo;t hold the relevant parts of a system in their head at once starts to make changes based on incomplete understanding — which is where bugs come from and where confidence erodes.&lt;/p&gt;</description></item><item><title>Collaborative Development</title><link>https://prule.github.io/pauls-blog/page/software/pairing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/pairing/</guid><description>&lt;h2 id="collaborative-development--beyond-strict-pair-programming"&gt;Collaborative Development — Beyond Strict Pair Programming&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;(updated to include mentoring and teaching)&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="the-spectrum-of-collaboration"&gt;The Spectrum of Collaboration&lt;/h3&gt;
&lt;p&gt;Traditional pair programming has a specific form: two people, one keyboard, one screen, switching between driver and navigator roles. The research behind it is solid — it produces fewer defects, spreads knowledge, and keeps both people focused. But the strict form has real costs: it&amp;rsquo;s cognitively intense, it doesn&amp;rsquo;t suit all personality types, and it treats every problem as requiring the same level of collaboration.&lt;/p&gt;</description></item><item><title>Configurable Systems</title><link>https://prule.github.io/pauls-blog/page/software/configurable-systems/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/configurable-systems/</guid><description>&lt;h2 id="configurable-systems-and-the-right-abstraction"&gt;Configurable Systems and the Right Abstraction&lt;/h2&gt;
&lt;h3 id="the-core-idea"&gt;The Core Idea&lt;/h3&gt;
&lt;p&gt;There is a class of problem where the right move is not to write another solution, but to recognise that you&amp;rsquo;ve already written several solutions to the same underlying problem and extract the pattern. Instead of building bespoke code repeatedly, you build a framework that models the &lt;em&gt;shape&lt;/em&gt; of the problem — and then configure it for each specific instance.&lt;/p&gt;
&lt;p&gt;The payoff is significant: new instances of the problem become configuration rather than code. The framework is tested once deeply; each configuration gets a shallow test. Developers working with it operate at the level of the domain concept — star schema, workflow, form, pipeline — rather than the level of implementation detail.&lt;/p&gt;</description></item><item><title>Continuous Integration and Delivery</title><link>https://prule.github.io/pauls-blog/page/software/continuous-integration/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/continuous-integration/</guid><description>&lt;h2 id="continuous-integration-and-delivery"&gt;Continuous Integration and Delivery&lt;/h2&gt;
&lt;h3 id="the-problem-with-infrequent-integration"&gt;The Problem with Infrequent Integration&lt;/h3&gt;
&lt;p&gt;Imagine two developers working independently on the same codebase for two weeks. They&amp;rsquo;ve each made hundreds of changes across dozens of files. On day fourteen they attempt to merge. The merge itself might be mechanical — resolving conflicting edits line by line — but the harder problem is behavioural: their changes made assumptions about the system that are no longer true. Tests fail in ways that are hard to diagnose because the surface area of change is enormous. Nobody is sure whether a failure was introduced yesterday or ten days ago.&lt;/p&gt;</description></item><item><title>Decision Making</title><link>https://prule.github.io/pauls-blog/page/software/decision-making/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/decision-making/</guid><description>&lt;h2 id="decision-making-under-uncertainty"&gt;Decision Making Under Uncertainty&lt;/h2&gt;
&lt;h3 id="the-problem-with-deciding-too-early"&gt;The Problem With Deciding Too Early&lt;/h3&gt;
&lt;p&gt;Architecture decisions are made at the worst possible time. At the start of a project — when the key decisions feel most urgent — the team has the least information. The domain isn&amp;rsquo;t fully understood, the usage patterns are hypothetical, the team hasn&amp;rsquo;t discovered the pain points yet. And yet this is precisely when decisions are made that will shape the system for years.&lt;/p&gt;</description></item><item><title>Domain Modelling</title><link>https://prule.github.io/pauls-blog/page/software/domain-modelling/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/domain-modelling/</guid><description>&lt;h2 id="domain-modelling-and-rich-domain-models"&gt;Domain Modelling and Rich Domain Models&lt;/h2&gt;
&lt;h3 id="the-core-idea"&gt;The Core Idea&lt;/h3&gt;
&lt;p&gt;Domain modelling is the practice of capturing the concepts, rules, and behaviour of a business problem in code. A &lt;strong&gt;rich domain model&lt;/strong&gt; goes further — it places business logic &lt;em&gt;inside&lt;/em&gt; the domain objects themselves, rather than in surrounding service or use case classes.&lt;/p&gt;
&lt;p&gt;The opposite of a rich domain model is an &lt;strong&gt;anaemic domain model&lt;/strong&gt; — objects that are little more than bags of getters and setters, with all logic extracted into services. Martin Fowler describes the anaemic model as an anti-pattern: it has the structure of OOP without the substance.&lt;/p&gt;</description></item><item><title>Feature Flags and Trunk-Based Development</title><link>https://prule.github.io/pauls-blog/page/software/feature-flags/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/feature-flags/</guid><description>&lt;h2 id="feature-flags-and-trunk-based-development"&gt;Feature Flags and Trunk-Based Development&lt;/h2&gt;
&lt;h3 id="the-problem-they-solve-together"&gt;The Problem They Solve Together&lt;/h3&gt;
&lt;p&gt;Continuous Integration demands frequent integration to mainline. Continuous Delivery demands that mainline is always releasable. These two commitments create an immediate tension: what do you do with a feature that takes two weeks to build? You can&amp;rsquo;t keep it on a branch for two weeks — that defeats CI. But you can&amp;rsquo;t have a half-built feature in production — that defeats CD.&lt;/p&gt;</description></item><item><title>Keeping Dependencies Up to Date with Renovate</title><link>https://prule.github.io/pauls-blog/page/software/updating-dependencies/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/updating-dependencies/</guid><description>&lt;h2 id="keeping-dependencies-up-to-date-with-renovate"&gt;Keeping Dependencies Up to Date with Renovate&lt;/h2&gt;
&lt;h3 id="the-problem"&gt;The Problem&lt;/h3&gt;
&lt;p&gt;Every application sits on a foundation of dependencies — libraries, frameworks, build tools, base images. That foundation is not static. Dependencies release updates continuously: new features, performance improvements, bug fixes, and critically, security patches.&lt;/p&gt;
&lt;p&gt;The default human response to this is inertia. Updating dependencies takes time, updates occasionally break things, and there is always something more immediately valuable to work on. So updates get deferred. Weeks become months, months become years, and the gap between what you&amp;rsquo;re running and what&amp;rsquo;s current grows quietly in the background.&lt;/p&gt;</description></item><item><title>Managing Complexity</title><link>https://prule.github.io/pauls-blog/page/software/complexity/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/complexity/</guid><description>&lt;h2 id="managing-complexity--keeping-systems-comprehensible"&gt;Managing Complexity — Keeping Systems Comprehensible&lt;/h2&gt;
&lt;h3 id="the-two-kinds-of-complexity"&gt;The Two Kinds of Complexity&lt;/h3&gt;
&lt;p&gt;Fred Brooks introduced the distinction in his 1986 paper &lt;em&gt;No Silver Bullet&lt;/em&gt;. It remains one of the most useful ideas in software engineering.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Essential complexity&lt;/strong&gt; is inherent in the problem itself. A tax calculation system is complex because tax law is complex. A trading platform has complex rules because financial markets have complex rules. A healthcare system handles nuanced workflows because healthcare is genuinely nuanced. This complexity cannot be removed — it can only be managed, modelled, and represented as clearly as possible. Fighting essential complexity is fighting the domain.&lt;/p&gt;</description></item><item><title>Modelling Domains in Kotlin With Value Objects</title><link>https://prule.github.io/pauls-blog/page/software/kotlin-value-objects/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/kotlin-value-objects/</guid><description>&lt;h2 id="modelling-domains-in-kotlin-with-value-objects"&gt;Modelling Domains in Kotlin With Value Objects&lt;/h2&gt;
&lt;h3 id="the-problem-with-primitives"&gt;The Problem With Primitives&lt;/h3&gt;
&lt;p&gt;Every domain has concepts that primitives can represent but cannot express. An email address is a &lt;code&gt;String&lt;/code&gt;, but not every &lt;code&gt;String&lt;/code&gt; is an email address. An order total is a &lt;code&gt;BigDecimal&lt;/code&gt;, but not every &lt;code&gt;BigDecimal&lt;/code&gt; is a valid order total — it shouldn&amp;rsquo;t be negative, it should have a defined currency, and it shouldn&amp;rsquo;t be mixed with a price in a different currency. A user ID is an &lt;code&gt;Int&lt;/code&gt;, but it shouldn&amp;rsquo;t be added to a product ID, compared to a quantity, or passed where an order ID is expected.&lt;/p&gt;</description></item><item><title>Observability</title><link>https://prule.github.io/pauls-blog/page/software/observability/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/observability/</guid><description>&lt;h2 id="observability--understanding-your-system-in-production"&gt;Observability — Understanding Your System in Production&lt;/h2&gt;
&lt;h3 id="why-observability-is-a-design-concern"&gt;Why Observability is a Design Concern&lt;/h3&gt;
&lt;p&gt;Most teams treat observability as something added after the fact — sprinkle some log statements in, wire up a metrics library, declare the system observable. The result is a production system that generates enormous volumes of data while remaining fundamentally opaque when something goes wrong. The logs exist but don&amp;rsquo;t answer the question being asked. The metrics show something is wrong but not where or why. The traces are missing for the one request that caused the incident.&lt;/p&gt;</description></item><item><title>Reading and Understanding Unfamiliar Codebases</title><link>https://prule.github.io/pauls-blog/page/software/reading-code/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/reading-code/</guid><description>&lt;h2 id="reading-and-understanding-unfamiliar-codebases"&gt;Reading and Understanding Unfamiliar Codebases&lt;/h2&gt;
&lt;h3 id="why-its-a-distinct-skill"&gt;Why It&amp;rsquo;s a Distinct Skill&lt;/h3&gt;
&lt;p&gt;Most developer education focuses on writing code. Reading code — particularly large, unfamiliar codebases written by people you&amp;rsquo;ve never met, under constraints you don&amp;rsquo;t know, solving problems you&amp;rsquo;re still discovering — is a different activity that receives almost no explicit attention.&lt;/p&gt;
&lt;p&gt;Yet it is something every developer does constantly. Joining a new team, picking up an open source library to understand its internals, inheriting a system from a team that no longer exists, returning to your own code after six months. The ability to build an accurate mental model of an unfamiliar system quickly is one of the highest-leverage skills a developer can have, and it is largely learned through trial and error rather than through deliberate practice.&lt;/p&gt;</description></item><item><title>REST and HATEOAS</title><link>https://prule.github.io/pauls-blog/page/software/rest-hateoas/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/rest-hateoas/</guid><description>&lt;h2 id="rest-and-hateoas"&gt;REST and HATEOAS&lt;/h2&gt;
&lt;h3 id="rest-representational-state-transfer"&gt;REST (Representational State Transfer)&lt;/h3&gt;
&lt;p&gt;REST is an architectural style for distributed hypermedia systems, first described by Roy Fielding in his 2000 doctoral dissertation. It&amp;rsquo;s not a protocol or standard, but a set of constraints that, when applied to a web service, produce desirable properties like scalability, simplicity, and modifiability.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The six constraints of REST:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Client-Server&lt;/strong&gt; — Concerns are separated between the UI/consumer and the data storage/logic. This allows each to evolve independently.&lt;/p&gt;</description></item><item><title>Technical Debt</title><link>https://prule.github.io/pauls-blog/page/software/tech-debt/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/tech-debt/</guid><description>&lt;h2 id="technical-debt--thinking-about-it-honestly"&gt;Technical Debt — Thinking About It Honestly&lt;/h2&gt;
&lt;h3 id="the-metaphor-and-its-limits"&gt;The Metaphor and Its Limits&lt;/h3&gt;
&lt;p&gt;Ward Cunningham coined the term &amp;ldquo;technical debt&amp;rdquo; in 1992 to describe a specific situation: shipping code that isn&amp;rsquo;t quite right in order to learn something from real users, with the intention of going back to refactor once that learning has happened. The debt metaphor was deliberate — like financial debt, it accrues interest. The longer you leave the suboptimal code in place, the more every subsequent change that touches it costs.&lt;/p&gt;</description></item><item><title>Technical Documentation — What's Worth Writing Down</title><link>https://prule.github.io/pauls-blog/page/software/tech-docs/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/tech-docs/</guid><description>&lt;h2 id="technical-documentation--whats-worth-writing-down"&gt;Technical Documentation — What&amp;rsquo;s Worth Writing Down&lt;/h2&gt;
&lt;h3 id="the-documentation-paradox"&gt;The Documentation Paradox&lt;/h3&gt;
&lt;p&gt;Documentation has a reputation problem in both directions. Teams that write too little leave critical knowledge locked in individuals&amp;rsquo; heads, where it fades and eventually disappears when people move on. Teams that write too much produce documents that are immediately out of date, never read, and actively misleading — giving readers false confidence that they understand something they don&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;The failure mode is treating documentation as a uniform activity — either you document everything or you document nothing. The more useful question is: what specific knowledge needs to exist in written form, for whom, and why? Different answers produce radically different kinds of documentation, each with different value and different maintenance costs.&lt;/p&gt;</description></item><item><title>Test-Driven Development</title><link>https://prule.github.io/pauls-blog/page/software/tdd/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/tdd/</guid><description>&lt;h2 id="test-driven-development-tdd"&gt;Test-Driven Development (TDD)&lt;/h2&gt;
&lt;h3 id="the-core-idea"&gt;The Core Idea&lt;/h3&gt;
&lt;p&gt;TDD inverts the traditional write-code-then-test workflow. You write a failing test &lt;em&gt;before&lt;/em&gt; writing the implementation, then write the minimum code to make it pass, then clean up. The tests don&amp;rsquo;t just verify correctness after the fact — they drive the design of the code itself.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="the-red-green-refactor-cycle"&gt;The Red-Green-Refactor Cycle&lt;/h3&gt;
&lt;p&gt;This is the heartbeat of TDD. Every small increment of work follows three steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Red&lt;/strong&gt; — Write a test for behaviour that doesn&amp;rsquo;t exist yet. Run it. It must fail. If it passes, either the behaviour already exists or the test is wrong.&lt;/p&gt;</description></item><item><title>The Spirit of the Craft</title><link>https://prule.github.io/pauls-blog/page/software/manifesto/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/manifesto/</guid><description>&lt;h1 id="the-spirit-of-the-craft"&gt;The Spirit of the Craft&lt;/h1&gt;
&lt;p&gt;These documents represent a living collection of my thoughts on building software. While they cover varied topics—from architectural patterns to testing strategies—they are unified by a single perspective: &lt;strong&gt;Software is a human-centric endeavor.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;spirit&amp;rdquo; of this collection can be distilled into five core convictions:&lt;/p&gt;
&lt;h3 id="1-the-primary-constraint-is-human-cognition"&gt;1. The Primary Constraint is Human Cognition&lt;/h3&gt;
&lt;p&gt;We build systems that eventually exceed our ability to understand them. Most of our tools—TDD, Clean Architecture, Decomposition—are not about &amp;ldquo;correctness&amp;rdquo; in a vacuum; they are defensive measures against &lt;strong&gt;cognitive load&lt;/strong&gt;. We write code for the reader, not the compiler, because the hardest part of software is keeping the mental model in our heads long enough to change it safely.&lt;/p&gt;</description></item><item><title>Writing Code for the Reader</title><link>https://prule.github.io/pauls-blog/page/software/readable-code/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/page/software/readable-code/</guid><description>&lt;h2 id="writing-code-for-the-reader"&gt;Writing Code for the Reader&lt;/h2&gt;
&lt;h3 id="the-compiler-is-not-your-audience"&gt;The Compiler Is Not Your Audience&lt;/h3&gt;
&lt;p&gt;Code is written once. It is read many times — by the next developer to work in the area, by a colleague reviewing the PR, by you returning to it six months later with the context entirely gone. The compiler will accept almost anything that is syntactically correct. The human reader is far more demanding, and far more important.&lt;/p&gt;</description></item></channel></rss>