Dublin Library

The Publishing project

The Limits of Laziness in Software Development

In this post

One of my favorite quotes about software development comes from Larry Wall, the creator of Perl:

We will encourage you to develop the three great virtues of a programmer: laziness, impatience, and hubris.

Larry Wall, Programming Perl (1st Edition)

The book defines laziness as “the quality that makes you go to great effort to reduce overall energy expenditure. It makes you write labor-saving programs that other people will find useful and document what you wrote so you don’t have to answer so many questions about it.”

I agree entirely. Productive laziness (the drive to build a tool rather than repeat a task) is a cornerstone of good engineering. However, there is a fine line between this virtue and a counterproductive over-reliance on automation. This post explores the limits of laziness, why typing code is rarely the real bottleneck, and what we lose when we let our tools do all the thinking for us.

A familiar pattern of hype

My brand of laziness means I would much rather build a reusable tool or write a definitive guide than repeat myself. But this approach has its limits, especially when a new technology arrives. We often become so beholden to our new tools that we shape our work around the technology, rather than using the technology to improve our work.

This isn’t a new phenomenon; I’ve seen this pattern play out before. In the mid-2000s, people flocked to Second Life, a virtual world buzzing with excitement. The technology was novel, but many projects ignored the fundamental principles of user experience and sustainable design. A decade later, the release of the Oculus Rift in 2016 sparked a second wave of VR enthusiasm. Again, the groundbreaking hardware overshadowed the need for solid planning and design, and most of the initial hype fizzled.

AI is the latest prominent iteration of this pattern. Organizations are adopting AI for tasks from code generation to content creation, sometimes without fully evaluating the requirements, risks, and long-term consequences.

Coding isn’t the bottleneck

The seductive promise of AI is generating functional code from a simple prompt. But this convenience masks a deeper truth: the act of writing code is often the easy part.

While an AI agent can generate code quickly, it offers no guarantee of correctness, efficiency, or security. Developers must review, test, and integrate AI-generated code before pushing it to a repository. To do this, you must still understand the programming language, the frameworks, and the project’s architecture. The time saved on typing is often just shifted to time spent on verification.

The harder constraints in many software projects lie in planning, design, and testing, areas that demand human creativity, empathy, and expertise. We, the developers, remain accountable. This accountability is crucial, because the risks of blindly trusting AI-generated code go far beyond simple errors. They represent massive, hidden liabilities.

Your new partner has a few problems

When we outsource our “laziness” to AI without critical oversight, we run into three severe, real-world problems.

The context-limited assistant

Imagine working with an assistant that can consult project instructions, retrieve repository files, and recall information from earlier sessions, but can process only a limited amount of that context at one time. As a project grows, some goals, architectural decisions, coding standards, or earlier changes can fall outside what the assistant is actively considering. This constraint comes partly from the underlying language model: all current models have finite context capacity, although the amount they can process varies, and the agent’s retrieval and context-management tools affect how effectively that capacity is used.

Workspace instructions, cross-session memory, and access to repository context help, but they do not remove this processing limit. Developers must still identify the context that matters, restate constraints when necessary, and verify that the agent’s changes remain consistent with decisions made elsewhere in the project. For an AI to be a dependable partner, access to context is not enough; it must also select and apply the right context at the right time.

The security and licensing minefield

AI coding tools can generate insecure code, including code vulnerable to SQL injection or cross-site scripting. Developers must review and test generated code using the same security practices applied to human-written code.

AI agents can also reproduce code from third-party projects, including GPL-licensed code, without reliably identifying its source or license. If a commercial vendor unknowingly incorporates GPL-covered code into a proprietary product and distributes it, the vendor may have to release the combined work under the applicable GPL terms, remove or replace the GPL-covered code, or stop distributing the product. Because built-in public-code matching varies among tools and does not replace compliance review, vendors must integrate an intellectual property or license scan into the AI-assisted development workflow or run one manually before release.

The accumulation of technical debt

An AI might solve an immediate problem with code that is overly complex, difficult to read, or completely ignores your project’s established design patterns. While it might “work” today, it creates a maintenance nightmare for the future. This is the exact opposite of productive laziness; it is a shortcut that creates significantly more work down the road when future developers (including your future self) have to spend hours untangling AI-generated “spaghetti code.”

The human in the loop: a real-world example

This isn’t just a theoretical problem. I encountered it directly while trying to save a bit of time on a recent project.

I asked a popular AI assistant for instructions on how to integrate Storybook into an Astro project. The instructions mostly worked, but the agent told me to run npx astro add storybook. That command cannot work because astro add installs official Astro integrations and supported community integrations, and Storybook is neither.

When I pointed this out, the AI insisted it was correct, even after I provided direct proof from package registries. It had hallucinated a solution and was entirely unable to self-correct. In a real project, this kind of confident error could lead to hours of frustrating debugging. It underscores a vital rule: AI can assist, but it cannot replace human judgment.

The path forward: from coder to conductor

These pitfalls don’t mean we should abandon AI. Instead, they signal a fundamental shift in what makes a developer valuable.

The most valuable engineers will no longer be the fastest typists, but the best critical thinkers and system architects. The job is shifting away from manual syntax writing and toward high-level engineering orchestration:

  • Precise prompting: Articulating requirements with clarity, context, and foresight.
  • Critical evaluation: Rapidly reading and assessing AI-generated code for correctness, efficiency, and safety.
  • Skillful integration: Understanding how to cleanly weave isolated, AI-generated pieces into a massive, coherent system.
  • Expert debugging: Diagnosing and fixing complex bugs in code that you didn’t write yourself.

The developer is becoming a conductor, guiding an orchestra of AI tools to produce a symphony, rather than trying to play every single instrument themselves.

Where productive AI laziness shines

This brings us back to Wall’s original virtue. The goal isn’t to avoid AI, but to apply it productively. When used as a deliberate tool instead of a magic wand, AI excels at taking over tedious, repetitive work:

  • Generating boilerplate: Instantly creating skeletons for files, classes, components, or unit tests.
  • Translating and refactoring: Converting a function from one language to another or restructuring existing code before a human reviews it.
  • Explaining cryptic code: Deciphering complex regular expressions or explaining legacy code you’ve never seen before.
  • Automating small tasks: Writing simple, isolated utility scripts for data transformation or file manipulation.

Ultimately, AI is a powerful tool for augmenting our skills, not replacing them. True laziness isn’t about letting a machine think for you; it’s about making the machine do the tedious work so you have more time and energy to do the thinking that actually matters.