DEV Community

Cover image for AI Can Write the Code. I Still Need to Understand the System.
Okello Odhiambo
Okello Odhiambo

Posted on

AI Can Write the Code. I Still Need to Understand the System.

This is the final part of a three-part reflection on what I am learning about software engineering at Zone01 Kisumu.

The first part was about moving beyond "the code works."

The second was about architecture and understanding what our technical decisions become as systems grow.

This final part is about the thing sitting beside almost every developer conversation today:

AI.

I use AI.

I find it useful.

And precisely because it is useful, I think developers need to become much clearer about what our actual job is.

There is little value in pretending AI cannot code

It can.

Sometimes very well.

Ask for a function that sorts a collection.

Done.

Ask for an API endpoint.

Done.

Ask for a React component.

Done.

Ask for SQL migrations, tests, Docker files, validation logic or a Python script.

Often, done.

It can also explain unfamiliar code, find mistakes, propose refactors and help investigate errors.

Pretending otherwise doesn't prepare me for the industry I am entering.

But neither does handing every problem to AI and assuming that receiving code means the problem has been solved.

Those are two extremes.

My experience at Zone01 Kisumu is pushing me towards something between them:

Use the tools. Understand the work.

A generated solution still creates responsibility

Imagine I am building an application that collects personal information.

Users upload profile pictures and identification documents.

The application also accepts payments.

I ask AI to implement file uploads.

It does.

I ask it to integrate payments.

It does.

I ask for authentication.

It does.

Now I have several thousand lines of code and a functioning application.

But I still need answers.

Where are the ID documents stored?

Are they publicly accessible?

Can User A request User B's document?

Are uploaded files validated on the server?

Where are payment credentials stored?

Does the application trust payment status coming from the browser?

How are payment callbacks verified?

Are passwords hashed correctly?

Can a user change their role by modifying an API request?

What information is written into logs?

What happens when the payment provider is unavailable?

What happens when the same webhook arrives twice?

AI's ability to generate the implementation doesn't transfer responsibility for those answers.

The system is still ours.

This is changing how I define a good developer

If you asked me earlier in my learning journey what makes someone a strong developer, I probably would have talked mainly about programming ability.

How quickly can they solve a problem?

How many languages do they know?

Can they build the feature?

Those things still matter.

But my list is getting longer.

Can they understand a problem before implementing it?

Can they read unfamiliar code?

Can they explain why something was designed a particular way?

Can they recognize when an abstraction is unnecessary?

Can they identify security assumptions?

Can they debug a system rather than just a function?

Can they communicate trade-offs?

Can they review someone else's solution fairly?

Can they change their mind when another approach is better?

Can they determine when AI-generated code is wrong even when it looks convincing?

Those skills are harder to demonstrate with a single code snippet.

They are also becoming difficult for me to ignore.

Peer-to-peer learning feels strangely appropriate for the AI era

There is something interesting about learning software engineering through a peer-to-peer model at this particular moment.

When knowledge is immediately available through search engines, documentation and AI, the challenge isn't always obtaining an answer.

The challenge is understanding it.

When a peer reviews my project, saying:

"AI gave me this code."

doesn't answer:

"Why does this work?"

And it certainly doesn't answer:

"Why did you choose this approach?"

That pressure to explain is valuable.

Teaching another person exposes gaps in my own understanding.

Reviewing another person's implementation exposes me to decisions I wouldn't have made.

Defending my own decisions forces me to separate preference from reasoning.

Sometimes a peer's five-minute question teaches me more than another hour of adding code.

Learning multiple languages has reinforced this

At Zone01 Kisumu, working across Go, Python and JavaScript has also helped separate programming from software engineering in my mind.

The languages approach problems differently.

Go can make me think carefully about explicit error handling and package boundaries.

Python can let me explore an idea with remarkably little ceremony.

JavaScript puts me close to asynchronous behaviour, browser interactions and the realities of client-server applications.

But after spending enough time with them, something becomes obvious.

The languages change.

The important questions survive.

How should this data be represented?

Who owns this state?

Where should this responsibility live?

What happens when this operation fails?

How do I test this?

What does this component need to know?

How does this system communicate with another system?

What should I trust?

What should I never trust?

Those aren't Go questions.

They aren't Python questions.

They aren't JavaScript questions.

They are engineering questions.

AI has made syntax cheaper

I think this is one of the biggest changes we are experiencing.

Syntax used to represent a significant portion of the friction between an idea and working software.

AI is reducing that friction.

That is good.

But when one resource becomes cheaper, other resources become more important.

Judgment becomes more important.

Context becomes more important.

Problem definition becomes more important.

Architecture becomes more important.

Verification becomes more important.

Security becomes more important.

Communication becomes more important.

Understanding becomes more important.

If AI gives me 500 lines of code in thirty seconds, I haven't necessarily saved time if I spend the next two days discovering that the underlying design was wrong.

Generating code quickly and building the right system are different optimizations.

Prompting isn't a replacement for understanding

There is a tendency to frame prompting itself as the new programming.

I think that misses something.

A precise prompt can absolutely improve the output.

But where does the precision come from?

Suppose I tell an AI:

Build a secure REST API.

Compare that with:

The endpoint requires authentication. A user can access only resources they own. Validate the request server-side, reject unknown fields, enforce a 5 MB upload limit, allow only specific MIME types, avoid exposing storage paths, rate-limit requests and return consistent errors without leaking internal details.

The second prompt is better.

But the improvement didn't come from learning magical words for talking to AI.

It came from understanding the engineering problem.

The quality of what I ask AI to build is constrained by what I know to ask about.

And the quality of what I accept is constrained by what I know how to verify.

That makes fundamentals more useful to me, not less.

Sometimes the best use of AI is disagreement

One habit I am trying to develop is not treating AI as the final authority.

Instead of only asking:

"Build this."

I can ask:

"What can fail in this design?"

"Give me three alternatives."

"What assumptions am I making?"

"Attack this architecture."

"What security issues should I test?"

"Explain why this abstraction is necessary."

"What would you remove?"

Then I still have to evaluate the answers.

That feels much closer to engineering than simply accepting generated code.

AI becomes a collaborator in the thinking process rather than a machine that finishes the thinking for me.

The debugger still needs a human question

Something I keep encountering while learning is that debugging rarely begins with knowing the answer.

It begins with forming the right question.

Is the frontend sending the wrong data?

Is the API rejecting it?

Did authentication fail?

Did the database operation execute?

Is the state stale?

Is this a race condition?

Is my assumption about the input wrong?

AI can help investigate each possibility.

But someone needs a mental model of the system strong enough to know where to look.

Without that model, debugging becomes repeatedly pasting errors into a chat window and hoping the next suggestion works.

Sometimes it does.

Sometimes it creates the next error.

Understanding lets me tell the difference.

Software engineering is also communication

This may be the least glamorous part.

Software is built by people.

Requirements come from people.

Users are people.

Designers, engineers, testers, managers and clients all see different parts of the problem.

Being able to explain:

Here's the problem.

Here are our constraints.

Here are the options.

Here's what this option gives us.

Here's what it costs us.

Here's what could go wrong.
Enter fullscreen mode Exit fullscreen mode

is an engineering skill.

Our peer-to-peer environment keeps reinforcing this because learning doesn't happen entirely in isolation.

Sometimes I am receiving help.

Sometimes I am providing it.

Sometimes we are both staring at the same bug wondering what we've missed.

That process develops something a code generator cannot simply hand me: experience.

I don't know exactly what software engineering will look like in five years

I don't think anybody does.

AI capability will continue changing.

The tools we use today will change.

Some tasks that currently take hours will probably become nearly instantaneous.

Some roles will change with them.

So I don't want to build my identity around being the person who can type code faster than a machine.

That competition doesn't interest me.

I want to become the engineer who understands what needs to be built.

Who can inspect what was generated.

Who can recognize when something that works shouldn't be deployed.

Who understands the data moving through the system.

Who can reason about failure.

Who can collaborate with other engineers.

Who can explain technical decisions.

Who can learn an unfamiliar technology when the problem requires it.

And, importantly, who knows when they don't understand something yet.

My biggest lesson so far

My journey at Zone01 Kisumu is still ongoing.

I am still learning Go.

Still working through Python.

Still improving my JavaScript.

Still debugging things that seemed obvious five minutes earlier.

Still making decisions I later realize could have been better.

But perhaps that is exactly the point.

I came into this journey wanting to become better at writing code.

I still do.

What has changed is my understanding of what sits around the code.

Architecture.

Data.

Security.

Testing.

Trade-offs.

Communication.

Failure.

Users.

Other developers.

And now AI.

The code matters.

But the decisions behind it matter longer.

AI can help me write the function.

My responsibility is understanding what happens when that function becomes part of a real system used by real people.

That is the kind of software engineer I am learning to become.

Part 3 of 3 — Learning Software Engineering in the Age of AI

Top comments (0)