DEV Community

Mánu Fosela
Mánu Fosela

Posted on

The Hardest Part Isn't AI. It's Us

In the first article I talked about how AI is shifting our work toward a higher level of abstraction: increasingly less focused on writing the how and more on deciding what we want to achieve. In the second, I tried to answer the inevitable question: if we’re going to delegate more and more work to agents, how do we do it without having to blindly trust them? My answer was to build governance systems around them: external rules, verification mechanisms, guardrails and orchestration.

In this one, I want to address something just as important, if not more so: how to lead this change. Because we can solve those two problems perfectly and still fail.

Get comfortable, because this article is long.

Companies don’t change when we install a tool, or when we adopt a different way of working. They change when the people working in them change and their culture, or part of it, changes too, not because the company loses its essence, vision, mission or values, but because it evolves. And this is where we probably enter the most complicated part of the game.

Writing code is starting to become the easy part

Right now, and even more so in the future, it increasingly looks like “writing code” is going to be the easy part. Careful! I’m not saying that developing software is easy. Not even close. I’m saying exactly the opposite. Writing the code is becoming the part we can delegate most easily. The hard part is starting to move somewhere else.

Understanding what needs to be done. Understanding the domain. Designing it. Choosing between alternatives. Knowing what consequences a decision might have. Measuring it. Testing it. Operating it. Maintaining it. Knowing whether it actually solves the problem we wanted to solve. And above all, being able to look at something an AI has built, verify that it works perfectly and say: “This works, but it’s wrong”. And even more importantly, being able to explain why.

DISCLAIMER: the following example is there to illustrate what I mean in the simplest possible way. Software engineering scholars, please refrain from nitpicking it. Don’t look at the finger. Look at the moon.

For example (JavaScript code). Imagine you come across this:

  function isDigit(value) {
    if (value === 0) return true;
    if (value === 1) return true;
    if (value === 2) return true;
    if (value === 3) return true;
    if (value === 4) return true;
    if (value === 5) return true;
    if (value === 6) return true;
    if (value === 7) return true;
    if (value === 8) return true;
    if (value === 9) return true;
    return false;
  }
Enter fullscreen mode Exit fullscreen mode

It works. You give it a value and it tells you whether it’s a digit. It can perfectly pass every test we’ve defined.

And yet, almost anyone with some experience will probably stare at it for a few seconds and think: “Do we really need ten ifs to express this?”.

I’m sure that while you were reading it, you were already thinking of another way to do it. Maybe even several. And we’d probably end up debating which one is better.

Well, that’s exactly what I’m talking about.

Not that this function is going to break production or that it is objectively incorrect. It is deliberately a ridiculously simple example. I’m talking about that ability to look at a solution that works and ask yourself whether it is a good solution, whether it expresses properly what we want to do and whether there is a better way to solve it. A solution can satisfy every criterion we’ve checked and still be badly designed. It can do unnecessary work. It can introduce coupling we don’t need. It can add absurd complexity. It can introduce a decision today whose cost we won’t see until we have to modify, operate or maintain that part of the system. It can be insecure. It can work and still be shit.

That’s judgment. And it’s something we’ve so often seen AI lack, precisely because it has been trained on all the code in the whole damn world, where we upload every kind of code imaginable.

In the first article I said that our work is shifting upwards. I think this is one of the places it’s shifting to. And if that is going to become one of the main sources of value of a software engineer, another problem immediately appears: how do we help those who already have that judgment move it into this new way of working, and how do we train those who don’t have it yet? That is one of our biggest challenges. And it isn’t technological. It’s human.

“You’re taking away what I love doing: programming”

Put yourself in the shoes of someone who has spent five, ten, fifteen or twenty years programming. Depending on when they started, they probably didn’t choose this profession only because it paid well, although we have lived through a “golden age” in which many people moved into software development because there was plenty of work and it paid well, and many of them also discovered their passion thanks to that. Most people who program do it because they enjoy programming. Not necessarily outside working hours too, although quite a few of us do ;)

What we tend to have in common is that we enjoy facing a problem. Thinking of a solution. Writing a function that is efficient and elegant at the same time. Finding an abstraction. Removing twenty lines and turning them into five while somehow making the code more readable. Building something useful for someone else. Looking at something you’ve just finished and thinking: “I am God”. Let’s ignore those other occasions when we think we chose the wrong profession and are completely useless at this :P

Then the first traces of AI appear. Autocomplete. Suggestions for methods, functions, classes. We start asking it for larger pieces, with varying degrees of success. We start using it to get past the blank page. To write tests for us. It finds bugs and saves us hours of debugging. But it’s still an assistant. A helper. Support.

And then someone comes along telling you about the wonders of agentic development, that AI can write the code, and tells you that, if everything evolves the way it seems to be evolving, programming the way we have until now will gradually become less necessary. Well. I wouldn’t exactly expect people to jump for joy.

I think one of the things we do wrong when talking about AI adoption is minimising this. We treat it as resistance to change. Irrational fear. People who “don’t want to adapt”. And part of it may be that. But another part isn’t. Mainly for two reasons: disappointing experiences with “the technologAI” and a very real sense of loss. The feeling of becoming a secondary actor. Of losing the thing you’re good at and that gives you identity. Even of becoming expendable.

Grief

If you’ve spent years building a professional identity around something and that something starts to change, there is a kind of grief involved. I think we need to say it. Something is lost. Something dies a little bit inside our “soul”. Because in all likelihood we will gradually write less code manually. Many of the things that give us professional satisfaction today will slowly stop being part of our everyday work. Pretending that isn’t happening doesn’t help.

But I don’t think craftsmanship disappears either. I think some of that craftsmanship also moves upwards and some of it, the more romantic part, will continue “weaving by hand” every line of code when efficiency, quality or the problem itself justify it. The pleasure of writing an especially efficient and readable line of code may turn into designing an especially efficient and scalable architecture. Finding a simple way to solve a complex problem. Defining an acceptance criterion that catches twenty incorrect solutions. Spotting a consequence nobody else had noticed. Being able to look at five proposals generated by agents and understand which one makes sense and why. Or even realising that we’re perfectly building something nobody actually needs.

Most of us will gradually stop being craftspeople of code. But we may become another kind of craftsperson: of products, systems and impact. And that doesn’t happen automatically because someone gave us access to Claude or Codex. We have to help people make that transition.

Understanding doesn’t mean accepting that someone stands still

This is where, for me, an idea I’ve tried to apply for years when leading people comes in. You can perfectly understand why someone is afraid, why they feel threatened, or why they don’t want to abandon a way of working they master or feel comfortable with. And at the same time clearly tell them that they need to explore it, consider the new paradigm and accompany them while they do it. Those positions aren’t contradictory. Understanding doesn’t mean lowering expectations. Neither does supporting someone.

In the way I understand leadership, which I call affective leadership, I build relationships with the people I lead and put emotions at the same level as objective considerations, so I don’t avoid uncomfortable conversations. I initiate them when they are necessary, because allowing a problem to fester isn’t caring for someone either. If I believe someone may be left behind professionally, my responsibility isn’t to reassure them by saying nothing is going to change. It’s to help them prepare for the change.

And I don’t think the answer is to tell someone “adapt or you’ll be left behind” either. That’s not leadership. That’s dumping the problem on them and leaving them alone. Leading this transition means explaining where I think we’re going, listening to where each person is, what they think and feel, understanding what they need and building a path so they can get there. But the destination can’t disappear from the conversation just because talking about it is uncomfortable.

Don’t evangelise by selling “magic”

I also think there’s a common mistake among those of us who adopt these tools early. We get excited and start evangelising.

“This is insane!”
“I’m ten times faster”
“I barely program anymore”
“I did in one afternoon what used to take me a week”

It may be true. I’ve experienced it myself. But then somebody tries exactly the same tool, has a horrible afternoon and thinks you’ve sold them bullshit. Because we forget the details. How many hours did you spend experimenting and failing before you got there? How many prompts, specs, skills, “MCPs”... did you try and discard? In other words, what price did you pay to get where you are? (pun very much intended)

And there will be bad days too. The agent will stubbornly insist on some absurd solution. A model update will change something that worked. The context will be wrong. The provider will go down. Something will get through controls you thought were sufficient. None of that invalidates the direction. It means we’re working with a technology that is still evolving at a brutal pace.

If we promise “magic”, every failure destroys trust. If we explain that we’re building a new way of working that still has problems, every failure can become an opportunity to learn. We don’t need believers. We need engineers experimenting, learning and building judgment around this new way of working. And we also need to understand that not everyone is at the same point. For someone who feels they’re training the thing that’s going to “take their job”, experimenting with all this can be extremely uncomfortable.

You don’t leave the office on Friday as a code craftsperson and come back on Monday morning having changed professions. We’d be making a mistake if we thought someone who has spent fifteen years developing in a certain way is going to change because we install a tool, give a talk and write a “Notion” explaining that now we’re AI-first. The transition has to happen while working.

First, without a doubt, we need to build the governance structure, which serves both AI and humans. An environment that guarantees nobody can screw things up. Then maybe you delegate the things that bring you the least value. Then a small implementation. Then a whole task. You start reviewing plans before the agent writes anything. You start worrying less about exactly how a particular function was implemented and more about whether the complete solution makes sense. Little by little, you stop being inside every line and start sitting above the system. And one day you realise you’ve spent hours developing software without writing much code at all, and that the code it generated meets all the requirements for quality, efficiency, security... just like your best code.

That change shouldn’t be imposed as a surrender. We should help each person discover where their value lies now. A senior who has spent fifteen years programming has an enormous amount of knowledge and experience that isn’t stored in their fingers. It’s in all the shit they’ve been through. In those migrations that went wrong. In that wonderful architecture that six months later nobody knew how to maintain. In that optimisation nobody actually needed. In that ridiculous bug that reached production and nobody spotted. In that technically perfect product or feature that nobody used. That is exactly what we can’t afford to lose when we delegate writing code to AI. We need to apply that judgment to what AI produces.

The problem is that we have to learn while still delivering

This is, for me, one of the most interesting organisational problems. We have to adopt a new way of developing software, but the company can’t stop developing software while we learn. We can’t say: “For the next six months we’re not shipping anything because we’re training everyone on AI”. We have to do both at the same time. Learn and deliver. Accepting that is no small thing.

For a while, we may have to accept a percentage drop in productivity while trying to learn how to become dramatically more productive. And that’s something the company has to accept if it doesn’t want to be left behind. Someone will reasonably ask: and how do I know whether that bet is paying off? Not by the number of tokens we’re spending or the number of lines we’re writing. You start seeing it when more work reaches production with fewer errors. That’s the signal that we’re learning to become more productive, rather than merely faster. And for that, you should already be measuring the impact you have now so you can compare it with the impact you’ll have later.

And I think platform engineering and developer experience teams play a fundamental role here. If your company doesn’t have them yet, you’re already late :P

And during the process we’ll get things wrong. We’ll try tools that we abandon two weeks later. We’ll build processes that are too complicated. We’ll swing too far in the opposite direction. We’ll come back. And we’ll encounter another problem: the technology we’re trying to learn isn’t standing still. While we move forward step by step, models improve, tools change and agents acquire new capabilities. Something that was considered good practice six months ago — well, let’s say six weeks now — may stop making sense.

That’s why I don’t think adoption can be based mainly on traditional training. We can’t think: course → certification → now you know AI. The unit of learning has to be the work itself. Real cases. Real projects. Real experiments. And mechanisms that allow what one person learns today to spread to the rest of the team tomorrow. Knowledge governance.

How do we build judgment?

And now we come back to what I said at the beginning. If writing code is becoming the easy part and a growing share of an engineer’s value is shifting toward judgment, a pretty f...reaking hard question appears: how do you acquire judgment? Because nobody is born knowing how to look at a solution and say “this works, but it’s wrong”.

Traditionally we’ve acquired it by doing. Programming. Making mistakes. Seeing the consequences. Getting reviews. Maintaining our own decisions years later. Discovering why something that looked so elegant was actually stupid. Working alongside people who knew more than us. Putting in hours, coffees and pizzas. Debating. Doing hackathons.

And then the inevitable question about juniors appears. How do we train juniors if traditionally a junior learned by programming, making mistakes, receiving reviews and accumulating experience until becoming senior, but now an AI is going to execute a large part of that work?

I think we’re asking the wrong question. Because what turns someone into a senior isn’t having written enough lines of code. It’s having acquired judgment. A senior isn’t someone with five years of experience. It’s someone capable of avoiding a mistake before it happens and recognising a problem before it lands on top of them. Five, ten or fifteen years of just any kind of experience don’t make you senior. It’s a very particular kind of experience that hardens that layer of seniority, the kind that teaches you when a solution makes sense and when it doesn’t. What questions to ask. How to detect that something apparently correct doesn’t fit. To understand that every decision has a price, what you gain and what you give up. To understand that there are almost never silver bullets capable of killing the “werewolf”.

And so the interesting question becomes a different one: how does a junior acquire judgment if AI is executing a large part of the work? I think the answer is right in front of us and we’re not seeing it. We can’t see the forest for the trees.

The washing machine

This happened to me during these holidays with a washing machine. We were staying in an apartment and there was a fairly analogue washing machine from a brand I didn’t know, with programs numbered from 1 to 8. I needed to use it. Program 3? 5? 7? No idea. So I did what many of us would probably do today. I took a photo and sent it to ChatGPT. It recognised the washing machine and the model. It asked what I wanted to wash, I explained what clothes were in the load and it recommended a program.

If I’d been alone, I would have used that program. No further questions. Why? Because I’m the junior when it comes to laundry in our house. Generally speaking, I handle cooking and shopping. My wife handles the laundry. So I lack mileage, in other words, I don’t have judgment. I have some knowledge: I know the basics of washing programs, separating clothes, adding fabric softener and which one we prefer... But I lack judgment. Standing in front of that washing machine, I didn’t have enough experience.

Fortunately, my wife was there, and in that domain she’s the senior. And she didn’t simply accept the first answer. She said:

“But I want the clothes to come out like this. Did you tell it that?”
“How long does that program take? Wow! That seems like a lot”
“What temperature does it wash at?”
“Do you know the water here is really hard?”

She questioned the solution. Added context. Made me debate with the model. Compared its answer with what she knew from experience. From having “broken” laundry loads. And eventually, we arrived at another program that fitted what we actually wanted better. And the clothes came out perfectly!

That was the difference between junior and senior. I had an answer. She had the judgment to evaluate the answer.

Now imagine she hadn’t been there. I would have used the first program ChatGPT recommended, taken the clothes out and thought: “This hasn’t come out the way I expected”. What would I have done next? Gone back to ChatGPT. Explained what happened. Asked why. It would agree with me and apologise, obviously. We’d compare alternatives. And probably on the next wash, or twenty washes later, we would eventually have reached the same conclusion my wife arrived at by asking a few questions. With one small difference. I would have had to break a few laundry loads to learn it. And after enough loads, I would have had more judgment than before.

Well, I think that’s how we need to train juniors too. We need to let them do laundry. A junior needs to do things. They need to make decisions. They need to make mistakes. They need to see the consequences. They need to ask AI, try its answer and discover that sometimes something that sounded perfectly reasonable doesn’t produce exactly the result they expected.

We need to let them use AI from day one. Not teach them for years how to work the way we did in the pre-AI era, only to then explain how to stop working that way. That’s absurd. It makes no sense.

How many times have we seen the joke “another day without ever using the least common multiple”. And although we know that some knowledge and learning can appear useless while still helping us “furnish the mind”, we need to find the balance, carefully select what is useful and what will simply leave people feeling that they’ve learned something they’ll never use. We should be able to justify every thing we teach without AI, even when right now it looks like “wax on, wax off” (The Karate Kid, 1984) and they don’t understand why; soon enough they should be able to see that they’ve internalised useful things that help them build judgment. For example, learning how to really debug: reading a stack trace, forming a hypothesis about why something is failing and testing that hypothesis. Today you can ask an agent to do that too, but that is exactly the muscle you’ll later use to judge whether what AI did is actually right or merely looks right. It’s pure “wax on, wax off”: it seems useless until the day you look at a solution with all the tests green and know it’s wrong.

And we need to teach them how to work with AI. But that doesn’t mean leaving them alone in front of an agent. It means teaching them to ask better questions. To challenge answers. To request alternatives. To understand why one option is better than another. To spot missing information. To verify the result. To debate and learn alongside them. And above all, let them break laundry loads. In environments where breaking a laundry load is cheap. Controlled projects. Scoped tasks. Development environments. Systems where mistakes are detected early. With people around them who have more judgment and can help them understand not only that something is wrong, but why.

The governance system I talked about in the previous article also serves this purpose: allowing us to make mistakes without every mistake ending up in production. It doesn’t just protect the software. It can also become a learning environment.

They also need to understand the rules

There’s another source of learning that I think is particularly important. If we’re going to build systems where AI works under certain rules, juniors should know those rules. Not simply obey them. Understand them. Why do we do TDD? Why have we decided that a review should be performed by a model from another family? Why do we limit the size of a PR? Why was this architectural decision made this way? Why this dependency and not that one? What alternatives were there? What do we gain? What do we sacrifice? And we should debate those things with them and let them propose and experiment with their own alternatives alongside us.

Because those rules are, to a large extent, accumulated judgment. They’re decisions made after years of mistakes, experiences and lessons learned. Explaining them means transferring part of that judgment. But we also need to explain something even more important: those rules may be wrong. They’re not commandments. They need to be questioned. They are decisions made in a particular context at a particular moment. And context changes.

Maybe that’s exactly why we need juniors more than ever

There’s an interesting paradox here. We could think that if AI can do much of the work we traditionally assigned to junior profiles, we’ll need fewer juniors. I think that’s a huuuuuuge mistake. Because if we stop bringing juniors in, the obvious question is: where are the seniors going to come from in five or ten years?

But there’s another reason. The juniors we train now may have an advantage that we seniors don’t have, and I’ve already seen this with my own children, who are moving toward the industry. We accumulate judgment. But we also accumulate habits. Ways of doing things. Decisions that worked for years. And a dangerous tendency to think: “We’ve always done it this way because it works”. Seniors have a tendency to rest on their laurels. And at the speed things are moving now, you can’t even afford a quick nap. In the past, that might have been relatively cheap. Technology could change a lot, but certain paradigms could last for years. Now some things change practically month by month.

And this is really fucking hard. We’ve always said you need to stay up to date, but what’s happening now is frantic. In a way, we’ve all become “juniors” again: learning, experimenting and questioning continuously. Eternal juniors. No rest for the warrior.

The people who are starting now and those who come after them, who learn from the beginning by working with AI and who we teach to build judgment, may be precisely the ones best positioned to question our own rules:

“Why do we do this this way?”
“Does this restriction still make sense?”
“This model can now do something it couldn’t do before”
“Why are we still keeping this manual step?”

And maybe they’re right. That’s why we need to teach them our rules. But we also need to teach them to question those rules.

That’s why we need juniors. Always. And that’s why I think companies should deliberately continue bringing juniors in and training them. Spend resources on it. Take vocational training and university interns and later bring them into the company. Create internal onboarding and training programmes. Give them projects where they can work inside an AI governance environment from day one, accompanied by people with more judgment and inside systems where making mistakes is cheap. We don’t need juniors to do the boring tasks seniors don’t want to do. AI will increasingly do those better. We need them for something much more important. To build the next generation of people with judgment. Because if the work shifts upwards, we also need to teach the next generation how to work up there.

I’m genuinely worried about building an entire system where AI writes the code and eventually having nobody left capable of governing that AI and applying the necessary judgment. So let’s burn this into our brains: judgment isn’t installed. It’s built. Question by question. Decision by decision. Mistake by mistake. Laundry load by laundry load.

Not everyone will move at the same speed

Not everyone will move at the same speed, and we need to accept that there will be differences. Some people have already been working this way for months. Others are just starting. Someone will remain sceptical until they see data. Someone else will move too fast and we’ll have to hold them back. Another person will discover a way of working nobody had anticipated. We don’t need everyone to move at exactly the same pace. We need everyone moving in the same direction. Diversity with a shared goal.

And we need to turn individual learning into team learning. Because in a transition this fast, we can’t depend on three people who independently figured out how to work well with these tools. What one person learns has to spread through the rest of the team. And tomorrow we need to be willing to throw part of that learning away because the conditions have changed again.

And the challenge also changes for those of us who lead

All of this changes what those of us leading engineering teams need to do too. Buying licences isn’t enough. Saying we’re AI-first isn’t enough. Measuring how many developers use Copilot or how many tokens they spend isn’t enough.

We need to help each person understand where their value is shifting. For someone who has spent fifteen years writing code, we need to help them understand that their experience doesn’t disappear just because someone else writes the lines: we need precisely that experience to judge what the agents produce. And for someone who doesn’t yet have that experience, we need to create opportunities to build it. We need to create spaces where experimentation is cheap. Allow bad days. Share what we’ve learned. Prevent the person moving fastest from looking down on someone who’s only just getting started, and also prevent someone who refuses to move from turning their fear into a reason that paralyses other people or the company itself, and make them aware when that is happening.

We’ll also have to change what we recognise and reward. If we continue considering the best engineer to be the person who produces the most code while at the same time asking agents to produce the code, we’ve created a completely contradictory system. And please don’t measure AI adoption by who spends the most tokens. No. Maybe we need to start recognising much more the person who realised something shouldn’t be built at all. The person who prevented a bad architecture. The person who found a vulnerability. The person who got an agent to solve a difficult problem well while spending very few tokens. The person who taught five colleagues something they’d learned. The person who was able to explain why a solution that apparently worked was actually wrong. That’s engineering too. It probably always was. Writing code simply took up so much space that we couldn’t see it.

And yes: standing still isn’t an option either

This is probably the most uncomfortable conversation. Not adopting these tools doesn’t mean preserving your current position, because the rest of the world doesn’t stand still with you. The bar moves. And there is also a generation coming for whom this transition won’t even exist. A developer starting a few years from now probably won’t have to “learn how to develop with AI”: it will simply be how they learned to develop. Just as someone who started using Git never had to experience the transition from copying folders called project_final, project_final_good, project_final_now_really_final... For them, version control simply existed. Something similar will happen with agents.

I don’t think we should use that as a threat. But we shouldn’t hide it just to avoid an uncomfortable conversation either. Leadership also means explaining that the world is changing before the change runs you over.

Summary and conclusions

Over the last few years, we’ve talked endlessly about AI as a productivity tool. How to write code faster. How to build more features. How to produce more with less. That’s already becoming too narrow. The real opportunity is much bigger: it’s about changing which part of the process machines do and which part we do.

And if that happens, writing code will increasingly become less of what defines a software engineer, because writing code is starting to become “the easy part”. The hard part will be knowing which code deserves to exist. Understanding the problem. Designing the system. Knowing the domain. Choosing between alternatives. Measuring. Verifying. Understanding the consequences. Keeping it alive. And being able to look at something generated by AI, see that it compiles, that the tests are green, that it apparently does exactly what you asked it to do and say: “No. This works, but it’s wrong”. That’s judgment.

And I think one of our biggest challenges over the next few years won’t be getting our teams to learn how to use AI. It will be helping those who already have that judgment move it to this new level, while making sure those who don’t have it yet can build it in a world where they will probably write less and less code themselves.

AI can write the code. We need to develop the people capable of knowing what is worth building and when what has been built is wrong. And that has to be led, always with affection.

Top comments (0)