What Makes a Good Developer
After 15 years in software development, I've seen what separates good developers from mediocre ones. It's not about knowing every framework or memorizing syntax—it's about fundamental practices that compound over time.
Here's what I think really matters.
1. Get Down to the Root Problem
Like any engineer, a good developer doesn't just fix symptoms—they dig until they understand what's actually wrong. This is harder than it sounds.
I've seen developers slap on a quick fix without understanding why something broke in the first place. A week later, the same bug appears in a different form. Or worse, their "fix" creates three new bugs because they didn't understand the underlying system.
Example: Your app is slow. The knee-jerk reaction might be to add caching everywhere. But what if the real issue is an N+1 query problem in your database? Or inefficient re-renders in your React components? You need to measure, profile, and understand before you start throwing solutions at the wall.
Tools I use: Browser DevTools Performance tab, React DevTools Profiler, database query analyzers. Don't guess—measure.
Common mistake: Jumping straight to Stack Overflow and copying the first answer that "works." You might fix your immediate problem, but you've learned nothing and you'll hit the same wall next week.
2. Read the Documentation Properly
This sounds obvious, but most developers don't actually read documentation—they skim it, looking for code examples to copy-paste. That's not reading.
Good developers read the docs to understand how something works, not just to get it working. There's a massive difference.
Example: When I first learned React hooks, I could've just memorized "useState for state, useEffect for side effects" and moved on. Instead, I read the React docs thoroughly—understanding the dependency array, the cleanup function, and why hooks can't be called conditionally. That foundation saved me countless hours of debugging later.
Pro tip: When you encounter a library or API, resist the urge to immediately jump to tutorials. Start with the official docs. They're usually better than you think, and they'll give you the mental model you need.
Common mistake: Relying entirely on blog posts and tutorials. These can be helpful, but they're often outdated or show only one specific use case. The official docs give you the complete picture.
3. Use Tools to Keep Your Code Clean
Your brain should be focused on solving problems, not remembering where to put semicolons or whether to use single or double quotes. That's what tools are for.
Linters catch bugs before they happen. Formatters ensure consistency. Type checkers prevent entire categories of errors. These aren't nice-to-haves—they're essential.
Example: ESLint catches issues like unused variables, missing dependencies in useEffect, and potential null reference errors. Prettier formats your code consistently so you never waste time in code reviews arguing about tabs vs spaces. TypeScript catches type mismatches before they become runtime errors.
My current setup: Biome (combines linting and formatting), TypeScript, and pre-commit hooks with Husky. Set it up once, forget about it.
These tools also make collaboration easier. When everyone's code looks the same and follows the same rules, code reviews focus on logic instead of style.
Common mistake: Thinking these tools slow you down. They don't—they speed you up by catching issues early and eliminating decision fatigue.
4. Write Clear, Clean Code
Code is read far more often than it's written. If you write code that only you can understand, you've failed—even if it works perfectly.
Clear code doesn't need comments to explain what it does. Variable names are descriptive. Functions do one thing. Logic is straightforward.
Example: Compare these two approaches:
Bad:
const d = new Date();
const x = d.getTime() + 86400000;
if (u.lt < x) { /* ... */ }
Good:
const now = new Date();
const oneDayInMs = 24 * 60 * 60 * 1000;
const tomorrow = now.getTime() + oneDayInMs;
if (user.lastLogin < tomorrow) { /* ... */ }
The second version takes three more lines, but it's immediately clear what's happening. Future you (and your teammates) will thank you.
Common mistake: Optimizing for "clever" code instead of readable code. A one-liner that takes five minutes to understand is worse than five lines that are instantly clear.
5. Test Your Code
I know, I know—writing tests feels like extra work. But untested code is a ticking time bomb.
You don't need 100% test coverage. But critical paths, complex logic, and anything that handles user data should have tests. Not just to catch bugs now, but to prevent regressions when you refactor later.
Example: I once spent an entire day debugging a payment processing issue in production. The fix took five minutes—the problem was a simple edge case I hadn't considered. A single test would have caught it before it ever shipped.
Start small: Don't try to test everything. Start with unit tests for utility functions and integration tests for critical user flows. Build the habit first.
Common mistake: Only testing the happy path. Real bugs live in edge cases—empty arrays, null values, network failures, concurrent requests.
6. Communicate and Collaborate
Development isn't just sitting alone in a dark room typing. It's working with designers, product managers, and other developers. Communication matters.
Write clear pull request descriptions. Leave helpful code review comments. Ask questions when requirements are unclear. Document your decisions.
Example: When reviewing code, don't just say "this is wrong." Explain why it's wrong and suggest an alternative. Better yet, ask a question: "Have you considered how this handles concurrent requests?"
Common mistake: Assuming everyone has the same context you do. They don't. Be explicit.
7. Keep Learning
Technology changes fast. What worked five years ago might be an anti-pattern today. Good developers stay curious.
But learning doesn't mean chasing every new framework. It means understanding fundamental concepts deeply. Learn how JavaScript's event loop works. Understand HTTP and networking. Study data structures and algorithms—not to pass interviews, but because they make you a better problem solver.
Common mistake: Learning frameworks without understanding the underlying principles. Frameworks come and go, but fundamentals last.
Final Thoughts
Being a good developer isn't about being the smartest person in the room or knowing every new tool. It's about being disciplined, thorough, and thoughtful.
Dig deep to understand problems. Read documentation properly. Use tools to maintain quality. Write code that others can read. Test what matters. Communicate clearly. Never stop learning.
These aren't shortcuts—they're fundamentals. And fundamentals compound over time.