Lessons I Learned after Writing Over 100k Lines of Python
#006 / 5 min read
I have written over 100,000 lines of Python code.
This number increased over the years and across various products, APIs, and scripts. Some were clean. Others ... weren't.
But across all that code, I noticed some patterns starting to emerge.
Here are the biggest lessons I've learned, along with my quick go-to Python practices for writing maintainable, scalable, and performant code.
👋 Hello, I’m Eric! I write and make videos about all things software engineering!
Items after article:
- Codingwithroby update.
1. When Reuse Becomes a Trap
You've probably heard it a hundred times: Don't Repeat Yourself, the DRY principle. And yes, in theory, it's solid advice. But after 100k of lines of Python, I've learned this the hard way:
Premature abstraction can be more damaging than duplication.
Here's why: Abstractions are promises. They imply structure and intention. When you create an abstraction too early, before the patterns are clear, you're locking yourself into assumptions that often don't hold.
Instead, favor this mindset:
- Let duplication live a little. It's often the best way to spot the right abstraction later.
- Wait for patterns to repeat more than three times before abstracting.
- Ask if the abstraction reduces or increases cognitive load.
The goal isn't fewer lines. It's a more apparent intent. Abstractions should feel obvious in hindsight.
2. Make future you, thank you
One of the most humbling lessons I've learned after writing over 100,000 lines of Python isn't about syntax or speed, it's about clarity. Because here's the thing:
Code is read far more than it's written.
When I'm deep in the zone, for some reason, I start using one-liners or slick tricks that feel satisfying in the moment. But fast-forward six months, and that "brilliant" logic becomes hard to solve. I have to debug my one-liners, which is a huge pain.
Readability is what you want to focus on. It's what enables me to move quickly, and it's what distinguishes professional engineers from hobbyists.
So what does that actually look like in practice?
- Name variables like you would when naming functions in a manual.
- Favor explicit logic.
- Organize your code like a professional, even for small projects.
This is how I thank my future self for sticking with whatever my today's project is.
3. The Power of Boring Code
Early on, I used to chase perfection. The shorter the function, the fancier the pattern, the better I felt. This made me feel like a pro!
But after years of scaling Python projects, one thing keeps coming back:
Simple code wins. Almost always.
Why? Because complexity compounds. Clever solutions might impress on day one, but they tend to break and slow everyone down in the future.
The best Python I've written isn't the most clever. It's the stuff that runs, and no one has any questions about it.
Boring code is underrated.
4. The Safety Net I Didn't Know I Needed
I can get away without tests for a while. Things will seem fine. I'll move fast.
Then one day, a refactor breaks. That's when it sucks.
And just like that, I'd regret not writing that test.
If a function interacts with something critical, such as a database, authentication, billing, or user sessions, it deserves thorough testing.
You don't need 100% coverage. You need strategic coverage. The kind that buys you confidence.
Implementing tests can be a pain at the beginning, mainly if you're not accustomed to adding tests to an application. There are three different types of tests that you can implement in your application.
- Unit Tests: Test individual functions or methods in isolation
- Example: Does a calculate_total() function return the correct value?
- Integration Tests: Test how multiple parts of your system work together (e.g., API + database). Do you get the correct response?
- End-to-End (E2E) Tests: Test the entire user flow through the app
Testing isn't just about preventing bugs, it's also about ensuring quality. It's about ensuring your application runs smoothly when no one is available to troubleshoot it.
5. Type Hints Are Underrated
For a long time, I ignored type hints. Python was dynamic, wasn't that the whole point? Typing felt optional, maybe even unnecessary.
But after tens of thousands of lines and dozens of bugs traced back to a wrong assumption, I changed my mind.
Type hints don't slow me down. They save me from myself.
When I start working with:
- APIs that return deeply nested JSON
- Functions that evolve from two to ten parameters
I begin to appreciate the power of static analysis.
If you've avoided typing because it "feels heavy," I'd encourage you to give it another shot.
It's one of the few tools that improves both developer experience and code quality, without adding real friction.
Final Thoughts
Writing 100k lines of Python humbled me over the years.
I see how my old code breaks, scales, or survives. I learned that readability, testability, and structure matter far more than trendy libraries or clever patterns.
And most of all, I learned to build with empathy for my teammates, my future self, and the users who rely on your software.
Keep it simple. Keep it clean. Keep building.
Codingwithroby Update:
- LinkedIn: now has over 40k followers. Thank you to everyone who loves to see the technical content daily. I really enjoy making this content and will continue doing so 🙂.
- Threads / X: I have just started sharing some thoughts on here. If you prefer these platforms check me out. Threads account link and X account link
- YouTube content currently preparing next month's videos. Let me know what you want to see in the future!
- Video released this week:
I can't believe it is already half way through the year. I am expecting my second kiddo in the next two months. Really mind blowing!
Cheers friends,
Eric Roby
Find me online: