
Learning to Code With AI Without Losing the Struggle
Back with another one in the series where I write about the arguments we have while building Levelop, and this one is less about an algorithm than about a decision we could not avoid: what should an AI actually do at the moment someone is trying to learn?
I kept watching the same pattern repeat. A learner gets stuck, pastes the problem into a chatbot, receives a clean working solution within seconds, and moves on convinced they have made progress. They finished the problem without ever learning it, so when the same shape of question resurfaces a week later they are stranded in precisely the same place, faster than ever yet no better than before. That gap is the entire reason this post exists, because learning to code with AI is not the same activity as letting artificial intelligence write the code for you, and the difference is easy to miss when both paths feel productive in the moment.
The part that was bugging me
What specifically bothered me is that when I learned to code, the slow part was the valuable part. Sitting with a bug for an hour, forming a wrong theory, testing it, watching it collapse, and gradually isolating what was actually happening felt like wasted time, yet that hour was quietly assembling the intuition I now rely on without thinking. AI compresses that hour into a single query, and when you delete the hour you also delete whatever it was constructing, leaving the learner holding a correct answer and none of the underlying wiring that was supposed to grow while they reached for it.
So the real question was never whether AI is good or bad for learning, a framing too broad to act on. The useful question is narrower: which parts of the struggle are worth protecting, and which parts are merely friction we can safely automate away?
Why the struggle is not just suffering
Learning research already has a name for this. Robert Bjork at UCLA describes desirable difficulties, conditions that make acquisition feel harder and slower in the moment while producing substantially stronger and more durable understanding, which is why effortful retrieval outperforms passive review and generating an answer yourself outperforms being handed one. That final principle carries its own label, the generation effect: when you produce something through your own effort, even a partly incorrect attempt, you retain it far more reliably than material you simply read, a result Slamecka and Graf documented in 1978 that has survived decades of replication.
Combine those two findings and an uncomfortable conclusion follows. The friction embedded in problem solving is not a defect in the process, it substantially is the process, so when a tool erases that friction it frequently erases the learning riding on top of it. This is the central trap of using AI to learn to code, because artificial intelligence is engineered to minimize friction, and for a working professional minimizing friction is exactly the objective. GitHub has reported that developers using its coding assistance completed a benchmark task roughly 55% faster in one of their studies, which is a genuine victory when you are shipping features in production software development. For someone still constructing the mental model, however, speed is not the goal, the model is the goal, and nobody constructs a model by watching another entity assemble it.
Augment the learner, do not replace the struggle
The principle we settled on at Levelop is trivial to state and genuinely difficult to implement: augment the learner, do not replace the struggle. Augmentation means stripping away the friction that teaches nothing, while replacement means dissolving the friction that teaches everything, and the entire craft lies in distinguishing the two under real conditions.
Some friction is pure noise, including configuring a development environment for the fifth time, recalling the argument order of an obscure standard library function, or fighting a cryptic build error unrelated to the concept in front of you. None of that develops durable skill, so delete it, and let AI tools delete it, freeing the learner to spend scarce attention where it compounds. Other friction is the actual lesson: choosing which data structure fits, reasoning about why a first approach runs in O(n squared) and what to restructure, tracing a recursive call and predicting its output before execution, or debugging your own broken logic rather than your own typo. When a tool performs that work for you, it has not helped you learn to code, it has simply completed your repetitions while you spectated.

What this looks like in practice
Concretely, the principle governs what the AI is permitted to say and precisely when it may say it. When a learner stalls, the wrong move is surrendering the finished solution, whereas the right move mirrors what a strong mentor does: pose a question that advances them one step, indicate the line where their assumption fractures, or offer a reduced version of the problem they can solve unaided, keeping the answer close enough to sustain momentum yet far enough that reaching for it remains their own work.
Consider the difference in literal terms, starting from a slow two-sum attempt a learner has written.
# The learner's first attempt, brute force
def two_sum(nums, target):
for i in range(len(nums)):
for j in range(i + 1, len(nums)):
if nums[i] + nums[j] == target:
return [i, j]The replace-the-struggle response generates the optimal hash-map version and moves on, the learner pastes it, the tests pass, and nothing durable survives. The augment-the-learner response instead asks something nearer to this: your loop inspects every pair, which explains why it degrades on large inputs, and since you have already computed the value at i, what would you need to remember so that on reaching j you already know its partner exists? The learner sits with that prompt, independently reaches for a dictionary, and the pattern becomes permanently theirs. The volume of AI assistance is identical across both cases, yet the outcome diverges completely, and the reliable tell is whether the learner could rederive the answer tomorrow unaided: if yes, the artificial intelligence augmented them, and if no, it quietly replaced them.
But will AI replace programmers anyway?
This is the objection I encounter most, usually compressed into some form of will AI replace programmers, so why endure the struggle of learning at all, and it is a fair anxiety that deserves a direct answer rather than a comforting one. Nobody credibly knows the timeline, but I am reasonably confident about its shape, because the value of a developer is migrating away from producing lines of code and toward judgment: deciding what deserves to be built, catching the subtle defect the model introduced with total confidence, and recognizing when generated code is wrong for reasons the model cannot perceive. That judgment is precisely what the struggle manufactures, so as code generation grows more capable the genuinely scarce skill becomes understanding code deeply enough to direct and correct it.
Which means the answer to should I still be learning to code with AI in the room is emphatically yes, and the reason is not nostalgia. If you delegate your thinking to the tool while you learn, you graduate into a software engineering market that only compensates thinking, whereas practicing learn to code with AI in a disciplined way is exactly how you arrive on the productive side of that shift instead of the replaced side.
The honest tension we still live with
I am not going to pretend we have solved this cleanly, because a real tension is baked into the design. A learner in the moment wants the answer, and when they are frustrated and it is late, the tool that simply surrenders it feels more helpful than the one issuing another question, so in the short term replacing the struggle earns better reviews than protecting it does. Part of the job, then, is engineering the productive path to also feel good rather than merely be good, because a hint that lands at the right instant feels like a mentor who understands you while a dumped solution feels like a vending machine. We would rather remain the mentor even on the days the vending machine would score higher, since the learner who struggles briefly and genuinely gets it is the only version of this that still functions a month later. That is the bet: augment the learner, do not replace the struggle, even when the struggle is the less popular product in the moment.
Frequently asked questions
Is it bad to use AI while learning to code?
No. Using AI tools to learn to code is fine and frequently excellent. The problem arises only when artificial intelligence replaces the specific effort that builds understanding, such as reasoning through logic or debugging your own code, so deploy it to remove noise rather than to skip the thinking.
What is the difference between AI augmenting a learner and replacing them?
Augmenting removes friction that teaches nothing, like environment setup or syntax lookup, while replacing removes friction that teaches everything, like choosing an approach or tracing a bug. A simple test settles it: if you could not rederive the answer tomorrow unaided, the AI assistance replaced you rather than helping you.
Will AI replace programmers, so is learning to code still worth it?
Learning remains worth it. As code generation absorbs more routine work, the scarce skill shifts toward judgment, deciding what to build and catching what the model gets wrong, and that judgment emerges from exactly the struggle people are tempted to skip, which makes deep understanding more valuable rather than less.
How should a beginner use AI to learn to code?
Attempt the problem yourself first, and when stuck request a hint or a smaller version rather than the full solution, while using AI tools freely for setup, documentation, and error messages. Keep the core reasoning and debugging as your own work, because that is the portion doing the teaching.
Does using AI make you a worse programmer?
It can, if you let it complete your repetitions while you spectate, yet it can equally make you sharper if you use it for faster feedback and to remove busywork. The outcome depends entirely on whether you protect the effortful parts of learning to code with AI or hand them away.
Where this comes from
This is the philosophy underneath how we build Levelop, shaping everything from how hints surface to why we require an attempt before revealing help. If you want the rest of how we think about coding assistance and pedagogy, the Levelop blog has more, including a longer piece on what building an AI mentor taught me about how engineers actually learn.
