I have 143 commits in one codebase, 69 in another, and 23 in a third. Same project, three different versions, three completely different philosophies. And the journey between them taught me something that changed how I code forever.
The Winter Storm That Started Everything
For three intensive months during the winter storms, I've been working with Claude and Claude Code—building, iterating, learning. The first project was something I genuinely needed: MacRetriever, an application that indexes my entire Mac and lets me find anything in milliseconds. No more digging through folders. No more lost files.
The problem? I had no idea how to build it when I started.
But once I got something working—even something rough—I couldn't stop. I'd build a feature and think, "what if we also added..." and suddenly I'm adding Gmail integration, import from repositories, advanced search with custom filters, photo indexing, email classification. Just one more feature. And one more. And one more.
The code grew. The features multiplied. The functionality became incredible.
And then I realized: I've built something amazing that I can barely maintain.
That moment of realization—when you have great functionality but an unmaintainable codebase—that's the turning point. That's when most developers either give up or get serious about quality.
I got serious. And this is the story of that evolution.
Most developers go through the same growth pattern—but nobody talks about it. We hide the messy version, we skip the story of how we got here, and we pretend we just knew better from the start. So let me tell you the real story instead.
The Pattern Nobody Talks About
Every developer follows three phases:
- "Does it work?" ← You are probably here
- "What can it do?" ← Most people get stuck here
- "How should it work?" ← This is the goal
The metrics are different. The code quality is different. But the mindset? That's the real evolution.
Let me show you through my own codebase, tracking three generations of the same application.
Phase 1: "Does It Work?" (Deep_Me5)
This is where I started. I had no idea what I was doing.
"I was just trying to get something to work. Something I had no idea how to get working in the beginning. I was only focused on functionality—what it did, not how it did it."
The Reality:
- No experience with desktop applications
- No architecture plan
- No design patterns in mind
- Just trying to make anything work
What the code looked like:
- 59 files, 26,490 lines of code
- Average file size: 449 lines
- Complexity rating: 31.1
- Largest file: 2,678 lines (no, that's not a typo)
Why it was like that:
When you're learning, you don't know where to put things. You don't know what "good structure" means. So you write until something works, and then you move on to the next feature. The "messy" code isn't a failure—it's the natural result of learning in public.
The Lesson:
If you're in this phase right now—if your code is dense, your functions are long, and your files are huge—that's not a personality flaw. That's learning. The goal at this stage isn't perfection. The goal is understanding the domain well enough to build something real.
Ship it. Learn from it. Improve next time.
Phase 2: "What Can It Do?" (MacR)
Then I got confident. Maybe too confident.
"Then when I went to MacR, it was adding more and more stuff—adding Gmail, adding loading from repositories, adding stuff, adding stuff just to see what was possible. Then I realized I'd created a complex team monster."
The Reality:
- Excitement about possibilities
- Every feature became "let's try it"
- No thought to maintenance
- The question became "can we do THIS?" instead of "should we?"
What happened to the code:
- Files DOUBLED: 59 → 142 files
- Code DOUBLED: 26K → 50K lines
- Worst files got WORSE: 2,678 → 2,968 lines
- Setup wizard alone grew 920 lines in one version
This is the phase where "move fast and add things" hits its limit. You're learning what's possible in your domain. And yes, you're creating a monster in the process. But that monster is teaching you something important: where the boundaries should be.
Why this happens:
At this stage, you've proven you can build things. So you build more things. You're not worried about quality yet—you're proving capability. It's feature exploration, not engineering.
The Lesson:
If you're in the "add everything!" phase—if your codebase is growing faster than you can organize it—congratulations, you've earned the right to feel lost. This phase is necessary. It teaches you that more features don't equal better code. The question "what can we do?" only makes sense if you eventually ask "what should we do?"
The "monster" phase is your permission slip to stop and refactor.
The Catalyst: The Icon That Changed Everything
Here's where most stories skip ahead. They say "and then I refactored everything" without explaining why.
The real reason? It wasn't the complexity. It was an icon.
"The reason I fixed it with PyQt wasn't because of the complexity—it was because there were certain limitations in Flet which I didn't like. Specifically, I couldn't create a custom icon in Flet and just got the stupid otter icon from Flet's library."
This is important.
The best refactorings often don't start with "let's fix the technical debt." They start with "I don't like this." A small frustration. A UX annoyance. Something that makes you go, "you know what, I'm going to fix this."
And once you're fixing one thing anyway... might as well fix everything else too.
The Lesson:
Don't wait for the perfect moment to refactor. Wait for the small annoyance that motivates you to start. Your instinct about "this feels wrong" is often right, and it's a better trigger than any metric.
Phase 3: "How Should It Work?" (MacR-PyQt)
This is where everything changed.
"By then I'd created other apps in PyQt6 and had got more sophisticated. I was learning about module sizes and complexity and stuff like that, and was more concerned with how the code worked than that it did."
The Shift:
- Mindset changed from "does it work?" to "is it well-structured?"
- I'd built other projects in the same framework, learned patterns
- Started thinking about metrics, module sizes, complexity
- Refactored the services first, then tackled the GUI
- Multiple attempts (some failed), but the focus stayed on quality
What the code looked like:
- Files: 142 → 123 (reduced)
- Code: 50K → 30K lines (40% reduction)
- Largest file: 2,968 → 1,114 lines (62% smaller!)
- Complexity: 25.3 → 18.0 (29% improvement)
- Every single metric improved
This isn't just "better code." This is code written by someone who knows what they're doing.
The Lesson:
Maturity in programming isn't about knowing more syntax. It's about caring about how code works, not just that it works. And here's the crucial part: you can only get to this phase by going through the other two first.
You can't skip from "just make it work" to "here's the perfect architecture." The messy phase teaches you what clean means. The exploration phase teaches you what simple means.
The Three Phases Visualized
| Phase | Mindset | Focus | Code Quality | Metrics |
|---|---|---|---|---|
| "Does it work?" | Beginner | Functionality | Whatever works | 449 LOC/file, 31.1 complexity |
| "What can it do?" | Explorer | Features | "We'll fix it later" | 356 LOC/file, 25.3 complexity |
| "How should it work?" | Craftsman | Architecture | Deliberate quality | 249 LOC/file, 18.0 complexity |
Each phase is necessary. Each one teaches you something the last one didn't.
Why This Story Matters
For beginners in Phase 1:
If your code is messy right now, that's normal. You're not a bad developer. You're a learning developer. Every expert was once a beginner who wrote code that made them cringe. The difference is they kept going.
For explorers in Phase 2:
If you're adding features and creating "monsters," that's necessary. You need to know where the boundaries are before you can architect elegantly. Your exploration is creating the knowledge you'll use in Phase 3.
For craftspeople in Phase 3:
If you're refactoring, caring about metrics, thinking about architecture—congratulations. But remember: you could only get here by stumbling through the other phases first. Experience isn't taught. It's earned.
The Numbers Don't Lie
Here's what changed between Phase 2 and Phase 3:
Code Reduction: 50,602 → 30,628 lines (-39%)
- Deleted dead code
- Removed framework boilerplate
- Broke up mega-files
- That's not just "cleaner"—that's 40% less to maintain
Complexity Reduction: 25.3 → 18.0 average (-29%)
- Fewer branches per function
- Clearer logic flow
- Easier to understand
- Fewer hiding places for bugs
File Size Reduction: 2,968 → 1,114 (largest file, -62%)
- Setup wizard went from one massive file to modular services
- Each file does one thing well
- Easier to test, easier to modify
These aren't just numbers. They're measurements of understanding. Each metric represents a decision to care about quality.
The Real Lesson: Metrics + Context = Understanding
The metrics alone tell you: "Complexity decreased from 25.3 to 18.0."
The human story tells you: "I learned to care about HOW, not just WHAT."
Together, they tell the complete story:
- The metrics prove the improvement is real
- The narrative explains why it happened
- The combination teaches others how to grow
This is why I tracked both. Numbers without story are just numbers. Story without proof is just talk.
Your Journey Will Look Different
The pattern is the same:
- Make it work
- Make it feature-rich
- Make it right
But your triggers will differ.
Maybe you hit a performance wall instead of an icon limit. Maybe you onboard a teammate and a code review reveals issues. Maybe you revisit code after 6 months and can't understand your own work.
The important thing: Each phase is necessary. You can't skip steps. The messy phase teaches you what clean means. The complex phase teaches you what simple means. The monster phase teaches you what elegant means.
What This Means for Your Next Project
Start with quality awareness — Set file size limits from Day 1. Not perfection, just awareness.
Embrace exploration — You need to discover what's possible before you architect elegantly. The monster phase is a feature, not a bug.
Use your framework — Some frameworks enable bloat, others enforce structure. Choose wisely.
Metrics are your friend — You can't improve what you don't measure. Track complexity, file sizes, function length from the start.
Migrations are opportunities — When you're moving to a new framework or platform anyway, don't just port—rethink.
The Journey Never Ends
This isn't the end of the story. This is just Phase 3 of this particular project.
There will be Phase 4 projects. And Phase 5. Each one will teach me something new. Each one will make me better.
But the pattern stays the same:
- First, make it work
- Then, make it powerful
- Then, make it beautiful
And if you're just starting out, remember: every expert has a messy Phase 1. Yours is just starting now.
Keep going.
What phase are you in right now? Drop a comment—I'd love to hear about your own journey through these phases.
About This Journey
I'm a 74 year old Boomer, and for three intensive months during the winter storms, I've been working with Claude and Claude Code—building, iterating, learning. I built MacRetriever, an application that indexes my entire Mac and lets me find anything in milliseconds. Through that journey, I discovered something fundamental about how code—and developers—grow.
Why am I sharing this? Because the software development community loves to pretend we start perfect. We don't. The journey from "Does it work?" to "How should it work?" is messy, important, and usually invisible. By sharing mine—complete with the ugly metrics—I want to normalize the learning process and show that refactoring isn't failure; it's growth.
The MacR Experience Changed Everything
When I hit that "Phase 2 vs Phase 3" crisis with MacR—when I realized I'd built something powerful but unmaintainable—I didn't just refactor the code. I learned a lesson that led me to build something bigger.
That experience taught me that developers need visibility into code quality, not as a punishment, but as a compass. Metrics without context are just numbers. Context without data is just storytelling. Together, they're actionable intelligence.
This realization became Claude Command Centre (C3) — a sophisticated development orchestration platform built specifically to solve the problems I faced:
- CC Cleanup — Automatically identify and refactor code quality issues before they become crises
- Code Metrics — Real-time visibility into complexity, file sizes, and architectural health (like the Observatory tool that generated this report)
- Multicycle CC Orchestration — Run multiple code refinement cycles while retaining context across iterations, so AI agents can learn from previous decisions and improve progressively
C3 is what I wish I'd had during the MacR phase. It would have caught the "mega-file" problem earlier. It would have guided me through the refactoring with data-driven decisions. Most importantly, it would have preserved the context across all 23 commits of the PyQt migration.
This is why I'm building. Not to sell tools, but to democratize the kind of code quality infrastructure that used to only exist at big tech companies. Every developer deserves to see their code the way I see mine now—not through guilt, but through understanding.
The three phases are universal. The tools to guide them through each phase shouldn't be.
About This Article
This article was created and published by the **Silver Wizard SW Brand Manager Agent, with creative input, technical research, and architectural insights from the **Enterprise Architect Agent* (EE). It's a collaboration between AI agents working together to tell the story of how code quality metrics, developer growth patterns, and thoughtful refactoring practices led to building better tools for the entire development community.*
Resources
- Keeping code quality high as you ship fast (coming next)
- How to refactor without breaking everything (coming soon)
- Observatory: The tool I used to track these metrics (repo coming)
Top comments (0)