跪拜 Guibai
← Back to the summary

Vibe Coding Didn't Kill the Programmer — It Just Changed the Job Description

Since the release of ChatGPT 3.5, I have been using large models to write code. At that time, ChatGPT 3.5's programming ability was not very strong; as soon as the requirements became slightly complex, the generated code was not very reliable. Therefore, I still mainly wrote code by hand, using AI primarily for looking up information and handling simple problems.

Later, I used GPT-4 and Claude successively, and since then I have been continuously trying new models released by OpenAI and Anthropic. As model capabilities have steadily improved, the scenarios where I need to hand-write code at work have become fewer and fewer. In the past year, I have basically not written any code by hand, only occasionally doing so when practicing on LeetCode.

This change has gradually influenced my development approach. Now, when developing a new feature, I usually first clarify the requirements and list the relevant key points, then send the requirements to the AI, asking it to check if my understanding is correct and what areas need supplementation. Generally, after a few rounds of discussion, the implementation plan can be finalized.

Once the plan is set, I let the AI start generating code. After the code is complete, I am responsible for checking and testing it. If problems are found, I send the error messages and my feedback back to the AI for it to make corrections.

I now basically follow this process for developing requirements. However, I do not simply hand the requirements to the AI and use the code directly after it is generated. I still review what it specifically changed, whether it meets the requirements, whether it affects the original functionality, and whether there are any security or performance issues.

AI sometimes modifies many files at once. If I had to review every line from start to finish each time, the review would take a huge amount of time. So, I usually first understand which business processes and modules this modification involves, and then check by combining the code changes, automated tests, and actual running results.

Over the past one or two years, many programmers' working methods have undergone similar changes. As the quality of code generation continues to improve, I have also started thinking: if most of the code can be handed over to AI, what will programmers do in the future?

This article will sort out this question based on my own work experience. Because much of the content comes from personal practice, it is inevitably biased, and I welcome everyone to discuss it together.

What Vibe Coding Has Changed

I think the biggest change brought by Vibe Coding is that it has greatly shortened the time required from requirement analysis to feature implementation.

In the past, if you wanted to develop a feature you were unfamiliar with, you usually needed to first look up information, read documentation, find examples, and then write the code bit by bit. If you encountered problems along the way, you had to continue searching for information and debug repeatedly. Throughout the whole process, looking up information and debugging took the most time; the time actually spent writing code was relatively small.

Now, a large part of this work can be handed over to AI first. Whether it's implementing new features, analyzing bugs, or understanding existing projects, as long as you describe the problem and relevant background clearly, AI can usually quickly provide ideas and code. For development tasks with relatively clear requirements, using AI can significantly shorten the time spent looking up information, writing code, and troubleshooting problems.

After development costs are reduced, teams can complete more features in the same amount of time, and code changes will become more frequent. But an increase in development speed does not necessarily mean an improvement in product delivery quality. If the requirement analysis, code review, testing, and release processes do not keep up, some changes that have not been fully tested may enter the production environment, leading to frequent product issues.

Moreover, the easier it is to implement features, the more likely teams are to skip requirement reviews and start development directly. In the past, when a requirement required an investment of several days or even weeks, everyone would usually seriously consider whether it was worth doing. Now that development costs are lower, it is even more necessary to judge before starting whether this requirement can solve a real problem, to avoid ending up building a feature with no value.

In the past, programmers spent a lot of time writing code. As more and more code can be generated by AI, programmers need to spend more energy on analyzing requirements, designing solutions, and verifying results.

Can People Who Don't Know Development Build Products?

A person who knows nothing about software development can also build websites, apps, or mini-programs through Vibe Coding.

Titles like "Can't write code, built a product in a few hours" are often seen online. Based on current AI capabilities, it is indeed possible to create several pages, connect to a database, implement login and basic CRUD operations, and deploy it to a cloud platform in a few hours.

However, what you get at this stage is usually just a demo for demonstration purposes.

Once real users start using it, the difference between a demo and a product becomes apparent. For example, a user clicking repeatedly generates two records, the page and backend states become inconsistent after a network interruption, or old data cannot be read correctly after a feature update. At this point, the person building the product has to check logs, verify data, and figure out at which step the problem occurred.

Small projects don't necessarily need a complete monitoring and alerting system from the start. You can first keep necessary logs, back up data regularly, and ensure there is a way to recover if a deployment goes wrong. As the number of users increases, or a certain type of failure starts occurring frequently, you can then supplement corresponding tools and processes based on the actual situation.

A person who originally didn't understand development, if they can discover and solve these problems in real usage, will gradually come into contact with testing, deployment, troubleshooting, and data maintenance, not just letting AI generate the features.

Software Engineering Is Even More Necessary in the AI Era

The context size of large models is limited. It's difficult to put project code, business documents, and design plans all into the context at once. So when this information is incomplete, AI might re-implement functionality that already exists in the project, or modify common logic without synchronously handling other affected modules.

AI can participate in requirement analysis, code generation, testing, and review, but it does not understand the full background of the project. Therefore, what solution to adopt and whether code can go live must still be decided by the team.

Confirming Requirements with Interactive Demos

Vibe Coding is not only changing how programmers write code; it is also changing the collaboration methods between product, design, development, and testing.

In the past, product managers wrote requirement documents, designers created prototypes and visual drafts, and developers implemented features based on these materials. Requirement documents and design drafts can describe page structures and main flows, but it's hard to fully demonstrate state changes during operation. For example, whether input content is retained after a form submission fails, whether repeated clicks generate multiple requests, and how loading and empty data states switch, usually can only be confirmed after the page is actually operable.

Now, product managers can use AI to quickly create interactive demos, bringing the flows in the requirement documents to life in advance. The team can directly experience page navigation, form operations, and various states, then modify requirements based on the actual effects. Compared to just looking at documents and design drafts, this approach makes it easier to discover whether the flow is smooth, whether the information is complete, and what scenarios were not considered.

Designers can also use AI to quickly generate different page schemes, then continue adjusting based on product positioning and usage scenarios. After the main flow and requirement boundaries are confirmed, programmers then proceed with formal development based on the demo and related documents, and testers can prepare test scenarios based on the acceptance criteria.

Demos are mainly used to confirm requirements and interactions; they cannot directly replace formal development. Programmers still need to complete the code implementation in conjunction with the existing project, handling issues like permissions, data validation, exception flows, and compatibility.

Writing Project Rules into Documentation

The same feature might be written completely differently in different projects.

Some projects require all interfaces to return a unified data format, such as { code, message, data }; other projects directly return business data, and use a different error response format when an error occurs. Some projects allow querying the database in the Controller, while others stipulate that all database operations must be placed in the Service or Repository.

After participating in a project for a long time, developers usually know which set of rules the current project should follow. But AI may not understand this background. Without relevant context, it might generate code based on its own understanding, resulting in functionality that works but has a code style inconsistent with the project's original writing style.

To reduce this situation, teams should ideally write down these rules, including how directories are divided, how files and variables are named, how interfaces return errors, what information logs need to record, and what tests need to be added for new features. General rules can be placed in AGENTS.md or project documentation, allowing AI to read these contents before modifying code.

In addition to general specifications, the business background within the project also needs to be appropriately documented.

Project code is iterated over a long period. Some logic that seems unreasonable might have specific business reasons behind it, or it might be there to handle problems that occurred previously. If this information is not recorded, it's hard for later maintainers to know why it was written that way originally, and AI can easily mistakenly delete logic that is still useful.

You can place a README.md in the module directory, briefly explaining the purpose of the current directory, which modules it contains, and how the modules divide the work. For example, a common web project splits receiving requests, processing business rules, and reading/writing databases into different modules. The README can explain which step the current directory is responsible for, which modules it calls, and which logic should not be placed there.

After each PR is merged, you can let AI update the corresponding directory's README.md based on the code changes, and then have the committer check if the content is accurate. This can reduce the cost of documentation maintenance and make it easier for documentation to keep up with code changes.

Organizing UI Specifications Clearly

When multiple people use AI to develop frontend pages simultaneously, the problem of inconsistent UI styles easily arises. If there are no clear design specifications in the project, the model can only choose layouts and styles based on the current requirement. Pages generated by different people separately are very likely to have different button sizes, table spacing, and even inconsistent layouts for modals, forms, and operation areas.

Teams can write down rules for common components and pages, including font sizes, colors, spacing, border radius, button types, form layouts, table styles, modal widths, and how loading, empty data, and error states should be displayed.

For example, whether to use a drawer or a modal for add/edit pages, what color to use for dangerous operations, whether a secondary confirmation is needed before deletion, and where to place table operation buttons—these can all be determined in advance.

If the project already has a component library, you can have AI first search the repository for existing components and similar pages before developing a page, reusing them whenever possible instead of re-implementing; also, refer to the layout and style of existing pages to keep the new page consistent with the original UI style.

PRs Should Be Easy to Review

A PR (code merge request) should ideally only accomplish one thing. Don't mix business features, code refactoring, and performance optimization together.

For example, if the requirement is just to add a "Refund Status" filter to the order list, normally you only need to modify the query parameters, backend interface, and page filter options.

But when AI generates code, it might incidentally refactor the query method, modify the filter components of other pages, or reformat a batch of files. In the end, a very small requirement turns into a large-scale change across many files.

The reviewer has to both confirm whether the refund filter is correct and check whether those extra modifications will affect the original functionality. In such cases, it's best to delete changes unrelated to the current requirement, and put genuinely needed refactoring into a separate PR.

The clearer the scope of a PR, the easier it is for the reviewer to understand the purpose of this modification and to discover truly important issues.

Large-scale refactoring should also not be done all at once. It can be broken down into several PRs that can be understood, verified, and rolled back independently. This way, if a problem occurs in one step, you don't need to revert all the changes.

Now, I usually let AI check the requirements and code diff before manual review, to see if there are any unrelated changes, missed exception scenarios, or places that might affect other modules. The results from AI are only used as a first round of screening; developers still need to review again in conjunction with the business and existing code.

Tests Should Not Be Written Solely Based on Implementation

After letting AI write the business code, having it generate tests based on that code is a very common practice. But if AI only sees the implementation code, the tests it writes often just verify the current behavior of that code.

For example, after an order refund, it should enter the refunded status, but the code mistakenly updates the status to completed. If you let AI supplement tests directly based on this implementation, it will likely also assert that the result is completed. The test passes, but the business logic is wrong.

Therefore, before generating tests, you must also tell AI the requirements and acceptance criteria. Under what circumstances can an order be refunded, how to handle orders that have already been shipped—these rules should all be provided to AI together before letting it generate tests.

In addition to normal flows, you also need to supplement exception scenarios based on the feature. For example, a user might click the submit button multiple times in a row, or a third-party interface might time out. Tests need to determine which scenarios to cover based on the actual business, not just looking at what the existing code has written.

Ordinary business logic needs unit tests. Core processes and key long-term stable rules within them also need to be covered by end-to-end (E2E) tests. Run them before each deployment to the testing or production environment to confirm that the main flow can still be completed from start to finish. This also adds an extra check before release.

High-Risk Code Needs Key Review

Different code errors cause different levels of impact, so the same standard cannot be applied during review.

Modifying button colors or page spacing only requires confirming that the page displays correctly. For changes with a smaller impact scope, like adding query conditions or adjusting form fields, the main check is whether they meet the requirements and whether they affect the original functionality.

Payments, permissions, amount calculations, database migrations, and production environment configurations require more careful inspection. When reviewing this type of code, you need to confirm how the data will change, whether it can be recovered if execution fails, whether repeated execution will cause problems, and which existing functionalities this modification will affect.

Payment is one such high-risk feature.

The payment process usually involves multiple steps like callback handling, order status updates, and shipment. Payment platforms sometimes send the same callback repeatedly, so callback handling needs to ensure idempotency to avoid the same order being recorded or shipped multiple times.

If the order status and shipment record need to be updated together, you also need to consider how to handle it if one of the steps fails. After a successful payment, notifications or reward distributions might be triggered subsequently. If a certain step fails, you need to determine whether to re-execute the entire process or only retry the failed part.

When a refund occurs later, it also needs to be processed in conjunction with the original payment record, order status, and shipment result. Whether the goods have been shipped and whether the reward has been distributed will both affect the refund process. The related logic is usually scattered across multiple modules, and during development, the entire process and state changes need to be sorted out together.

To ensure the reliability of the payment process, development needs to handle idempotency, transactions, retries, and compensation, and verify the results under different states through testing. After the feature goes live, logs and monitoring are needed to confirm whether callbacks, status updates, and subsequent tasks are executing normally.

Teams can list high-risk modules in advance and clearly designate the corresponding reviewers. Whether the code is handwritten or AI-generated, someone must ultimately approve the merge and be responsible for the results after going live.

What Abilities Should Programmers Improve in the Future

Understanding Business and Product

In the past software development process, the most common division of labor was product managers writing requirements, designers creating visuals, and programmers responsible for implementation. Under this collaboration model, programmers focused more on how to implement, just needing to complete the corresponding features according to the requirements.

Now, AI can already complete feature implementation based on clear requirements. The ability to simply convert requirements into code is no longer as scarce as before. Programmers need to participate more in requirement analysis, understand the purpose behind features, and judge whether the current solution can truly solve the problem.

For example, when a product manager proposes adding a check-in feature, you can first ask what the purpose of the check-in is. Is it to hope users open the app every day, or to hope users who have left come back? Different goals will lead to different subsequent solutions.

If the input to AI is only "develop a check-in feature," the model will directly generate a check-in page, check-in interface, and reward logic. As for why users are inactive, whether check-in can improve activity, and whether there is a simpler way, the team still needs to analyze these themselves.

Whether check-in can improve activity is hard to determine just through discussion. You can first look at existing data, find some users to understand why they no longer use the product, or first make a small-scale version and observe the actual effect before deciding whether to continue investing.

After clarifying the goal, you also need to continue confirming the feature boundaries. Taking the check-in feature as an example, which users can check in, whether make-up check-ins are supported, and how to handle reward distribution failures all need to be determined before development. If the requirement document does not cover these points, they still need to be confirmed one by one during development.

If this information is not clearly written, AI will supplement it based on its own understanding. Sometimes its understanding meets the project requirements, but other times it may deviate from the actual needs.

Judging Solutions and Controlling Risks

After using AI to generate code, programmers still need to judge whether the solution it provides is suitable for the current project.

For example, after a user submits a form, a notification needs to be sent. AI might suggest integrating a message queue, putting notification sending and failure retries into asynchronous tasks. This approach is suitable for scenarios with high request volumes where the main process cannot be blocked. But if the current request volume is very low, and retrying directly after a send failure meets the requirement, introducing a message queue actually increases deployment and maintenance work.

After a project develops to a certain scale, a message queue might indeed be necessary. But whether it is needed at the current stage depends on the request volume, the impact of failure, and whether the team has the ability to maintain this system.

After the solution is determined, you also need to continue checking what risks it brings. For example, what dependencies are added, whether it can be recovered if the modification fails, and how to observe the operation status after going live. Thinking through these questions in advance will make subsequent development and maintenance much easier.

Improving Aesthetic Judgment

AI-generated UI easily suffers from the problem of uniformity, such as repeatedly using gradient colors, rounded corner cards, large titles, and data panels. Even if you switch to a different project, the final generated UI might still be in a similar style.

So, programmers also need to possess basic visual judgment ability. After a page is completed, check the layout, component sizes, spacing, fonts, and colors against the design draft, then actually operate it once to confirm whether modals, form validation, and loading states conform to the design.

AI Can Improve Learning Efficiency, But Cannot Replace Practice

Besides writing code, AI is also very helpful for learning new knowledge.

In the past, when entering an unfamiliar field, you usually had to search for information yourself, then look for relevant content from official documentation, blogs, and Q&A sites. When encountering a specific problem, you might need to understand several different concepts simultaneously and then combine this information to find a suitable solution.

Now, you can first ask AI, letting it explain basic concepts, explain which approaches are suitable for which scenarios, or list the knowledge you need to understand based on the current problem. If you encounter something you don't understand, you can continue to ask follow-up questions without needing to search again from scratch each time.

When I first started doing backend development, I was unfamiliar with a lot of backend and cloud service knowledge. When encountering issues like AWS containerized deployment, S3, Route 53, and DNS resolution, I often needed to consult several documents simultaneously. Although the official documentation was very comprehensive, when first encountering these services, it was hard for me to judge which part to read first.

Now, when encountering similar problems, I first send the goal, runtime environment, and error messages to AI, letting it help me analyze possible causes and the order of investigation. This can avoid many detours, without needing to blindly search from the start.

However, this convenience can also easily give people the feeling that they have already learned something.

This is similar to watching tutorials. When watching someone else operate, you always feel you understand every step, but when you close the tutorial and try it yourself, you realize there are still many parts you don't know. AI can help us look up information, explain concepts, and provide ideas when encountering problems, but in the end, you still have to implement and debug it yourself.

When I used to learn new knowledge, I often asked myself three questions:

  1. What is it?
  2. Why do it this way, and can it be done differently?
  3. Is there a better way?

Now, these questions can all be asked to AI, but you can't just look at the answers it gives. You also need to try it yourself, see if what it says is correct, and whether it can be used in an actual project.

Retaining Coding and Debugging Ability

Programmers still need to retain coding and debugging ability.

Only by personally writing, modifying, and debugging code will you gradually become familiar with the call relationships between modules, how states change, and in what order to investigate when a fault occurs. This experience also helps programmers judge whether AI-generated code has problems.

When beginners use AI, the most important thing to watch out for is the black box problem. If you can't understand the generated code and only know that it can run, then this code is a black box to you. When problems arise in the project, you neither know where the cause is nor which part should be modified, and can only continue to send the error messages to AI, then replace the original implementation with the newly generated code.

The more this method is used, the easier it is for the code to become messier. After the current error disappears, the new modification might affect other modules. Because you don't know the reason for each change, even if problems are discovered later, it's hard to judge which code should be kept and which should be reverted.

Usually, you can do some small projects you are interested in yourself, or practice on LeetCode. Without using AI, write the code yourself and solve the problems within it. This can prevent you from not knowing where to start with basic coding and debugging after long-term dependence on AI.

Most of the code at work can be handed over to AI for generation, but after the code is generated, you need to be able to understand it yourself and know why it was changed that way. When AI fails to solve the problem after several consecutive modifications, the programmer must still be able to continue troubleshooting on their own.

Understanding AI Engineering Applications

Programmers also need to understand some knowledge about AI engineering applications.

Most application developers do not need to train large models or delve deeply into underlying algorithms. Usually, you can first understand technologies like RAG, Tool Calling, AI Agent, and structured output, knowing what problems they are respectively suitable for solving.

In the future, many software products may incorporate features like intelligent search, document Q&A, content generation, and automatic task execution. Programmers need to understand how these features integrate into existing systems and what issues need to be handled during the integration process.

For example, when an AI Agent reads files, sends emails, or operates databases, it can only obtain the permissions needed for the current task, cannot access unrelated data, and cannot perform operations beyond its scope.

The data returned by the model also cannot be used directly. Even if it is required to return JSON, the system still needs to check field types, value ranges, and business rules. When encountering model timeouts, returned errors, or incomplete results, the program must also have corresponding handling methods.

Issues like prompt injection, sensitive data leakage, call costs, retry strategies, and result tracking also need to be considered. These are all engineering problems that must be dealt with after AI features are integrated into real systems.

Product Engineers and Technical Experts

The emergence of AI will give more programmers the opportunity to become product engineers.

A product engineer usually has sufficient depth in a certain technology, while also being able to participate in product, design, frontend/backend, testing, deployment, and operations. When encountering a requirement, they can start from problem analysis and follow through all the way to feature launch and user feedback.

In the past, a programmer might have found it difficult to independently build a complete product because they didn't understand design, backend, or deployment. Now, they can use AI to generate solutions and code for parts they are not familiar with, and after checking and modifying, turn ideas into usable products faster.

Product engineers still need to collaborate with product managers, designers, and testers. The difference is that they will pay attention to the complete delivery process, from business goals and solution design all the way to launch and user feedback, not ending after completing the code they are responsible for.

Technical experts will also exist for a long time.

Fields like databases, compilers, distributed systems, security, and infrastructure still require technical experts who study specific problems over the long term. These fields often involve complex performance, reliability, and security issues that require long-term analysis and verification based on the actual operation of the system, not just generating the code and considering it solved.

AI is better at handling tasks with clear rules and high repeatability. Adding a similar management page based on an existing page, or supplementing a set of interfaces according to a fixed format—this type of work can already be mostly handed over to AI.

But solutions in real projects cannot just look at whether the code can be generated; you also need to judge whether it meets business goals, whether it can integrate into the existing system, and whether the team can maintain it long-term. Product engineers need to decide how features should be done, while technical experts need to solve performance, reliability, and security issues. Both directions will exist for a long time.

Summary

Vibe Coding has significantly changed the way programmers work. Whether it's adding features to existing projects, modifying business logic, or troubleshooting problems, AI can participate in requirement analysis, solution discussion, code modification, and testing.

In the future, programmers may no longer need to spend as much time directly writing code, but they still need to think through the requirements clearly, judge whether the solution is suitable for the project, and be responsible for the final changes and running results.

Code can be handed over to AI for generation, but whether it can ultimately be merged, whether it can go live, and how to handle problems after going live still need to be decided by the programmer and the team.