Stop Building What Already Exists: The Lazy Dev Mindset
I've seen juniors spend 3 days building a cache layer. The senior rewrote it in one line. Not because the senior is smarter, but because they know what not to build.
The rule
The laziest solution that actually works is the right solution.
That's not the same as cutting corners. It means: before writing code, ask whether you actually need to. Code is a liability. Every line you write is a line someone has to read, debug, and maintain. The less code you write, the less there is to break.
Example 1: Stop writing what shiki already does
This blog needed syntax highlighting for code blocks. Here's what a junior might build:
// ❌ Junior approach: 300+ lines, custom tokenizer
import { tokenize } from './my-tokenizer';
import { applyTheme } from './my-theme';
function CustomCodeHighlighter({ code, language }) {
const tokens = tokenize(code, language);
const themed = applyTheme(tokens, 'github-light');
return (
<pre className="code-block">
{themed.map((line, i) => (
<div key={i} className="code-line">
{line.map((token, j) => (
<span key={j} style={{ color: token.color }}>{token.text}</span>
))}
</div>
))}
</pre>
);
}Here's what we actually did, 14 lines, using shiki which was already in the project:
// ✅ Lazy approach: 14 lines, uses an installed dep
import { codeToHtml } from 'shiki';
async function CodeBlock({ value }: { value: { code: string; language?: string } }) {
const html = await codeToHtml(value.code || '', {
lang: value.language || 'text',
theme: 'github-light',
}).catch(() => codeToHtml(value.code || '', { lang: 'text', theme: 'github-light' }));
return (
<div
className="my-4 rounded-lg overflow-x-auto text-sm [&>pre]:p-4"
dangerouslySetInnerHTML={{ __html: html }}
/>
);
}Before writing anything, check what you already have installed. shiki does tokenization, theming, and language detection. One function call. The lesson: check your installed dependencies before writing a single line.
Example 2: The stdlib does it
Juniors love creating utility classes. A DateFormatter is the classic example:
// ❌ Junior approach: 40+ lines
class DateFormatter {
private locale: string;
private options: Intl.DateTimeFormatOptions;
constructor(locale = 'en-US', options = {}) {
this.locale = locale;
this.options = options;
}
format(date: Date): string {
return new Intl.DateTimeFormat(this.locale, this.options).format(date);
}
formatShort(date: Date): string {
return new Intl.DateTimeFormat(this.locale, { dateStyle: 'short' }).format(date);
}
// ... more methods
}// ✅ Lazy approach: one line, already in JavaScript
new Intl.DateTimeFormat('en-US', { dateStyle: 'medium' }).format(date)JavaScript's Intl API handles locale, formatting, timezones, everything your class was going to rebuild. Before writing a helper, google "{thing} MDN" or "{thing} Node.js docs". The stdlib usually already handles it.
Example 3: You Aren't Gonna Need It (YAGNI)
A junior joins a 2-person startup and builds this:
// ❌ Junior approach: built for a scale that doesn't exist
class UserRoleManager {
private roles: Map<string, Permission[]> = new Map();
addRole(name: string, permissions: Permission[]) { /* ... */ }
removeRole(name: string) { /* ... */ }
assignRole(userId: string, role: string) { /* ... */ }
checkPermission(userId: string, action: string): boolean { /* ... */ }
// ... 80 more lines
}// ✅ Lazy approach: for a 2-person startup
const isAdmin = user.role === 'admin';Build for what's real today. If you get 10,000 users and 5 roles, you'll know exactly what the role system needs to handle. Right now you're guessing, and guessing is expensive.
The decision ladder
Before writing any code, go through this in order:
- Does this need to exist at all? (YAGNI)
- Does stdlib or the native platform already do it?
- Is there already an installed dependency that covers it?
- Can it be one line?
- Only then: write the minimum code that works.
Stop at the first rung that holds. If step 1 kills the idea, great, you just saved yourself days. If step 3 finds the solution, use it and move on.
Lazy is not careless
Lazy is 14 lines that work instead of 150 that might. It's checking what already exists before reaching for your keyboard. It's asking "does this need to exist?" before asking "how do I build this?"
The best code is the code you never had to write.
Recommended for you
- QualityClaude Code
Boring Over Clever: Why Simple Code Wins at 3am
Clever code impresses in code review. Boring code survives production. Here's why the most experienced developers write the most unexciting code, and why you should too.
- QualityClaude Code
AI Agents Are the Most Expensive Junior Devs You'll Ever Hire
The same over-engineering reflex that costs a team two days of junior time now costs you an hour of agent output, multiplied across every PR. The tax rate did not change. The volume did.
- QualityClaude Code
When AI Agents Split Your Codebase Into Too Many Files
The agent's PR has six new files for one small feature. A utils file for one function. A types file for two interfaces. An index.ts that re-exports everything. None of it earns its keep.
Enjoyed this article?
Subscribe for new articles. No spam. Unsubscribe anytime.
By subscribing you agree to receive the newsletter. See the Privacy page.