We have spent decades making software development more abstract. AI is simply taking that abstraction further. The question is not whether we should use it, but what expertise remains essential when implementation becomes cheap.
At 11:47 p.m., the application was finally working.
The login page looked good. The dashboard loaded. The database was connected. Users could create accounts, upload files, search through them, and receive AI-generated answers.
There was even a dark mode.
A few years ago, building all of this might have taken days or weeks.
Now, much of it had been built by describing what was needed to an AI coding assistant.
The developer hadn’t written every function.
He hadn’t memorized the syntax of every library.
He hadn’t spent an afternoon searching Stack Overflow for the exact error message.
He had prompted, reviewed, corrected, tested, and prompted again.
And it worked.
That last part matters.
It worked.
So why are some developers uncomfortable with this?
Why does AI-assisted programming sometimes feel like it is somehow less legitimate than writing the code ourselves?
Should we frown on AI use in software development?
I think that is the wrong question.
The more interesting question is:
As software development becomes increasingly abstracted, what knowledge must a programmer still possess?
To answer that, we need to look at something software engineers have been doing for decades.
We have been hiding complexity.
We have been abstracting software for decades
Imagine asking a mathematician to perform a complicated calculation.
Now imagine telling them:
“You didn’t really calculate it. You just pressed buttons on a calculator.”
The objection would be strange.
The calculator did not make mathematics meaningless.
It abstracted arithmetic.
It removed some of the mechanical work while leaving the intellectual work intact.
The mathematician still had to know what calculation was necessary, which numbers belonged in it, whether the result made sense, and what to do with the answer.
The calculator simply changed how much manual computation was necessary.
Software development has followed a similar trajectory.
The earliest programmers worked extremely close to the machine.
Then came assembly language.
Then higher-level languages.
Then languages such as C and C++.
Then increasingly expressive languages such as Python, Java, JavaScript, Go and Rust.
Then libraries.
Frameworks.
Package managers.
Cloud platforms.
Managed databases.
Containers.
Infrastructure-as-code.
Serverless platforms.
Each layer moved developers further away from the machinery underneath.
A programmer working in Python does not manually translate every instruction into machine code.
A web developer does not implement TCP/IP before sending an HTTP request.
A developer using a managed database does not need to implement a storage engine before creating a table.
And a developer using a framework does not need to rebuild common infrastructure from scratch.
That isn’t a failure of programming.
It is one of the reasons programming became practical at scale.
High-level languages were explicitly designed to abstract away hardware-level details and let programmers express computation in terms closer to the problems they were trying to solve.
The history of software is, in large part, a history of moving the boundary of abstraction upward.
Abstraction doesn’t eliminate knowledge. It changes where knowledge matters.
This is the part we sometimes miss.
When we move up an abstraction layer, we don’t necessarily become less knowledgeable.
We become responsible for different knowledge.
An assembly programmer needs to understand things that a Python developer can safely ignore.
But the Python developer needs to understand things that matter at their own level.
The abstraction hides complexity.
It does not abolish complexity.
It moves the boundary.
That distinction is important because it changes how we should think about AI.
The argument cannot simply be:
“AI writes the code, therefore programmers will stop understanding software.”
We have been delegating implementation details to abstractions for decades.
The better question is:
How far can we move the boundary before we lose the ability to reason about what is underneath it?
And this is where AI becomes particularly interesting.
AI doesn’t only abstract implementation
Previous generations of software tools primarily helped us abstract how things were implemented.
AI can also abstract part of how we acquire knowledge.
Think about how a developer might have solved an unfamiliar problem over the years.
First, perhaps a textbook.
Then documentation became easier to access through the web.
Then blogs.
Then Stack Overflow.
Then Google became an almost universal starting point.
Then GitHub repositories became a way to discover how libraries were actually being used.
The workflow might look like this:
Problem → search → documentation → example → experimentation → solution
Now it can look like:
Problem → AI → explanation → example → implementation → debugging
A developer can ask:
“I’m using this authentication library. I need passwordless authentication with email magic links. Explain the flow and show me how to implement it.”
The AI can explain the concept.
Generate an example.
Modify the implementation.
Explain an error.
Write tests.
Suggest alternatives.
This is more than code generation.
It is knowledge retrieval, interpretation, synthesis and implementation assistance wrapped into one interface.
Research into how developers use AI coding assistants already shows these tools being used across activities such as implementing features, writing tests, bug triage, refactoring and producing natural-language artifacts.
That is a much bigger abstraction than simply replacing a few lines of code.
So why do we still need programmers?
Because knowing how to get an answer is not the same as knowing whether the answer is good.
Suppose you ask an AI:
“Build me a login system.”
It can probably build one.
You may get an email-and-password form.
A database table.
Password hashing.
Sessions.
Validation.
Tests.
The application works.
But should it use passwords?
That is a different question.
Perhaps the product would be better with magic links.
Perhaps it is a business application where Microsoft or Google single sign-on makes more sense.
Perhaps the application handles sensitive information and requires stronger authentication.
Perhaps the onboarding experience should begin with an invitation rather than account creation.
Perhaps the application needs multifactor authentication.
Perhaps authentication should be delegated to an identity provider instead of implemented inside the application.
AI can help implement any of these.
But someone still has to decide which problem is actually being solved.
That is judgment.
A functional application can still be a bad product
This is where “vibe coding” becomes interesting.
One of the things AI-assisted development makes remarkably easy is producing something that works.
But software quality has never been synonymous with functionality.
Imagine asking an AI to build a food-delivery application.
It produces:
restaurant listings,
user registration,
shopping carts,
payments,
order tracking,
notifications.
Everything works.
But perhaps the onboarding is confusing.
Perhaps restaurant discovery is poor.
Perhaps the application asks for too much information too early.
Perhaps checkout contains unnecessary friction.
Perhaps users struggle to recover abandoned orders.
Perhaps the interface looks like a hundred other applications.
Nothing is technically broken.
And yet the product isn’t particularly good.
This is where product judgment and creativity matter.
A professional isn’t simply someone who knows how to implement features.
A professional understands why those features should exist, how they should interact, and what experience they create for the person using them.
AI can generate possibilities.
It does not remove the need to choose among them.
Working is not the same as scaling
There is another trap.
An AI-generated application can work perfectly for a small number of users and still be poorly designed for scale.
Imagine an application that queries a database every time a page loads.
With ten users, nobody notices.
With ten thousand users, everything changes.
Perhaps the queries need indexes.
Perhaps the data model needs restructuring.
Perhaps caching is necessary.
Perhaps expensive work needs to become asynchronous.
Perhaps a queue should separate background processing from the request-response cycle.
Perhaps an algorithm that was acceptable for 1,000 records becomes painfully slow at 100 million.
Perhaps the architecture itself needs to change.
This is where knowledge of algorithms, databases, distributed systems, networking and system design becomes valuable.
AI can help implement an architecture.
But understanding architecture helps you recognize when the proposed architecture is inappropriate.
A solution can be correct for today’s workload and disastrous for tomorrow’s.
AI can help optimize an implementation. Expertise helps determine whether the implementation is the right solution to begin with.
And then there is security
Security may be the clearest example of why abstraction requires expertise.
An inexperienced developer might ask:
“Does the application work?”
A security-conscious engineer asks:
“How can this application fail?”
Those are completely different questions.
Who can access this endpoint?
What happens if a user changes an ID in the URL?
Where are secrets stored?
Can one customer retrieve another customer’s data?
What happens when a session expires?
Can an attacker abuse the password-reset flow?
Are uploaded files validated?
Are API endpoints rate-limited?
What information appears in logs?
Are sensitive values being sent to third-party services?
What permissions does this service actually need?
What happens if one of the dependencies is compromised?
Does the system satisfy the security, privacy and regulatory requirements of the organization using it?
AI can help answer these questions.
It can even help identify vulnerabilities.
But that requires someone to know that these are questions worth asking in the first place.
That may be one of the most important limitations of blindly relying on AI:
You cannot reliably evaluate risks that you don’t know exist.
This is not merely theoretical. NIST’s secure-development guidance now explicitly addresses generative AI and emphasizes monitoring, validation and human oversight of AI-generated software. Its broader DevSecOps guidance also treats security as a lifecycle concern rather than something to bolt on after development.
The danger isn’t simply that AI might produce insecure code.
The deeper danger is that someone without sufficient engineering knowledge might not recognize insecure code when they see it.
Requirements are another form of expertise
There is an even earlier problem.
Before asking:
“How should we build this?”
someone needs to ask:
“What exactly should we build?”
This sounds obvious.
It isn’t.
A surprising amount of software failure begins before the first line of code is written.
A client might say:
“We need an AI chatbot.”
But what does that actually mean?
A customer-support assistant?
An internal knowledge assistant?
A sales qualification agent?
A workflow automation tool?
A search interface?
A document-analysis system?
A conversational interface over a database?
These may all be described as “AI chatbots.”
Underneath, they can require completely different architectures.
The better AI becomes at implementation, the cheaper it becomes to build the wrong thing.
That is an uncomfortable consequence of powerful abstraction.
If implementation becomes almost frictionless, bad decisions become cheaper to execute.
Verification may become more important than generation
This may be the biggest shift AI brings to software development.
When generating code was expensive, programmers spent a large portion of their time producing code.
When generating code becomes cheap, production becomes less scarce.
Verification becomes more valuable.
Someone has to ask:
Is this correct?
Is it secure?
Is it maintainable?
Is it performant?
Does it satisfy the requirement?
What happens under unusual conditions?
Does it introduce regressions?
Is this architecture appropriate?
Can another engineer understand it?
Can we operate it in production?
This is why testing, evaluation, observability and code review don’t become irrelevant when AI writes more code.
They become more important.
The ability to produce ten thousand lines of code is not particularly impressive if nobody knows whether those ten thousand lines should exist.
But what if AI gets much better?
Here is where the argument gets uncomfortable.
What if AI eventually becomes capable of designing the architecture too?
What if it can identify scaling problems?
What if it can perform security reviews?
What if it can generate tests and evaluate its own code?
What if it understands the business requirements?
What if it can monitor production and fix failures automatically?
Then what?
This is where I think the argument for human expertise needs to be more careful.
We should not build our philosophy around the assumption that AI will forever be incapable of doing things that experienced engineers can do today.
It may become extremely capable.
The more interesting question is what happens when it does.
Perhaps the human role moves yet another level upward.
From writing functions to designing systems.
From designing systems to defining goals.
From defining goals to deciding trade-offs.
From making decisions to determining which decisions can safely be delegated.
The abstraction ladder doesn’t necessarily stop.
It keeps moving.
And that may be the most important lesson from the history of software.
The problem isn’t abstraction
It is tempting to think the solution is to tell people:
“Don’t use AI. Learn to code properly.”
But what does “properly” mean?
Should a professional Python developer abandon Python and learn assembly?
Should a web developer build their own HTTP server?
Should every engineer implement their own database?
Should we stop using frameworks because they hide complexity?
Of course not.
The goal of engineering has never been to maximize manual work.
The goal is to solve problems effectively, reliably and responsibly.
AI is another abstraction layer.
A powerful one.
The question isn’t whether we should use it.
The question is:
What are we delegating, and do we still understand enough to be responsible for the result?
The professional developer may be changing
The programmer of the future may spend less time translating ideas into syntax.
That doesn’t necessarily make the programmer less valuable.
It may make other skills more valuable.
Understanding systems.
Defining requirements.
Designing architectures.
Evaluating trade-offs.
Thinking about users.
Understanding security.
Testing assumptions.
Evaluating AI outputs.
Understanding failure modes.
Managing complexity.
Knowing when an abstraction is appropriate–and when it isn’t.
The professional developer may become less of a code producer and more of a system designer, evaluator and decision-maker.
And perhaps that is what abstraction has always done.
When calculators arrived, mathematicians didn’t disappear.
When high-level languages arrived, programmers didn’t disappear.
When frameworks arrived, software engineers didn’t disappear.
The work moved.
The abstraction ladder keeps moving
Perhaps one day we will look back at today’s AI-assisted development the way we now look at writing assembly.
Something we once considered normal may seem unnecessarily manual.
The tools will become better.
The abstractions will become higher.
The amount of code humans write directly may continue to fall.
That is not necessarily the problem.
The real question is whether our understanding rises with the abstraction.
Because abstraction gives us leverage.
But leverage without understanding can be dangerous.
A calculator gives us leverage over arithmetic.
A programming language gives us leverage over machine instructions.
A framework gives us leverage over common software patterns.
Cloud platforms give us leverage over infrastructure.
AI gives us leverage over implementation and, increasingly, over knowledge itself.
And with every increase in leverage, the responsibility to understand when, why and where to apply it becomes more important.
So perhaps the future isn’t one where programmers stop coding.
And perhaps it isn’t one where programmers reject AI to preserve some romantic idea of “real” software development.
Perhaps it is simply one where programmers move higher up the stack.
They write less.
They decide more.
They verify more.
They design more.
They understand systems more deeply.
And they become responsible for increasingly large pieces of software that they did not personally write.
The code may no longer be the scarce resource.
Judgment might be.
The question isn’t whether AI can code.
It already can.
The question is what we choose to understand when we no longer have to write every line ourselves.
And perhaps that is the real promise—and the real responsibility—of abstraction.
It frees us from the work underneath so that we can think about the work above.
But we have to make sure we are still capable of thinking.
CV Booster is an AI-powered career platform that helps you move from where you are to where you want to be.
It analyzes and improves your CV, tailors applications to specific jobs, generates matching cover letters, finds relevant opportunities through Opportunity Radar, and builds personalized career roadmaps that show you the skills, projects, and certifications you need for your target role.







