<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"><channel><title>Laws of Software Engineering</title><link>https://lawsofsoftwareengineering.com/</link><description>A collection of principles and patterns that shape software systems, teams, and decisions.</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Mon, 08 Jun 2026 14:43:12 +0200</lastBuildDate><atom:link href="https://lawsofsoftwareengineering.com/" rel="self" type="application/rss+xml"/><item><title>Conway's Law</title><link>https://lawsofsoftwareengineering.com/laws/conways-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/conways-law/</guid><description>Organizations design systems that mirror their own communication structure.</description><content:encoded><![CDATA[<p>Conway&rsquo;s Law states that <strong>software systems reflect the communication structure of the organization that builds them</strong>. A company with separate frontend, backend, and database departments will likely produce a three-tier architecture. Small, distributed teams tend to produce modular service architectures, while large, collocated teams tend to build monoliths.</p>
<p>To mitigate this, teams can use the <strong>Inverse Conway Maneuver</strong>: intentionally structuring the organization to match the desired software architecture.</p>
<ul><li>The architecture of software systems often mirrors the organization's org chart or team structure.</li><li>If your company is organized in silos, you might end up with siloed software modules that don't communicate well, reflecting those barriers.</li><li>To achieve a desired software architecture (e.g., microservices), you might need to restructure teams accordingly, because teams build software aligned with their communication paths.</li><li>When starting a project, realize that how you split teams or departments will likely lead to software boundaries at the same places.</li></ul>]]></content:encoded></item><item><title>Premature Optimization (Knuth's Optimization Principle)</title><link>https://lawsofsoftwareengineering.com/laws/premature-optimization/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/premature-optimization/</guid><description>Premature optimization is the root of all evil.</description><content:encoded><![CDATA[<p>Knuth&rsquo;s Optimization Principle captures a fundamental trade-off in software engineering: performance improvements often increase complexity. Applying that trade-off before understanding where performance actually matters leads to unreadable systems.</p>
<p>Early in development, your focus should be on a clear design. If you optimize too soon, you might introduce bugs or inflexibility, all to speed up parts of the code that may not even be bottlenecks. It&rsquo;s often cited that 20% of the code may consume 80% of the execution time (a Pareto-like notion). Optimizing anything outside that critical 20% is wasted effort and adds risk. The principle advises writing simple code, then profiling and improving only the parts that truly need it.</p>
<ul><li>Most code doesn't run in performance-critical hotspots, so obsessing over micro-optimizations everywhere wastes time and makes code harder to read and maintain.</li><li>According to Knuth, we should forget about small efficiencies about 97% of the time, and focus on clean design and correct functionality.</li><li>Optimized code is often more complex or less readable. If done prematurely, you incur this cost even when it's unnecessary.</li><li>Get it working correctly first, then make it fast, then make it pretty.</li></ul>]]></content:encoded></item><item><title>Hyrum's Law</title><link>https://lawsofsoftwareengineering.com/laws/hyrums-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/hyrums-law/</guid><description>With a sufficient number of API users, all observable behaviors of your system will be depended on by somebody.</description><content:encoded><![CDATA[<p>Hyrum&rsquo;s Law describes a phenomenon where the boundary between a software&rsquo;s documented interface and its implementation details gets blurred in practice. No matter what you promise in an API contract, if people use your system enough, they will depend on behaviors you never officially supported.</p>
<p>Over time, the implementation becomes the interface. Every observable trait, performance characteristic, or error code might be assumed by someone. This drastically limits freedom to change the system, as even internal changes can break users who wrote code around the old behavior.</p>
<ul><li>As the user count grows, everything your system does becomes a dependency point. Even unintended side effects or bugs can become 'features' that someone's workflow depends on.</li><li>Hyrum's Law warns maintainers that any change can break something for someone. Consumers may have integrated your API in ways you didn't expect, including relying on timing, error messages, formatting, etc.</li><li>The actual contract of your software isn't just the official API/spec; it's the exact behavior as observed in the wild. The contract can even be something informal, such as the UI that your users are used to.</li></ul>]]></content:encoded></item><item><title>The Boy Scout Rule</title><link>https://lawsofsoftwareengineering.com/laws/boy-scout-rule/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/boy-scout-rule/</guid><description>Leave the code better than you found it.</description><content:encoded><![CDATA[<p>The Boy Scout Rule basically means: leave the code better than you found it. In practice, it&rsquo;s not about doing big-bang rewrites or achieving perfection in one go. Instead, it&rsquo;s about constant and incremental improvements.</p>
<p>Whenever a developer encounters a piece of code, whether adding a new feature or hunting down a bug, they take the opportunity to polish something nearby. For example, if there&rsquo;s a confusing function name, you rename it clearly. If you notice some duplicated code, you refactor it into a single helper. If a test case is missing for a critical method, you add it.</p>
<p>These are often small changes that might take only a few extra minutes, but they compound over time.</p>
<ul><li>Don’t leave bad things rot in a project. This means take a moment to refactor or fix at least one small thing in the area you’re working on. It can include anything from variable names to simplifying logic.</li><li>A cleaner codebase is easier to read, work with, and extend. This improves project maintainability and reduces technical debt.</li><li>When every developer follows this rule, it creates a culture of ownership in the code. Teams collectively feel responsible for code quality.</li></ul>]]></content:encoded></item><item><title>YAGNI (You Aren't Gonna Need It)</title><link>https://lawsofsoftwareengineering.com/laws/yagni/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/yagni/</guid><description>Don't add functionality until it is necessary.</description><content:encoded><![CDATA[<p>YAGNI captures a core philosophy of agile development: don&rsquo;t write code for features that haven&rsquo;t been requested or aren&rsquo;t immediately needed.</p>
<p>If you&rsquo;re implementing Module A and think &ldquo;in the future we might need Module B to do X, so I&rsquo;ll code some hooks for that now,&rdquo; YAGNI advises against it because that future feature may never come or may change drastically.</p>
<p>This principle directly fights over-engineering. To apply YAGNI successfully, teams rely on confidence in refactoring. You defer a feature only if you trust you can add it later at low cost.</p>
<p>Agile methods provide that safety net via good test coverage, refactoring tools, and continuous integration. YAGNI pushes the problem of complexity to when it&rsquo;s actually needed.</p>
<ul><li>YAGNI is here to remind developers to focus on current tasks rather than implementing features that aren’t needed now.</li><li>Anticipating future needs often leads to over-engineering, and this adds complexity and maintenance issues.</li><li>YAGNI encourages iterative development. You implement minimal solutions and refine or extend them when needed.</li></ul>]]></content:encoded></item><item><title>Brooks's Law</title><link>https://lawsofsoftwareengineering.com/laws/brooks-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/brooks-law/</guid><description>Adding manpower to a late software project makes it later.</description><content:encoded><![CDATA[<p>Brooks&rsquo;s Law challenges the belief that a software development effort is perfectly divisible among people. In reality, adding a person to a project incurs training costs and increases the number of communication paths. This can outweigh that person&rsquo;s contribution for a while.</p>
<p>If a project is already late, adding new developers can cause further delays as they learn the system and may introduce new bugs. Brooks illustrated this with the analogy: &ldquo;You cannot get a baby in one month by impregnating nine women.&rdquo; The law doesn&rsquo;t say adding people never helps, but as a response to lateness, it&rsquo;s usually counterproductive.</p>
<ul><li>Simply throwing more developers at a project that's running behind schedule usually slows it down further initially.</li><li>New people take time to get up to speed, consuming existing team members' time for training and coordination, which reduces overall productivity.</li><li>Instead of hoping manpower will solve slippage, adjust the scope or timeline. Be wary of 'just hire more coders' as a solution to lateness.</li></ul>]]></content:encoded></item><item><title>Gall's Law</title><link>https://lawsofsoftwareengineering.com/laws/galls-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/galls-law/</guid><description>A complex system that works is invariably found to have evolved from a simple system that worked.</description><content:encoded><![CDATA[<p>John Gall observed that <strong>successful complex systems start as successful simple systems</strong>. If you attempt to create a complex system from the beginning, it usually doesn&rsquo;t work because there are too many unknowns you haven&rsquo;t validated.</p>
<p>Instead, start with a simple architecture and learn from real-world usage. Add features or complexity incrementally, ensuring each change still works. When you start with a small, functional core, you can validate assumptions early. Every new capability added incrementally is tested against reality, forcing the system to adapt.</p>
<ul><li>Don't build a complex system from scratch. Instead, make a simple version that works, then iterate and add complexity. This approach serves as a launching pad for experimentation and innovation.</li><li>Successful large systems often grow organically. A fully designed-from-scratch complex system usually fails because you can't foresee all interactions.</li><li>This law argues for creating a Minimum Viable Product (MVP), a simple working core, and then growing it, rather than a big-bang approach.</li><li>Systems that grow tend to adapt and handle complexity better because they've been tested and refined at each stage. An overly complex initial design can break when something unexpected happens.</li></ul>]]></content:encoded></item><item><title>The Law of Leaky Abstractions</title><link>https://lawsofsoftwareengineering.com/laws/law-of-leaky-abstractions/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/law-of-leaky-abstractions/</guid><description>All non-trivial abstractions, to some degree, are leaky.</description><content:encoded><![CDATA[<p>This law observes that in complex systems, the abstractions we create, meant to hide complexity, <em>inevitably fail in some scenarios</em>, revealing the underlying complexity to the programmer.</p>
<p>For example, consider an ORM (object-relational mapper) that lets you treat database entries as objects. Most of the time it works, but occasionally you hit a case where performance is terrible and you have to think about the SQL queries being generated. The abstraction &ldquo;leaks&rdquo; details of the database.</p>
<p>The law isn&rsquo;t saying abstractions are bad. They are essential. But it reminds us that <strong>one must be prepared for when they break</strong>.</p>
<ul><li>No matter how well-designed, abstractions (libraries, frameworks, etc.) have edge cases that depend on internal details.</li><li>Developers should understand that using a high-level tool doesn't absolve them from knowing what's happening underneath, at least at a basic level.</li><li>"Leaky" means you might encounter performance issues, bugs, or behavior that force you to consider the underlying system (e.g., networking, OS) on which the abstraction sits.</li><li>When creating abstractions, strive to minimize leakage and document the cases in which it might break.</li></ul>]]></content:encoded></item><item><title>Tesler's Law (Conservation of Complexity)</title><link>https://lawsofsoftwareengineering.com/laws/teslers-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/teslers-law/</guid><description>Every application has an inherent amount of irreducible complexity that can only be shifted, not eliminated.</description><content:encoded><![CDATA[<p>Tesler&rsquo;s Law, also known as the Law of Conservation of Complexity, states that for any system, there is a certain amount of complexity that cannot be removed; it&rsquo;s inherent to the problem. The key is <strong>who deals with it</strong>.</p>
<p>If you design software that&rsquo;s very simple for the user, it likely means the software is doing a lot of complex work under the hood. If you make the software very simple internally, it might dump complexity on the user (e.g., requiring many manual steps).</p>
<p>Tesler&rsquo;s Law encourages designers to <strong>move complexity away from the user experience</strong> whenever possible.</p>
<ul><li>Good design often requires that developers absorb most of the complexity (through smart defaults, algorithms, etc.) so that the user's interaction is simpler.</li><li>If your UI requires the user to manage many settings or steps, you've conserved complexity in the wrong place (on the user side). Often, it's better to design the product to manage that complexity internally.</li><li>Good design often hides complexity without eliminating it by handling it internally.</li></ul>]]></content:encoded></item><item><title>CAP Theorem</title><link>https://lawsofsoftwareengineering.com/laws/cap-theorem/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/cap-theorem/</guid><description>A distributed system can guarantee only two of: consistency, availability, and partition tolerance.</description><content:encoded><![CDATA[<p>The CAP theorem states that a distributed system cannot simultaneously provide all three guarantees: <strong>Consistency</strong> (all nodes see the same data), <strong>Availability</strong> (every request receives a response), and <strong>Partition Tolerance</strong> (the system operates despite network failures).</p>
<p>Since network partitions are unavoidable in practice, systems must be partition-tolerant. This means choosing between consistency and availability when designing distributed architectures. The CAP theorem is a useful starting point, though it is a simplification that doesn&rsquo;t cover all aspects of the design space.</p>
<ul><li>A distributed system can only guarantee two out of three things at once: Consistency, Availability, and Partition Tolerance. When the network is healthy you can have all three, but the moment a partition happens, you have to give one up.</li><li>When a network split occurs, you face a choice: stay consistent (every node agrees, but some requests may fail) or stay available (every request gets an answer, but the data might be slightly out of date). You can't fully have both.</li><li>Real databases pick a side. MongoDB leans toward consistency, blocking writes during a partition so all replicas stay in sync. Cassandra leans toward availability, keeping the lights on and serving queries even if replicas briefly disagree.</li></ul>]]></content:encoded></item><item><title>Second-System Effect</title><link>https://lawsofsoftwareengineering.com/laws/second-system-effect/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/second-system-effect/</guid><description>Small, successful systems tend to be followed by overengineered, bloated replacements.</description><content:encoded><![CDATA[<p>A small, elegant system is built and works well. A second version is initiated, and the designers, freed from the constraints of the first project, try to build something much bigger and more complex. They add enhancements, address all edge cases, and incorporate wishlist features. The result is often an overly complex, behind-schedule system.</p>
<p>Brooks noted this with IBM&rsquo;s OS/360: simpler earlier systems were followed by a second system that became very complex. The syndrome is an exercise in hubris. The team doesn&rsquo;t realize how much harder the bigger scope will be.</p>
<p>The second-system effect warns engineers to be suspicious of grand redesigns that promise to include everything.</p>
<ul><li>The first system is kept lean by constraints or inexperience. When designing its successor, there's a tendency to incorporate all the extras initially left out, leading to feature bloat.</li><li>Overconfidence plays a role. Having succeeded once, the team feels they can tackle much more, underestimating complexity.</li><li>The second-system effect often results in over-engineering with more modules, generality, and features than necessary, hurting performance and maintainability.</li></ul>]]></content:encoded></item><item><title>Fallacies of Distributed Computing</title><link>https://lawsofsoftwareengineering.com/laws/fallacies-of-distributed-computing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/fallacies-of-distributed-computing/</guid><description>A set of eight false assumptions that new distributed system designers often make.</description><content:encoded><![CDATA[<p>The Eight Fallacies serve as a checklist of what not to assume. They all spring from treating a distributed system like a local one. Developers might write code as if calling a remote service is just like calling a local function, ignoring latency and failure.</p>
<p>These mistaken assumptions lead to serious issues: unhandled errors when the network breaks, poor performance due to ignoring latency, security breaches from failing to authenticate remote calls.</p>
<p>By calling them &ldquo;fallacies,&rdquo; creators sought to instill the mindset that the network will fail and behave non-ideally, so your system must be designed to tolerate that.</p>
<ul><li>Networks drop messages, introduce delays, have finite throughput, and can be insecure. Properly built distributed systems must account for these with retries, timeouts, security measures, and dynamic discovery.</li><li>The fallacies often manifest in subtle bugs. Assuming latency is zero might lead to chatty remote calls that work fine locally but become painfully slow over a network.</li><li>Taking these fallacies into account leads to defensive design: using caches (bandwidth/latency aren't perfect), building redundancy (networks aren't reliable), and handling dynamic membership (topology changes).</li></ul>]]></content:encoded></item><item><title>Law of Unintended Consequences</title><link>https://lawsofsoftwareengineering.com/laws/law-of-unintended-consequences/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/law-of-unintended-consequences/</guid><description>Whenever you change a complex system, expect surprise.</description><content:encoded><![CDATA[<p>The Law of Unintended Consequences states that outcomes are not entirely predictable. Systems have complex interdependencies and human factors that can cause surprises.</p>
<p>Adding a new feature might unexpectedly degrade performance due to its interaction with an unrelated module. Simplifying a UI could lead to heavier backend load because users use the feature more often than expected.</p>
<p>It reminds engineers that systems are complex and our mental models are incomplete. When implementing changes, anticipate that &ldquo;unknown unknowns&rdquo; will crop up.</p>
<ul><li>No matter how well you plan, any significant change in a complex system can produce results you cannot anticipate.</li><li>Consequences can be unexpected benefits (happy surprises), unexpected drawbacks (side effects that hinder), or perverse results (the action makes the original problem worse).</li><li>In software engineering, this often manifests as a fix or new feature introducing bugs or performance issues elsewhere.</li></ul>]]></content:encoded></item><item><title>Zawinski's Law</title><link>https://lawsofsoftwareengineering.com/laws/zawinskis-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/zawinskis-law/</guid><description>Every program attempts to expand until it can read mail.</description><content:encoded><![CDATA[<p>Zawinski&rsquo;s Law is a humorous observation about software evolution stating that applications continually gain features until they do everything, even things completely outside their original scope. It highlights feature creep, the gradual expansion of scope in software development.</p>
<p>As an application attracts more users, it faces growing expectations to add more capabilities. A basic note-taking app might later incorporate chat or sharing.</p>
<p>Zawinski&rsquo;s point was about &ldquo;platformization&rdquo;: once users live in an app for a significant part of their day, there is pressure for that app to become a platform that can do everything. Unchecked expansion can sabotage a product&rsquo;s original value. Adding features is easy, but adding only the right features and saying &ldquo;no&rdquo; to the rest is essential.</p>
<ul><li>Feature creep is unavoidable. Over time, software tends to accumulate more features, leading to software bloat.</li><li>A lean, minimal application that gains popularity will continually add features until it becomes as complex as its competitors.</li><li>Programs expand because users (and product managers) keep asking for “just one more feature”. There is constant pressure to incorporate popular capabilities to keep users from leaving for other tools.</li><li>Each new feature increases complexity, which makes the product confusing for users. Developers should protect the tool’s focus and resist platform sprawl.</li></ul>]]></content:encoded></item><item><title>Dunbar's Number</title><link>https://lawsofsoftwareengineering.com/laws/dunbars-number/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/dunbars-number/</guid><description>There is a cognitive limit of about 150 stable relationships one person can maintain.</description><content:encoded><![CDATA[<p>Dunbar&rsquo;s Number means that an engineering department of 150 might function informally, but as it grows past that, you start needing more formal rules, communication channels, and management layers. Informal knowledge (&ldquo;I know who to talk to about X&rdquo;) begins to fail, and teams feel impersonal.</p>
<p>The rule encourages designing sub-teams or &ldquo;teams of teams&rdquo; that are small enough to work together effectively. Dunbar also proposed smaller social layers: ~5 intimate relationships, ~15 trusted collaborators, ~50 close working relationships, and ~150 stable social connections.</p>
<p>For software teams, high-trust work happens in tiny groups, teams larger than ~10-15 lose cohesion, and the 150 limit applies to departments or communities, not day-to-day collaboration.</p>
<ul><li>Dunbar's number (~150) is the size of a community in which everyone knows each other's identities and roles. Beyond this, our brains struggle to track relationships.</li><li>In software organizations, teams larger than ~100-150 will require more hierarchy or splitting into subgroups to function effectively. Coordination overhead rises sharply.</li><li>Smaller limits exist for closer relationships. Effective working groups might be much smaller than 150, but 150 is an upper bound for a community feeling.</li><li>Strong collaboration happens in groups far below the 150 threshold. Small teams win.</li></ul>]]></content:encoded></item><item><title>The Ringelmann Effect</title><link>https://lawsofsoftwareengineering.com/laws/ringelmann-effect/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/ringelmann-effect/</guid><description>Individual productivity decreases as group size increases.</description><content:encoded><![CDATA[<p>The Ringelmann Effect states that as more people work together, individual effort decreases. In software teams, productivity per person often declines in larger groups due to coordination overhead and some individuals contributing less when in a crowd.</p>
<p>This effect warns that adding team members can make each existing member less efficient. Along with Brooks&rsquo;s Law, it shows that teamwork doesn&rsquo;t scale linearly. Teams must be structured to mitigate this with clear roles and small, focused groups.</p>
<ul><li>In large teams, some people put in less effort because they assume others will pick up the slack or because their contributions are less visible.</li><li>More people mean more communication, meetings, and alignment needed. Time spent coordinating increases, leaving less time for actual work.</li><li>There is a point at which adding people yields diminishing returns, or even negative returns per person. Small, focused teams often outperform poorly coordinated larger teams.</li><li>Smaller teams or individuals feel greater ownership and responsibility.</li></ul>]]></content:encoded></item><item><title>Price's Law</title><link>https://lawsofsoftwareengineering.com/laws/prices-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/prices-law/</guid><description>The square root of the total number of participants does 50% of the work.</description><content:encoded><![CDATA[<p>You probably noticed that most of the major work depends on just a few people in your organization, and that is not false. In software teams, it means a relatively small group of engineers will deliver a disproportionately large part of the value. This is similar to the Pareto principle (80/20 rule) but even more extreme for larger groups.</p>
<p>Price&rsquo;s Law suggests that simply hiring more developers won&rsquo;t necessarily scale output as expected. Beyond a point, many may contribute little or be working on peripheral tasks. It&rsquo;s an argument for focusing on quality when hiring: a single excellent engineer can outperform several average ones. However, we must be careful with this &ldquo;law&rdquo; as we don&rsquo;t want to make other people feel useless, as they may be doing essential tasks that are given less importance.</p>
<p>It highlights a risk: if those top √N contributors leave, you lose a large chunk of productivity, so retention and preventing burnout for them are critical.</p>
<ul><li>A small fraction of people often contribute a significant fraction of the results. In a 100-person engineering org, about 10 people might produce half of the output.</li><li>As teams grow, productive output doesn't scale linearly. Adding more people increases total output, but many will make smaller contributions than the core group.</li><li>Knowing this helps in team planning and understanding why losing specific individuals has a significant impact on productivity.</li><li>It's wise to identify and retain the small group of people who are essential to the company's output.</li></ul>]]></content:encoded></item><item><title>Putt's Law</title><link>https://lawsofsoftwareengineering.com/laws/putts-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/putts-law/</guid><description>Those who understand technology don't manage it, and those who manage it don't understand it.</description><content:encoded><![CDATA[<p>Putt&rsquo;s Law explains a known concept: that the best engineers aren&rsquo;t in charge, and those in charge aren&rsquo;t deeply knowledgeable about the technology. While not universally true, this highlights a real challenge: managing technologists requires some understanding of their work. But managers often come from different backgrounds or have been away from the code for a long time.</p>
<p>The law&rsquo;s corollary states: &ldquo;Every technical hierarchy, in time, develops a competence inversion,&rdquo; meaning the people at the top know less about the work than those below. The gap creates dysfunction: managers set unrealistic deadlines because they don&rsquo;t understand technical subjects, while engineers build wrong solutions because they don&rsquo;t understand the business context.</p>
<p>The lesson is clear: technical leadership should maintain technical competence or risk mismanaging the technical work.</p>
<ul><li>There is often a gap between deep technical understanding and management roles. Rarely does one person excel at both.</li><li>Technical experts often aren't in management, and managers usually don't understand the technical details.</li><li>This can lead to unrealistic expectations, such as when management sets unrealistic expectations because they don’t understand the domain and its complexity. At the same time, engineers are feeling misunderstood.</li><li>Successful organizations bridge this by training managers in tech basics or promoting technically savvy leaders.</li></ul>]]></content:encoded></item><item><title>Peter Principle</title><link>https://lawsofsoftwareengineering.com/laws/peter-principle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/peter-principle/</guid><description>In a hierarchy, every employee tends to rise to their level of incompetence.</description><content:encoded><![CDATA[<p>The Peter Principle explains why organizations often end up with mediocre managers. A great engineer gets promoted to tech lead but struggles in the role, and now the company has lost a great engineer.</p>
<p>For a healthy organization, it&rsquo;s essential to mitigate this. Not every senior engineer should become a manager; some might advance as staff or principal engineers instead. New managers need training to be competent in their new role.</p>
<p>The Peter Principle warns that promotion systems can create mediocrity at higher levels if not designed carefully.</p>
<ul><li>People get promoted based on success in their current role until they reach a position where they are no longer competent.</li><li>A great developer promoted to manager might perform poorly, losing a good developer and gaining a bad manager.</li><li>Organizations should offer dual career paths (technical vs. managerial) to prevent this stagnation.</li></ul>]]></content:encoded></item><item><title>Bus Factor</title><link>https://lawsofsoftwareengineering.com/laws/bus-factor/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/bus-factor/</guid><description>The minimum number of team members whose loss would put the project in serious trouble.</description><content:encoded><![CDATA[<p>The Bus Factor highlights the human single point of failure in projects. In many software teams, one or two people might understand the legacy system, a crucial algorithm, or have all the deployment knowledge. If those people leave, others cannot easily pick up the work.</p>
<p>The concept encourages actively avoiding such dependency. Improving bus factor overlaps with knowledge management practices: pair programming, code reviews, documentation, mentorship, and rotating responsibilities.</p>
<ul><li>A bus factor of 1 means one person holds critical knowledge; if they disappear, the project is essentially “doomed” or stalled. A higher bus factor (e.g., 5) means the project could lose any one of five specific people before stopping work.</li><li>It's basically a measure of knowledge distribution and risk. A high bus factor is good (knowledge is shared among many), while a low is bad (single points of failure in expertise).</li><li>Teams should work to increase their bus factor by sharing knowledge, documenting critical systems, having code reviews, and rotating responsibilities. </li></ul>]]></content:encoded></item><item><title>Dilbert Principle</title><link>https://lawsofsoftwareengineering.com/laws/dilbert-principle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/dilbert-principle/</guid><description>Companies tend to promote incompetent employees to management to limit the damage they can do.</description><content:encoded><![CDATA[<p>The Dilbert Principle suggests that instead of addressing poor performance directly, companies often promote struggling employees into management roles where their impact is perceived as less immediately harmful. The satire resonates because it reflects a fundamental flaw: many organizations treat management as the default career path for engineers without considering what those employees actually want or are suited for.</p>
<p>When promotion replaces accountability, management layers fill with people lacking either technical credibility or leadership ability. The result is bad decisions, wrong priorities, and loss of trust between engineers and leadership.</p>
<ul><li>Organizations sometimes deal with underperformers by promoting them into management, removing them from hands-on work.</li><li>It reflects a cynical view that lower-level employees do real work while some managers add little value.</li><li>Technical excellence and people leadership require different skills. Failing at one does not qualify someone for the other.</li></ul>]]></content:encoded></item><item><title>Parkinson's Law</title><link>https://lawsofsoftwareengineering.com/laws/parkinsons-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/parkinsons-law/</guid><description>Work expands to fill the time available for its completion.</description><content:encoded><![CDATA[<p>This law shows a common problem with time management among developers. If a developer is given two weeks to complete a task that could be done in two days, the work will usually slow down, consuming most of that time. People might spend more time planning, bikeshedding minor details, or simply delaying the start of the work with the understanding that they have enough time.</p>
<p>Parkinson&rsquo;s Law is often used to warn that loose deadlines reduce productivity, so teams should set clear, realistic time limits. However, managers must use it judiciously, combining Parkinson&rsquo;s insight with realistic scheduling. If you compress timelines too much, you risk running into Hofstadter&rsquo;s Law, which reminds us that work often still takes longer than expected, even with buffers.</p>
<ul><li>If you give a task an overly long timeline, people tend to use all of it (or procrastinate until the last minute), so the task takes as long as the deadline allows.</li><li>Giving more time, teams often do polishing (gold-plating) or add minor improvements that aren't strictly necessary, just to use the whole time allotted for the task.</li><li>A bit stronger (but realistic) deadlines can counteract Parkinson's Law by having a sense of urgency (called deadline-driven development).</li></ul>]]></content:encoded></item><item><title>The Ninety-Ninety Rule</title><link>https://lawsofsoftwareengineering.com/laws/ninety-ninety-rule/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/ninety-ninety-rule/</guid><description>The first 90% of the code accounts for the first 90% of development time; the remaining 10% accounts for the other 90%.</description><content:encoded><![CDATA[<p>This rule quantifies the extent to which projects get stuck in the final phase. Often, teams make good progress at the start, building core functionality, which leads to optimism. Then integration, corner cases, performance tuning, and bug fixing consume an unexpectedly large amount of time, often equal to or greater than what has already been spent.</p>
<p>In practical terms, this rule advises that the last bit of a project is not a small bit. You should plan for a significant effort in finishing, polishing, and delivering.</p>
<p>It is also related to Hofstadter&rsquo;s Law, as it is another way our estimates fall short. We do not realize how hard that last leg is.</p>
<ul><li>The final parts of a project (polishing, edge cases, integration, bug fixes) often take far more effort than anticipated, often as much as the initial development.</li><li>What looks like the “finishing touches” involves many tricky problems and unknowns.</li><li>Reaching a “mostly done” state can create optimism, but the rule warns that “almost done” often means only halfway in terms of time.</li></ul>]]></content:encoded></item><item><title>Hofstadter's Law</title><link>https://lawsofsoftwareengineering.com/laws/hofstadters-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/hofstadters-law/</guid><description>It always takes longer than you expect, even when you take into account Hofstadter's Law.</description><content:encoded><![CDATA[<p>This recursive law captures the paradox of estimation. No matter how much experience we have, projects tend to run late. Even if you say, &ldquo;This might take 2x longer than I think,&rdquo; it might still take 3x. It highlights the inherent uncertainty in complex creative work, such as software development. There are often hidden tasks, unplanned integration issues, or requirement changes.</p>
<p>In practice, Hofstadter&rsquo;s Law explains why techniques like padding estimates, awareness of Parkinson&rsquo;s Law, and the use of historical data are essential, yet surprises still occur.</p>
<p>It pairs with Parkinson&rsquo;s Law as a caution: don&rsquo;t pad too much (Parkinson will waste time), but also don&rsquo;t be naive (Hofstadter will bite you with delays).</p>
<ul><li>Humans are generally bad at estimating how long tasks take, especially in complex projects. Even when we know we're bad at it, we still underestimate.</li><li>There are always unknowns and complexities that reveal themselves during implementation, extending the timeline.</li><li>Include contingency buffers in schedules, but even those buffers often get consumed.</li><li>Don't be overly optimistic in planning. Acknowledge that delays happen and factor that into timelines and expectations.</li></ul>]]></content:encoded></item><item><title>Goodhart's Law</title><link>https://lawsofsoftwareengineering.com/laws/goodharts-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/goodharts-law/</guid><description>When a measure becomes a target, it ceases to be a good measure.</description><content:encoded><![CDATA[<p>Goodhart&rsquo;s Law comes from economics and is very relevant to software teams. For instance, a manager might set a target that &ldquo;we must close 100 bug tickets this month.&rdquo; Developers, feeling pressure, might start closing tickets that are not truly resolved or splitting a single bug into multiple tickets to inflate numbers.</p>
<p>The metric (tickets closed) goes up, but software quality might not. Making the metric a goal distorts the process, so it loses its correlation with actual success. This is why experienced leaders use metrics as indicators rather than targets, and always consider the broader context.</p>
<ul><li>If you set a particular metric as a goal (e.g., lines of code written, number of features closed), people will find ways to optimize for that metric.</li><li>Metrics are proxies for what you value (productivity, quality, etc.). Once they're targets, people meet the metric even if it undermines the original intent.</li><li>Metrics are useful for insight, but they must be used in context and balanced with qualitative judgment.</li><li>Combine multiple metrics to avoid a singular focus that can be gamed.</li></ul>]]></content:encoded></item><item><title>Gilb's Law</title><link>https://lawsofsoftwareengineering.com/laws/gilbs-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/gilbs-law/</guid><description>Anything you need to quantify can be measured in some way better than not measuring it.</description><content:encoded><![CDATA[<p>Gilb&rsquo;s Law responds to the paralysis that Goodhart&rsquo;s Law can cause. This law asserts that even an approximate or indirect measurement is better than none. When something is essential (performance, customer satisfaction, code maintainability), you should attempt to measure it, because otherwise you have no objective feedback.</p>
<p>Gilb&rsquo;s Law is a good reply to the statement “this aspect is unmeasurable so we won&rsquo;t try.” For example, measuring “code quality” is difficult, but you can measure indicators such as cyclomatic complexity, lint warnings, or defect rates as partial indicators. More such indicators can paint the bigger picture.</p>
<p>Those metrics won&rsquo;t be perfect, but Gilb&rsquo;s Law suggests that having them gives you some insight and a starting point for improvement, which is better than having no clue at all.</p>
<ul><li>It is better to have some data or metric on a phenomenon than to be completely blind, as long as you understand the metric's limitations.</li><li>In contrast to Goodhart's Law, which warns about misuse of metrics, Gilb's Law reminds us not to throw out metrics entirely.</li><li>Start with a basic measure and refine it over time. The act of measuring helps teams focus and identify trends.</li><li>Even an approximate or indirect measurement is better than none.</li></ul>]]></content:encoded></item><item><title>Murphy's Law / Sod's Law</title><link>https://lawsofsoftwareengineering.com/laws/murphys-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/murphys-law/</guid><description>Anything that can go wrong will go wrong.</description><content:encoded><![CDATA[<p>In software, Murphy&rsquo;s Law is often used to explain bugs and production incidents: whatever can go wrong in code (a null pointer, a race condition, a network outage) eventually will manifest, especially in large user bases or at the worst possible time.</p>
<p>In practice, this law encourages developers to write more defensive code. This means checking for nulls, handling exceptions, validating inputs, and failing gracefully when errors occur. It also reminds DevOps teams to anticipate failures by implementing monitoring, enabling rollbacks, and maintaining contingency plans.</p>
<ul><li>If an error can happen, it will happen. Plan and code defensively with this in mind.</li><li>Add error handling, backups, and checks.</li><li>Edge cases will occur in production. Write tests for these kinds of scenarios.</li></ul>]]></content:encoded></item><item><title>Postel's Law</title><link>https://lawsofsoftwareengineering.com/laws/postels-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/postels-law/</guid><description>Be conservative in what you do, be liberal in what you accept from others.</description><content:encoded><![CDATA[<p>This law says that if your server sends HTTP responses, it should format headers exactly per spec. But if your server receives an HTTP request with an uncommon header order or an unusual format, you should still process it rather than drop the connection, as long as you can interpret it safely.</p>
<p>This principle contributed to the Internet&rsquo;s resilience, meaning that different implementations can communicate because each side strives to be compatible.</p>
<p>In software in general, think of file readers: a robust one can open not-quite-perfect files (e.g., a tolerant XML parser might recover from a minor error), whereas a strict one might refuse. Postel&rsquo;s Law would encourage the former. However, it has caveats. Being too liberal can allow sloppy producers to proliferate, and in security contexts, accepting malformed input can be risky. Some argue that overly tolerant software can cause long-term interoperability problems because producers never fix their bugs if everyone tolerates them.</p>
<ul><li>When your system emits data or interacts with the outside world, adhere closely to protocols and standards.</li><li>When receiving data, handle variations, minor errors, or deviations where possible. Don't crash or reject communication over minor issues.</li><li>In modern times, overly liberal acceptance can sometimes mask errors, so this law is occasionally tempered with security considerations.</li></ul>]]></content:encoded></item><item><title>Broken Windows Theory</title><link>https://lawsofsoftwareengineering.com/laws/broken-windows-theory/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/broken-windows-theory/</guid><description>Don't leave broken windows (bad designs, wrong decisions, or poor code) unrepaired.</description><content:encoded><![CDATA[<p>The Broken Windows Theory in software was popularized by the book The Pragmatic Programmer. In a city, a broken window left unfixed signals neglect and invites more vandalism. Similarly in code, an apparent bug or messy section left untreated can lead to more developers bypassing the process or introducing more mess.</p>
<p>The idea is that quality problems snowball if left unaddressed. For example, if a team routinely ignores failing tests or lets linters/errors slide during builds, developers get the message that it&rsquo;s okay to ship sloppy work. This accelerates code decay (also known as software entropy).</p>
<p>Conversely, if a team quickly fixes minor issues and maintains high standards, it creates a culture of quality.</p>
<ul><li>If you let minor bugs and bad style slide, people assume quality doesn't matter, and they'll ship messier code.</li><li>A clean, well-maintained codebase encourages engineers to keep it clean, whereas a chaotic codebase encourages corner-cutting and further degradation.</li><li>Fix problems while they're small. Refactor destructive code, update outdated docs, to prevent a downward spiral of code health.</li></ul>]]></content:encoded></item><item><title>Technical Debt</title><link>https://lawsofsoftwareengineering.com/laws/technical-debt/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/technical-debt/</guid><description>Technical Debt is everything that slows us down when developing software.</description><content:encoded><![CDATA[<p>Technical debt highlights a fundamental tension in software engineering: speed vs. quality. The term helps explain to both developers and non-technical stakeholders why seemingly &ldquo;done&rdquo; software still needs ongoing work. When you write clumsy code or postpone cleanup, you&rsquo;ve essentially taken out a loan: you get short-term feature delivery, but the complexity you introduce is the interest you&rsquo;ll keep paying.</p>
<p>Properly managing technical debt means being conscious of when you&rsquo;re adding a quick workaround or a &ldquo;temporary&rdquo; hack, and having a plan to revisit it. Teams often use tools to log technical debt items (like comments, issue tracker tickets, or dedicated debt backlogs).</p>
<p>When managed, technical debt can be an effective tool; you intentionally take on a bit of messiness to get feedback or meet a deadline, then clean it up. But if ignored, debt becomes a problem.</p>
<ul><li>When we take a shortcut in code, we borrow time from the future. This gives an immediate benefit, but you owe principal (the work to fix) plus interest.</li><li>If technical debt is not repaid, it accrues interest. Each minute spent on dirty code, bugs, and workarounds due to a lack of refactoring is interest on the debt.</li><li>Not all technical debt is inherently bad. It is sometimes necessary, for instance, for market timing or prototyping. </li><li>The way to pay down technical debt is to refactor code, add missing tests, and improve design.</li></ul>]]></content:encoded></item><item><title>Linus's Law</title><link>https://lawsofsoftwareengineering.com/laws/linuss-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/linuss-law/</guid><description>Given enough eyeballs, all bugs are shallow.</description><content:encoded><![CDATA[<p>Linux&rsquo;s open development model, releasing code early and often to the public, results in rapid bug-finding. When many people use and review a piece of software, problems become apparent to someone.</p>
<p>What is a perplexing bug to you might be trivial to another programmer who spots it. Or among thousands of users, one will stumble on the exact reproduction steps, and another might submit a fix.</p>
<p>This law shows the core of open-source: that transparency and collaboration lead to more robust, reliable software.</p>
<p>However, it&rsquo;s not absolute. Coordination and quality control are still needed. But as a guiding principle, Linus&rsquo;s Law captures the self-correcting nature of a large developer ecosystem.</p>
<p>The &ldquo;many eyeballs&rdquo; principle is also why internal code reviews and pair programming can be effective.</p>
<ul><li>Linus's Law highlights the strength of peer review and community in software development. If a codebase is accessible to many developers, someone will eventually have the expertise to identify and fix a given bug.</li><li>The rule is often cited as a key advantage of open-source software. When source code is widely available, you accumulate a large pool of contributors.</li><li>Linus's Law assumes those eyeballs are indeed looking, i.e., an active community. Simply being open-source doesn't magically fix bugs.</li></ul>]]></content:encoded></item><item><title>Kernighan's Law</title><link>https://lawsofsoftwareengineering.com/laws/kernighans-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/kernighans-law/</guid><description>Debugging is twice as hard as writing the code in the first place.</description><content:encoded><![CDATA[<p>Kernighan&rsquo;s Law says that debugging requires understanding what the code <em>actually</em> does, which can be twice as hard as writing it. When coding, you operate with a specific mental model and full context. When debugging, you might be dealing with someone else&rsquo;s code or your own code after that context has faded.</p>
<p>Writing &ldquo;clever&rdquo; or complex code is essentially setting a trap for your future self. A maintainable version is usually superior to an optimized version that is difficult to understand. As Kernighan implies, if you make your code too tricky, you&rsquo;ve essentially outsmarted yourself.</p>
<ul><li>Bug detection and removal is more complex than programming because debugging requires understanding both the code and why it doesn't work.</li><li>If you write code at the limit of your intelligence, you won't be able to understand or troubleshoot it later.</li><li>Simple code with good structure and documentation is easier to debug, saving time in the long run.</li><li>Even if your code runs successfully when you write it, it's fragile if it's too complex.</li></ul>]]></content:encoded></item><item><title>Testing Pyramid</title><link>https://lawsofsoftwareengineering.com/laws/testing-pyramid/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/testing-pyramid/</guid><description>A project should have many fast unit tests, fewer integration tests, and only a small number of UI tests.</description><content:encoded><![CDATA[<p>The pyramid is a visual metaphor: the largest level (at the bottom) is unit tests, which are fast and the most numerous. The middle layer is integration tests, fewer in number. The top is UI/end-to-end tests, the least numerous. As you go up, tests become more expensive in time, effort, and fragility, so you want proportionally fewer of them.</p>
<p>By following the pyramid, most bugs are caught at the cheapest level. If the pyramid is inverted (lots of end-to-end tests, few unit tests), the test suite tends to be slow and fragile.</p>
<ul><li>Unit testing is where you start. Unit tests are run as separate functions and execute quickly. That means you can afford to write lots of unit tests.</li><li>After the unit tests, there must be an integration test layer. These verify the integration of modules. You will require fewer integration tests than unit tests.</li><li>End-to-end tests at the top simulate real-world user scenarios. They are essential but slow and expensive to maintain.</li><li>Organizing tests this way, you receive quick feedback (most tests are quick unit tests), and when your UI test fails, there’s a better chance it’s due to a real problem</li></ul>]]></content:encoded></item><item><title>Pesticide Paradox</title><link>https://lawsofsoftwareengineering.com/laws/pesticide-paradox/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/pesticide-paradox/</guid><description>Repeatedly running the same tests becomes less effective over time.</description><content:encoded><![CDATA[<p>The &ldquo;Pesticide Paradox&rdquo; analogy comes from agriculture. When the same pesticide is used repeatedly, pests develop resistance to it.</p>
<p>In software, the first runs of a new test suite might find many bugs. Those bugs get fixed. If you keep running the same tests without changes, you won&rsquo;t find more bugs there. The software has become &ldquo;immune&rdquo; to those specific tests.</p>
<p>The testing process cannot be stagnant. Test cases must be maintained regularly. After every release cycle, testers should assess which bugs made it to production and enhance the test suite accordingly.</p>
<p>This paradox also argues for exploratory testing, where testers approach the application in new ways each iteration, uncovering problems a static regression suite would miss. The paradox doesn&rsquo;t mean regression testing is useless, as old tests catch regressions. But to catch <em>new</em> bugs, you must design <em>new</em> tests.</p>
<ul><li>Over time, an outdated test suite will identify fewer bugs. The tests are still helpful, but no longer effective at detecting new defects.</li><li>This paradox illustrates the need to infuse new test data continuously. It is essential for testers not to become complacent with their test scripts, thinking that these alone will be sufficient in the future.</li><li>By periodically creating new tests (by altering existing ones), you effectively “refresh the pesticide,” thereby providing an opportunity to catch new bugs. This involves extending tests for new functionality, trying new input combinations, or perhaps just investigating new boundary cases.</li></ul>]]></content:encoded></item><item><title>Lehman's Laws of Software Evolution</title><link>https://lawsofsoftwareengineering.com/laws/lehmans-laws/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/lehmans-laws/</guid><description>Software that reflects the real world must evolve, and that evolution has predictable limits.</description><content:encoded><![CDATA[<p>Lehman&rsquo;s Laws describe an unavoidable reality of long-lived software systems that operate in the real world. Such systems, business software, operating systems, and platforms, must continuously change to remain useful. That change is neither optional nor free.</p>
<p>As software evolves, complexity accumulates. Each change slightly increases internal disorder unless effort is spent counteracting it. Over time, this complexity reduces development speed, increases risk, and raises the cost of further change. Teams feel this as &ldquo;everything taking longer than it used to.&rdquo;</p>
<p>Organizations face hard limits: knowledge, coordination, and familiarity constrain how much change can be absorbed in a single release. Adding people does not remove these limits; it often reinforces them.</p>
<ul><li>The first law, Continuing Change, states that if a system isn't continuously updated to meet new needs, it becomes less satisfactory to use. In practice, this means that successful software is never truly “finished”; to remain useful, it undergoes ongoing enhancements (or else users abandon it for something that keeps up).</li><li>Over time, changes accumulate, making the system more complex (Law 2). Unless developers invest in refactoring or restructuring (i.e., paying down technical debt), the system's internal complexity will increase, slowing further development.</li><li>Even if users demand more, a development organization can only do so much in a given time. They can't exponentially accelerate delivery forever. Factors such as team knowledge (familiarity) and process overhead limit it.</li><li>The perceived quality of the system will decline (perhaps due to rising user expectations, environmental changes, or the accumulation of minor issues). </li></ul>]]></content:encoded></item><item><title>Sturgeon's Law</title><link>https://lawsofsoftwareengineering.com/laws/sturgeons-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/sturgeons-law/</guid><description>90% of everything is crap.</description><content:encoded><![CDATA[<p>In the tech sphere, Sturgeon&rsquo;s Law implies that most code or features are not necessary. Perhaps 90% of experiments or features don&rsquo;t pan out, and only 10% drive real value.</p>
<p>As an engineer, not every line of code you write is gold; as a product manager, many features don&rsquo;t delight users.</p>
<p>It pairs with the idea of the 10x engineer not as someone who writes 10x more code, but as someone who identifies the 10% of work that delivers 10x value. The risk isn&rsquo;t the lower quality of the 90%, it&rsquo;s the pretense that it isn&rsquo;t. When a team considers all work to have the same value, it introduces more complexity and slows down.</p>
<p>In practice, Sturgeon&rsquo;s Law encourages continuous refinement, assumes there&rsquo;s a lot of &ldquo;noise,&rdquo; and focuses on finding the &ldquo;signal.&rdquo;</p>
<ul><li>It’s like an extreme form of the Pareto Principle (80/20 rule). The bulk of what’s being put out just isn’t good, and the good stuff is the exception</li><li>In software, there are often many features or code paths that add very little value, and the critical challenge is to find a way to maximize the high-impact 10%.</li><li>Most new concepts or technologies fail to deliver, while the exceptional ones stand out.</li></ul>]]></content:encoded></item><item><title>Amdahl's Law</title><link>https://lawsofsoftwareengineering.com/laws/amdahls-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/amdahls-law/</guid><description>The speedup from parallelization is limited by the fraction of work that cannot be parallelized.</description><content:encoded><![CDATA[<p>As you add CPU cores, only the parallelizable fraction of your code speeds up. The sequential fraction remains unchanged and eventually dominates total execution time. If &ldquo;s&rdquo; is the sequential fraction, the maximum speedup with infinite parallel resources is 1/s. So if 10% is sequential, maximum speedup is 10x. If 50% is sequential, maximum speedup is only 2x.</p>
<p>This applies beyond hardware. If your system has a database that can&rsquo;t be parallelized, adding application servers hits a wall. The same holds for organizations: if one person or committee handles all architectural decisions, adding engineers increases coordination costs without increasing throughput.</p>
<ul><li>Sequential work sets the ceiling, and no amount of parallelism can overcome it.</li><li>Scaling exposes bottlenecks. More resources make limits visible, not disappear.</li><li>Fix before you scale: reduce sequential paths first. Parallelism comes second.</li><li>It applies to people, too. Decision bottlenecks can dominate at the team scale.</li></ul>]]></content:encoded></item><item><title>Gustafson's Law</title><link>https://lawsofsoftwareengineering.com/laws/gustafsons-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/gustafsons-law/</guid><description>It is possible to achieve significant speedup in parallel processing by increasing the problem size.</description><content:encoded><![CDATA[<p>Gustafson&rsquo;s Law is a principle in parallel computing that offers an optimistic view of scalability. Where Amdahl&rsquo;s Law assumes a fixed problem size and concludes that speedup is limited by serial work, Gustafson&rsquo;s Law changes the perspective.</p>
<p>It observes that when more processors are available, developers tend to increase the problem size to use that extra power. If you have a cluster twice as powerful, you might process twice as much data in the same time.</p>
<p>The parallel portion of work grows with N processors while the serial portion remains about the same, leading to &ldquo;scaled speedup&rdquo; that can be almost linear.</p>
<p>Gustafson&rsquo;s insight is that developers naturally use more computing power by asking bigger questions.</p>
<ul><li>As computing resources grow, you can compute more problems in a given time, rather than solving the same issues faster.</li><li>It opposes the pessimism of Amdahl's Law by assuming the size of the problem to be solved will increase proportionally with computing power, so that parallel processors remain busy.</li><li>Practically, Gustafson’s Law promotes the use of more resources in computation to achieve more in terms of the scope of tasks, rather than obtaining diminishing returns.</li><li>“The law,” it says, “teaches that software and algorithms should be designed to ‘scale out.’ That means that as available processor cores or machines increase, the amount of work that can be done can be scaled up accordingly.”</li></ul>]]></content:encoded></item><item><title>Metcalfe's Law</title><link>https://lawsofsoftwareengineering.com/laws/metcalfes-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/metcalfes-law/</guid><description>The value of a network is proportional to the square of the number of users.</description><content:encoded><![CDATA[<p>Metcalfe’s Law is an observation about communications networks that has been generalized to many technology ecosystems. It says that the value of a network is proportional to the square of the number of connected users. With 5 nodes, up to 10 pairwise connections are possible; with 12 nodes, 66.</p>
<p>Network effects feed on themselves, a rich-get-richer phenomenon. Initially, adding one user might not change much. But later, adding the 10-millionth user potentially enables millions of new interactions. This creates winner-takes-all dynamics in tech. However, Metcalfe’s Law is a simplified model, as not every user connects with every other, and incremental value can diminish.</p>
<ul><li>If you double the number of users, the potential connections roughly quadruple.</li><li>This law highlights the importance of network effects: each new user adds value to existing users by creating new opportunities for interaction. A product or platform becomes exponentially more useful as its user base grows.</li><li>This law helps explain why social media and messaging platforms can grow explosively in value once a tipping point is reached.</li></ul>]]></content:encoded></item><item><title>DRY (Don't Repeat Yourself)</title><link>https://lawsofsoftwareengineering.com/laws/dry-principle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/dry-principle/</guid><description>Every piece of knowledge must have a single, unambiguous, authoritative representation.</description><content:encoded><![CDATA[<p>The idea of DRY is simple: each fact or piece of logic in your system should be expressed once and only once. If you find the same code, formula, or rule in multiple modules, you&rsquo;re violating DRY. Such repetition creates hidden maintenance cost. When the business rule changes, you must hunt down every duplicate instance.</p>
<p>By following DRY, developers strive for a single, unique implementation of any given behavior. This often means abstracting common code into a function or class, or consolidating configuration into a single file.</p>
<p>DRY also applies to database schemas, tests, and documentation.</p>
<p>However, remember that DRY is about duplicated intent, not just similar-looking code. Two pieces of code can look identical but serve different purposes in an application.</p>
<ul><li>The DRY principle is about avoiding duplication of knowledge in code. If the same idea or logic is in multiple places, it's a signal to refactor.</li><li>When requirements change, you should update logic in only one place. Repeated code increases the risk of inconsistencies and bugs (you might fix a bug in one copy and forget about the others).</li><li>Be careful to apply DRY wisely. It’s about knowledge repetition, not just duplication. Sometimes two pieces of code look alike but do different jobs; merging them could over-complicate things.</li></ul>]]></content:encoded></item><item><title>KISS (Keep It Simple, Stupid)</title><link>https://lawsofsoftwareengineering.com/laws/kiss-principle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/kiss-principle/</guid><description>Designs and systems should be as simple as possible.</description><content:encoded><![CDATA[<p>The KISS principle is a reminder that simplicity should be a key goal. If you can solve a problem with a 50-line script versus a complex 500-line solution, KISS favors the 50-line solution because each line of code has the potential to cause an error.</p>
<p>Why is simplicity so important? Software has to be understood by humans. A simple design is much easier to maintain: new team members can get up to speed faster, bugs are easier to localize, and modifications cause fewer ripple effects.</p>
<p>The KISS principle encourages developers to resist &ldquo;clever&rdquo; code that does too much at once, and to avoid architecting solutions that address future problems at the cost of current complexity.</p>
<ul><li>KISS primarily refers to avoiding complexity in solution designs. A solution that satisfies the requirement and is simple in design is better than a complex one.</li><li>Code that is coded is easier and faster to understand and debug. It’s even easier to understand and fix if you’re your own future self. Smarter code may look impressive at first, but it often masks problems.</li><li>The code solution should be as simple as possible. Anything that adds complexity unnecessarily is counter to the KISS Principle.</li></ul>]]></content:encoded></item><item><title>SOLID Principles</title><link>https://lawsofsoftwareengineering.com/laws/solid-principles/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/solid-principles/</guid><description>Five main guidelines that enhance software design, making code more maintainable and scalable.</description><content:encoded><![CDATA[<p>The SOLID principles are five high-level guidelines for object-oriented design: <strong>Single Responsibility</strong> (one concern per class), <strong>Open/Closed</strong> (open for extension, closed for modification), <strong>Liskov Substitution</strong> (subclasses must be substitutable for their parent), <strong>Interface Segregation</strong> (no forced dependency on unused interfaces), and <strong>Dependency Inversion</strong> (depend on abstractions, not concretions).</p>
<p>When applied together, these principles produce systems that are modular, extensible, and robust under change. Code becomes easier to test, refactor, and extend without breaking existing functionality.</p>
<ul><li>Following SOLID leads to software that is easier to extend, test, and refactor without breaking existing functionality. Each principle addresses a different aspect of good OO design.</li><li>A class with a single responsibility (SRP) that depends on well-defined interfaces (ISP, DIP) and uses inheritance appropriately (LSP) and polymorphism for extensions (OCP) will likely be easy to maintain.</li><li>Changes to one part of the system won’t cascade into breakages elsewhere, because the code is loosely coupled and well-encapsulated.</li><li>SOLID does not guarantee a perfect design, but it provides proven guidelines for object-oriented programming.</li></ul>]]></content:encoded></item><item><title>Law of Demeter</title><link>https://lawsofsoftwareengineering.com/laws/law-of-demeter/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/law-of-demeter/</guid><description>An object should only interact with its immediate friends, not strangers.</description><content:encoded><![CDATA[<p>The Law of Demeter, also known as &ldquo;don&rsquo;t talk to strangers&rdquo; or the &ldquo;principle of least knowledge,&rdquo; was formulated to minimize the knowledge that any given object has about the overall system structure.</p>
<p>In practice, if object A has a reference to object B, and B has a reference to C, A should not call methods on C through B (like <code>a.b.getC().doSomething()</code>). A can talk to B, and B can talk to C, but A shouldn&rsquo;t directly get involved with C.</p>
<p>This fosters loose coupling. If you break LoD, your code assumes the structure extends beyond its immediate neighbors. For example, if <code>OrderProcessor</code> does <code>order.getCustomer().getAddress().getZipCode()</code>, it knows that an Order has a Customer with an Address. If Customer is changed to have multiple addresses, OrderProcessor breaks. If instead Order had a method <code>getShippingZip()</code> that internally navigates its customer/address, OrderProcessor could call that and be oblivious to structural changes.</p>
<p>LoD aligns with information hiding: each object hides its internals and only exposes necessary interfaces.</p>
<ul><li>An object should only call methods of: itself, its direct components, its function parameters, or objects it creates. It should not navigate through one object to reach another (“don’t talk to strangers”).</li><li>If object A only calls B (its immediate friend) and doesn’t reach into B’s internals (like C), then changes to C or removal of C don’t affect A. Each class knows as little as possible about others, reducing the impact of changes</li><li>It often leads to adding wrapper methods or delegations. While that might increase the number of methods, it results in cleaner interactions. </li></ul>]]></content:encoded></item><item><title>Principle of Least Astonishment</title><link>https://lawsofsoftwareengineering.com/laws/principle-of-least-astonishment/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/principle-of-least-astonishment/</guid><description>Software and interfaces should behave in a way that least surprises users and other developers.</description><content:encoded><![CDATA[<p>The Principle of Least Astonishment (POLA) is a general design principle in user interface design, software API design, coding, and documentation. The idea is simple: don&rsquo;t surprise the user.</p>
<p>The system should behave in a way that matches the user&rsquo;s mental model of how it ought to work. Violating this principle doesn&rsquo;t necessarily break functionality, but it breaks trust and ease of use.</p>
<p>In coding, this principle states that your code should behave as the developer expects when name, type, and context are taken into account. We should choose defaults and behaviors that match standard conventions and avoid “surprise” side effects.</p>
<ul><li>Design decisions should align with user expectations. When someone uses a component (a UI element, API, etc.), its behavior should not be surprising or counterintuitive.</li><li>Following platform norms or standard conventions yields the least astonishment.</li><li>In practice, it improves usability and developer experience. Users can predict how to interact with the software, and developers can predict how to use an API by analogy with similar ones. Surprises often lead to mistakes.</li></ul>]]></content:encoded></item><item><title>Dunning-Kruger Effect</title><link>https://lawsofsoftwareengineering.com/laws/dunning-kruger-effect/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/dunning-kruger-effect/</guid><description>The less you know about something, the more confident you tend to be.</description><content:encoded><![CDATA[<p>The Dunning-Kruger Effect explains a gap between confidence and competence. When people know little about a domain, they lack the awareness required to judge their own ability. As a result, they overestimate how well they understand the problem.</p>
<p>As learning progresses, people discover the depth and complexity of the domain.</p>
<p>Awareness of unknowns grows faster than capability, leading to a drop in confidence, often called the &ldquo;valley of despair.&rdquo; Only after experience does confidence rise again, now with fundamental understanding.</p>
<ul><li>Confidence without context is unreliable. Early confidence often signals ignorance, not mastery.</li><li>Awareness grows faster than skill. Learning initially reduces confidence, only to rebuild it.</li><li>Real experts speak in ranges, trade-offs, and probabilities, not with confidence about every topic.</li></ul>]]></content:encoded></item><item><title>Hanlon's Razor</title><link>https://lawsofsoftwareengineering.com/laws/hanlons-razor/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/hanlons-razor/</guid><description>Never attribute to malice that which is adequately explained by stupidity or carelessness.</description><content:encoded><![CDATA[<p>Hanlon&rsquo;s Razor advises against assuming bad faith when an outcome may be due to human error or ignorance. If a commit introduces a security hole, it&rsquo;s probably a mistake, not intentional sabotage. So one responds with help and fixes, not with blame.</p>
<p>This doesn&rsquo;t mean ignoring the possibility of malice when truly warranted (security does consider malicious actors). But for day-to-day development and operations, Hanlon&rsquo;s Razor keeps you grounded: the build failed likely due to a misconfiguration, not because someone deliberately broke it.</p>
<ul><li>When something goes wrong, it's likely not malicious but rather an error or misunderstanding.</li><li>Don't jump to “the system is hacked” or “someone intentionally broke this.” First, consider simpler explanations (e.g., a configuration file was missed or a typographical error).</li><li>If a colleague's code is problematic, it's probably not sabotage. It may be due to being rushed or unaware of something. Try to approach with questions, not accusations.</li></ul>]]></content:encoded></item><item><title>Occam's Razor</title><link>https://lawsofsoftwareengineering.com/laws/occams-razor/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/occams-razor/</guid><description>The simplest explanation is often the most accurate one.</description><content:encoded><![CDATA[<p>Occam&rsquo;s Razor is a problem-solving principle that reminds us that when we have multiple possible solutions, the simplest one is preferred.</p>
<p>In software, this principle supports the KISS (&ldquo;Keep It Simple, Stupid&rdquo;) approach. When we decide to keep our implementations simple, we reduce the risk of further complications.</p>
<p>For example, if a software architecture can achieve its goals with a monolith and one database, there is no need to split it into five microservices and two databases. These extra components would only introduce complexity and potential integration and coordination issues, but no benefits.</p>
<p>This is a reminder to avoid the temptation of over-engineering and keep things simple.</p>
<ul><li>Simple code is easier to understand, maintain, and debug, whereas complex code has more potential points of failure. Remove or avoid unnecessary moving parts in system architecture.</li><li>When debugging, start with the simplest explanation before jumping into complex theories.</li><li>Adding more features to the app can only complicate a product without adding real value. Occam’s Razor reminds us that less is more in many cases.</li></ul>]]></content:encoded></item><item><title>Sunk Cost Fallacy</title><link>https://lawsofsoftwareengineering.com/laws/sunk-cost-fallacy/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/sunk-cost-fallacy/</guid><description>Sticking with a choice because you've invested time or energy in it, even when walking away helps you.</description><content:encoded><![CDATA[<p>The sunk cost fallacy is a cognitive bias that challenges our decision-making. Humans irrationally value what they&rsquo;ve already invested, whether money, time, or effort, even when those investments can&rsquo;t be recovered.</p>
<p>In software development, teams often continue working on a feature or product without making progress simply because &ldquo;we have come this far.&rdquo;</p>
<p>Understanding this fallacy allows engineers and managers to make more rational choices: past costs should be ignored when deciding the future. Instead, consider current facts and future benefits.</p>
<p>If a rewrite or switch to a third-party solution will clearly save time and money from this point forward, do that, regardless of how much was sunk into the old approach.</p>
<p>Overcoming sunk-cost bias is tough because it requires admitting past efforts were in vain, but in technology it&rsquo;s crucial to learn to let go when evidence demands.</p>
<ul><li>Don't stay stuck based on past investments. The fact that 'we've invested a year already' is not an excuse to continue if it's clearly not working.</li><li>Healthy engineering organizations pivot or stop projects that no longer make sense. Continuing a bad project just because of sunk costs usually leads to greater loss.</li><li>Use clear measures and decision points: 'If we don't meet target X by end of quarter, we'll re-evaluate or discontinue.'</li><li>Teams should feel safe admitting a project isn't working without fear of blame.</li></ul>]]></content:encoded></item><item><title>The Map Is Not the Territory</title><link>https://lawsofsoftwareengineering.com/laws/map-is-not-the-territory/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/map-is-not-the-territory/</guid><description>Our representations of reality are not the same as reality itself.</description><content:encoded><![CDATA[<p>&ldquo;The Map Is Not the Territory&rdquo; is a mental model originating from general semantics. It encapsulates the idea that our perceptions or conceptual models of things are not the things themselves.</p>
<p>In software, we constantly create &ldquo;maps&rdquo;: requirements documents map user needs, architecture diagrams map how components should interact, and our mental understanding of a codebase is a personal map of how we think the code works.</p>
<p>These maps are useful and necessary. Without them, we couldn&rsquo;t plan or reason about complex systems. However, problems arise when we forget the map&rsquo;s limits.</p>
<p>A typical example is overconfidence in initial design: a team designs a system on paper, but when coding begins, they discover modules cannot communicate due to latency issues not captured in their assumptions.</p>
<p>As statistician George Box said, &ldquo;All models are wrong, but some are useful.&rdquo;</p>
<ul><li>Design docs, UML diagrams, and architecture schematics are abstractions. Don't confuse the blueprint with the actual running software.</li><li>When implementing a system, expect that unforeseen factors will emerge that weren’t captured in the initial designs. Be prepared to adapt the plan as you discover new “terrain” during development and testing.</li><li>Models and designs are valuable for guiding development, but always be willing to question assumptions when evidence from the real system contradicts them.</li></ul>]]></content:encoded></item><item><title>Confirmation Bias</title><link>https://lawsofsoftwareengineering.com/laws/confirmation-bias/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/confirmation-bias/</guid><description>A tendency to favor information that supports our existing beliefs or ideas.</description><content:encoded><![CDATA[<p>We all like to be right. Confirmation bias is our mind&rsquo;s way of cheating to feel right more often. Psychologically, once we form an opinion, we subconsciously filter information, noticing bits that support our view and ignoring those that contradict it.</p>
<p>In software, a typical scenario is debugging. A developer convinced that module A caused a production issue will comb through module A&rsquo;s code intensively. If module B (assumed to be fine) is also throwing errors, they might not even look there, missing the real cause. Awareness of this bias leads to asking &ldquo;What am I missing? Maybe there is another explanation?&rdquo; and encouraging environments where beliefs are constructively questioned.</p>
<ul><li>When reviewing code or debugging, notice if you're only looking for evidence that supports your initial hunch.</li><li>Challenge yourself when actively thinking about problems. If you have an opinion about an issue, try to ask, “What would I expect to see if I’m wrong?” In this, we can counteract our natural bias only to confirm.</li><li>Regarding team decision-making (for example, tech stacks and/or design decisions), seek input from people with differing opinions. Bias confirmation can be overcome by looking into alternative solutions. For example, if the whole team “feels” that technology X is the superior choice, assign someone to look into the opposing view on technology X.</li><li>Base decision-making on objective criteria (facts, not opinions). Automated tests, performance criteria, and experimentation (A/B tests) can provide truths regardless of human bias.</li></ul>]]></content:encoded></item><item><title>The Hype Cycle &amp; Amara's Law</title><link>https://lawsofsoftwareengineering.com/laws/hype-cycle-amaras-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/hype-cycle-amaras-law/</guid><description>We tend to overestimate the effect of a technology in the short run and underestimate the impact in the long run.</description><content:encoded><![CDATA[<p>This law describes the familiar boom-and-bust hype cycle in tech. Gartner&rsquo;s Hype Cycle captures the pattern: a new technology triggers inflated expectations, hits a trough of disillusionment when reality falls short, then gradually climbs a slope of enlightenment toward productive mainstream adoption.</p>
<p>In software engineering, many buzzword technologies are initially promoted as game-changers but decline when they cannot deliver promised results. However, after that reality check, some quietly mature and find real usability. The lesson is to have healthy skepticism during hype, but keep an open mind for long-term adoption.</p>
<ul><li>Early on, people overestimate what tech can do in the near term, leading to unrealistic expectations.</li><li>In the longer run, the same technology’s true potential emerges, often greater than initially imagined. Amara’s Law reminds us that we tend to underestimate the long-term impact of a significant innovation.</li><li>For developers and tech leaders, this means not getting swept up in the hype cycle. Be patient and evaluate new tools by their proven value, not just the buzz.</li><li>Treat innovation as a limited budget. Good teams use stable, proven tech for most needs and adopt a hyped new technology only when it truly addresses a real problem.</li></ul>]]></content:encoded></item><item><title>The Lindy Effect</title><link>https://lawsofsoftwareengineering.com/laws/lindy-effect/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/lindy-effect/</guid><description>The longer something has been in use, the more likely it is to continue being used.</description><content:encoded><![CDATA[<p>The Lindy Effect turns our intuition about aging on its head. For living creatures, older means less life expectancy. But in technology, it&rsquo;s often the opposite: the longer something has been in use, the more likely it is to continue being used.</p>
<p>Time acts as a filter. Anything irrelevant, flawed, or fragile tends to disappear, while what remains after many years is usually high-quality and valuable.</p>
<p>This principle serves as a reality check against shiny object syndrome. The majority of so-called &ldquo;innovations&rdquo; have little to no relevance to contemporary ideas; rather, they reinvent ideas of the past. Truly fundamental ideas in software (algorithms, data structures, protocols, paradigms) change slowly.</p>
<p>Applying Lindy&rsquo;s law means favoring things that have &ldquo;stood the test of time&rdquo; and learning languages like Python, Java, or C, as well as algorithms, rather than over-focusing on the hottest new framework.</p>
<ul><li>The Lindy Effect states that if something (a technology, tool, concept) has persisted for a long time, it will likely continue for much longer.</li><li>For developers, Lindy’s law is a reminder to invest in timeless skills and proven fundamentals (algorithms, core languages, design principles) rather than chasing every new framework that might be obsolete in a few years.</li><li>Use the Lindy Effect when evaluating technology. Things that have been around for some time stick around longer in the future (i.e., choose boring technology).</li></ul>]]></content:encoded></item><item><title>First Principles Thinking</title><link>https://lawsofsoftwareengineering.com/laws/first-principles-thinking/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/first-principles-thinking/</guid><description>Breaking a complex problem into its most basic blocks and then building up from there.</description><content:encoded><![CDATA[<p>First-principles thinking solves problems by questioning existing solutions rather than blindly copying them. Instead of &ldquo;We&rsquo;ll do X because that other project did X,&rdquo; ask: &ldquo;What are we really trying to accomplish? What are constraints versus assumptions?&rdquo; This approach is good for incremental improvements but essential for fundamental changes.</p>
<p>In software design, first principles challenge how current systems work: &ldquo;If we started from scratch today, how would we build this?&rdquo; This thinking led to microservices (questioning the monolith) and serverless computing (questioning server management). The drawback is that it is mentally intensive and not always necessary. Many problems are well-solved by known patterns.</p>
<ul><li>Do not accept the problem as it is. Break the problem down into its inherent parts and then question your assumptions: Are they really true, or are they just accepted standards? Once you grasp the underlying requirements, you may develop new solutions.</li><li>Just because “everyone uses Framework Y for this” isn’t a reason you should do so. First principles thinking pushes you to ask why people do certain things the way they do.</li><li>Rather than saying, “This feature will take 3 months because that’s how long similar features took,” break the feature down. Estimate from the basics, which can sometimes show that the “similar” feature had additional issues that you may not have anymore. </li></ul>]]></content:encoded></item><item><title>Inversion</title><link>https://lawsofsoftwareengineering.com/laws/inversion/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/inversion/</guid><description>Solving a problem by considering the opposite outcome and working backward from it.</description><content:encoded><![CDATA[<p>The core idea is that specific insights become clear when you look at a problem from the opposite angle. In software engineering, instead of designing only for the best case, you deliberately design for the worst case: What if the database goes down? What if latency spikes?</p>
<p>By thinking of how things can fail, you add features like circuit breakers, retries, or failover strategies. Inversion pairs well with First-Principles Thinking and is a form of defensive design that leads to robust outcomes by avoiding possible problems.</p>
<ul><li>For any goal, also ask the inverted question. If the goal is “deliver the project on time,” we should think about “what would make us miss the deadline?” Making a list of those factors (scope creep, underestimating tasks, etc.) can help us achieve those goals and escape issues.</li><li>Use techniques like pre-mortems. Our project failed, and we tried to determine what could have caused it. This critical thinking can show risks that optimistic planning overlooks.</li><li>In design and testing, we can account for edge cases and use cases of your system. For example, how could a malicious user break this API? Inverting in this way leads to better solutions (e.g., adding validation, rate limiting, etc., once you understand how things break).</li></ul>]]></content:encoded></item><item><title>Pareto Principle (80/20 Rule)</title><link>https://lawsofsoftwareengineering.com/laws/pareto-principle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/pareto-principle/</guid><description>80% of the problems result from 20% of the causes.</description><content:encoded><![CDATA[<p>The Pareto Principle is more of an observation than a law, but the 80/20 pattern (or similar ratios like 90/10) appears frequently.</p>
<p>In the domain of software engineering we say that, &ldquo;80% of the time in a program is spent in 20% of the code.&rdquo; This insight is significant for optimization: instead of micro-optimizing everything, profile to identify the hot 20% and optimize that.</p>
<p>The principle influences product development too. Often, a few core features satisfy the majority of user needs. When planning an MVP, teams focus on that core set rather than trying to do everything. It is an essential check against equal prioritization: everything is not equally important.</p>
<p>The Pareto Principle encourages strategic allocation of effort to maximize outcomes by investing where returns are highest.</p>
<ul><li>Identify the top 20% of factors that contribute to 80% of whatever you care about. This could be 20% of features that account for 80% of usage, or 20% of bugs that cause 80% of crashes. Prioritize your time and resources on those vital few for maximum impact.</li><li>Don’t spend the same effort on everything. If a particular area of code is rarely run, it probably doesn’t need the same optimization or attention as a hotspot.</li><li>It's not always exactly 80/20, but the idea is the same. Use profiling, analytics, and data gathering to empirically identify where the imbalances are.</li><li>On a personal level, as an engineer or manager, identify which tasks produce most of your value. It might be coding core features or coaching team members. </li></ul>]]></content:encoded></item><item><title>Cunningham's Law</title><link>https://lawsofsoftwareengineering.com/laws/cunninghams-law/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lawsofsoftwareengineering.com/laws/cunninghams-law/</guid><description>The best way to get the correct answer on the Internet is not to ask a question, it's to post the wrong answer.</description><content:encoded><![CDATA[<p>Cunningham&rsquo;s Law arose in the context of online communities, particularly wikis and forums. The underlying observation is that assertions draw more engagement than questions. On Wikipedia, if someone posts incorrect information, other editors will rush in to fix it.</p>
<p>In software engineering, you see this on Stack Overflow and mailing lists. A user asks a question and gets few responses, but if someone posts a slightly wrong answer, others quickly chime in to correct it. By putting something out there, you transform a passive question into an active discussion.</p>
<ul><li>People online love correcting errors. If you’re stuck on a problem, sometimes proposing a solution (even if it might be wrong) can get you to the right solution faster.</li><li>Asking a question might evoke only silence, but confidently stating something (even if incorrect) often provokes a reaction. </li><li>Instead of endlessly asking “How should we do X?”, propose a draft or prototype. Even if it’s not entirely correct, having a concrete starting point often gets more feedback (“No, not like that, do it this way”). </li></ul>]]></content:encoded></item></channel></rss>