When I first started learning DSA I attempted well over 70 problems. I was failing at problems I had attempted 3 or more times. That's when I decided to create CodeMaster - a spaced repetition tool that would track what I got wrong and surface it again until I got it right.
I really did not anticipate how long it would take.
I spent most of my time testing and continuously changing the code. Sometimes it was just too unstable for regular use. I did eventually complete my application. And I have a working app and the same skill level I started with.
That's the paradox. I built a tool to get better at DSA, and building it consumed all the time I could have spent getting better at DSA.
The Checkbox Illusion
I thought shipping would be the finish line. "Once I can see over the hill, I'll be done" was what I thought, and what kept me working ferociously.
Reality: shipping was the starting line. Maintenance, users, bugs, features - all of it was waiting on the other side. A product isn't a task you complete. It's a commitment you maintain.
Now that I'm using it constantly I see so many more opportunities for improvement. What was a bug-infested rent-controlled complex is now less infested and could probably get top dollar on the free market. Too bad it's open source. I keep two versions of the application now - one that's stable for my actual use, and another for continuous integration and improvements. Because I learned the hard way that you can't study on a platform you're actively breaking.
Perfection for Who?
I wanted my application to be perfect before releasing. The drive toward perfection was misguided. I wanted CodeMaster to be successful, and I hoped creating a perfect application would get me there. I wanted it to be all-encompassing, a full learning engine, so I incorporated a lot of moving parts.
I bet you aren't surprised when I tell you I never reached perfection.
I spent so much time on it that it got to the point where I just had to make it public because I actually wanted to get back to learning DSA and applying to jobs. I wanted this application on my portfolio. It just got to the point where I couldn't justify spending more time on it.
The Integration Tax
Each new feature must integrate with everything existing. I wanted CodeMaster to be adaptive to a user's performance. To do that means a lot of integration points. The app barely asks users for input - there's really only one form where we're regularly collecting anything, the problem submission page, and even there two of the inputs are automatically filled from LeetCode.
My session system has 3 layers:
- Layer 1: Spaced repetition engine (FSRS schedule)
- Layer 2: New problem handling (pattern ladders, tag relationships, difficulty scaling)
- Layer 3: Session generation (combining review + new problems)
Seems simple. But there's a 4th layer that integrates between everything else. To control stagnation and session composition I added escape hatches for when a user is stuck on one difficulty of problem. Just recently I fixed a bug where we were creating sessions that were all hard problems. Seeing that annoyed me. I didn't want to even attempt the session, so I waited for it to go stale and trigger the regeneration script to create a new one.
Can you believe I went to check my numbers on the Chrome extension store and it dropped from 5 whole users to 3? All that integration work. For 3 people.
The Paradox Resolved Itself
I spent so long building CodeMaster that I forgot why I was building it. The app was supposed to get me better at DSA. Instead it became the thing I poured all my time into while my actual skills stayed the same.
But now it exists. It works. And I'm finally using it for what it was meant for.
The paradox didn't resolve because I figured out the perfect balance between building and studying. It resolved because I eventually just stopped. Stopped adding features. Stopped chasing perfection for 3 users. Stopped treating the tool like it was the goal. I closed the IDE and opened a problem.
Sometimes the best feature you can ship is the decision to stop shipping features.