FAFO: The Art of Learning by Doing (and Breaking Stuff)
Setting aside TDD for a More Hands-On Approach to Coding
There was a time when I swore by Test-Driven Development (TDD). I wrote tests first, watched them fail, and then carefully crafted my implementation until everything turned green—it felt like I was a disciplined software engineer, building things the right way.
But then, something changed. Maybe it was the reality of tight deadlines, the frustration of rewriting tests every time I wanted to tweak something, or maybe I just got tired of pretending I always knew exactly what the code needed to do before I wrote it.
So, I started fucking around instead. And, as expected, I found out.
Now, I embrace what I like to call "Fuck Around and Find Out” (FAFO) Development. It’s not about being reckless—it’s about discovery. Here’s how (and why) I made the shift.
TDD: The Good, The Bad, and The Tedious
To be clear, I’m not here to say TDD is bad. It has its place.
Writing tests first:
✅ Forces you to think through edge cases.
✅ Helps prevent regressions.
✅ Gives you confidence in your code.
The problem is that TDD assumes you already know what your code should do, and if I’m being perfectly honest, a lot of the time, I don’t. Early in my career, much of my work revolved around repeating patterns when adding new features: add new CRUD endpoints for this new database table, trigger a request when the user clicks this button, etc.
As I’ve progressed as a software engineer, my daily work has started to shift away from individual, well-defined/scoped tickets to more research and spikes. TDD is great for building a clearly defined system, but I feel like it gets in the way of figuring out the feasibility of a new system.
Why FAFO Development Works
I recently came across the idea of discovery coding and recognized many similarities with how I’ve approached software development in recent years. It’s all about poking at the problem, letting the system show you its quirks, and adjusting as needed.
Here’s what I love about FAFO development:
1. You Discover What You Didn’t Know You Didn’t Know
Sometimes, the best way to understand a system is to break it and see what happens. Trying things without a rigid test-first approach lets you uncover edge cases organically.
2. You Prototype Faster
Writing tests for every little function before you even know if that function is right? Pain. FAFO lets you move quickly, iterate, and only write tests once you know something is worth keeping.
3. You Embrace the Real-World Messiness of Software
In theory, software is predictable. In practice? You write a function, deploy it, then discover an obscure API behavior or some caching nonsense is breaking everything. FAFO encourages adaptability instead of premature structure.
4. You Become Comfortable with Debugging
TDD prevents helps prevent bugs and defends against regressions. FAFO teaches you how to deal with bugs when you find them. When you spend more time investigating weird behavior instead of avoiding it, you get better at fixing things quickly.
When to FAFO vs TDD
FAFO development can be chaotic if you’re not careful. It’s important to know when it’s safe to be more reckless to aid discovery and understanding and when to be more thoughtful and cautious with your approach.
It’s also worth saying that the process of FAFO still includes writing tests. They can be a great tool to help quickly confirm your suspicions about a system, but you often won’t be writing them during the initial discovery phase.
FAFO is great for:
✅ Prototyping new features.
✅ Debugging unexpected issues.
✅ Exploring unfamiliar codebases.
TDD still shines for:
✅ Large, long-term projects.
✅ Mission-critical applications.
✅ Areas where stability is more important than speed.
Ultimately, the best approach is a hybrid one—knowing when to FAFO and when to bring in the discipline of TDD.
Don’t Be Afraid to Find Out
TDD is great. FAFO is fun. But the real magic happens when you balance both.
If you’re feeling stuck in rigid development patterns, I encourage you to fuck around a little more.