Skip to main content
黯羽轻扬Keep Growing Daily

AI coding: 5 Engineering Lessons I Learned After It Went Viral

Free2026-07-03#AI#AI

AI coding tools are not a silver bullet. I summarized 5 key lessons from real projects: why code reviews cannot be skipped, why migration plans need rollback points, and why prompt structure is far more important than imagined.

First encounter with the real scene of AI generating code

Last year, I took over a legacy Spring Boot microservice and needed to migrate the internal user authentication module to OAuth 2.1. The team had only three people, and the window was three weeks. Naturally, I thought of using the AI programming tool (Cursor + GPT-4) to speed things up. It started off smoothly: AI generated new authentication filters, token storage layers, and configuration classes, totaling about 800 lines of code, covering routes, exception handling, and some testing.

However, the issue erupted during integration testing: AI generated SecurityFilterChain configuration with two @Order annotations conflicted, causing some API endpoints to bypass authentication. Even more hidden is a null pointer in JwtAuthenticationConverter, where AI does not handle the missing claims field. Fixing these five issues took longer than writing manually, because you first had to understand AI your own "thinking"—it habitually uses Optional but isn't exactly consistent.

This scene made me realize: AI The biggest pitfall in coding isn't that it can't write code, but that you mistakenly believe the code it writes can be trusted directly.

4 Conclusions That Truly Change the Way You Judge

**First, code review cannot be skipped, but the subject of review has changed. ** Previously, reviewed colleague code, focusing on logic and style. Now review AI code, focusing on boundary conditions, exception paths, and implicit coupling with existing systems. AI is very good at generating code that "looks right," but often misses corners like null, out-of-bounds, and timeouts. My later approach was: before merging AI code each time, I specifically checked for three types of questions: 1) non-null assumptions for all input and output parameters; 2) Default behavior for all branch conditions; 3) Timeouts and retries of all asynchronous operations.

**Second, migration tasks should be replaced in phases, not completely rewritten. ** The biggest mistake I made during the OAuth migration was having AI generate replacement code for the entire module at once. A better approach is: first have AI generate a "proxy filter" compatible with both new and old authentications, gradually cutting traffic; Each step retains the old code as the rollback point. It took me two days working overtime to learn this lesson.

**Third, prompt structure directly affects output quality. ** It's not just about writing "Generate OAuth 2.1 configuration". I later fixed a three-part prompt: 1) clarify the problem context (framework version, existing structure, constraints); 2) Specific output format (class name, method signature, comment style); 3) Pitfalls to avoid (such as not using deprecated APIs or introducing new dependencies). Significant improvement in effectiveness, with error rates reduced by at least 40%.

**Fourth, AI is more suitable for "from 0 to 1" rather than "from 1 to 0.9." ** Prototypes, scaffolding, and demo code are AI's strengths; But when you need to make fine modifications to an existing system, AI can easily break existing logic. Now I isolate usage scenarios: new feature prototypes use AI, and existing modifications remain manual.

A laptop screen displaying a migration checklist, listing rollback points, compatibility tests, and other steps

Pitfalls Stepped On and Corrected Paths

The biggest pitfall: **No independent test layer was established for code generated by AI. ** I directly have AI generate code and then run it in the existing test suite. However, code generated by AI often requires special mock data or configurations that existing tests do not cover. The result was that the test passed, but the integration failed. The fix is to create a ai-generated/ directory, place all AI code in that directory first, write independent unit tests and integrated contract tests for it, and after passing them, merge them into the main codebase.

Another pitfall: **Excessive trust AI "explanations." ** When I ask "Why do this?", AI gives a reasoning that sounds reasonable, but sometimes it's an illusion. When AI explains a @Transactional propagation behavior, its reasoning is based on old Spring 5 behavior, while the project uses Spring 6's Jakarta namespace. Now I need to verify the official documentation before asking, or have AI cite it at the same time.

A laptop screen displaying a migration checklist, listing rollback points, compatibility tests, and other steps

If you're doing similar work, the most worthwhile step is to copy first

Set up a "AI Code Access Checklist", and after each time you get a code from AI, manually check the following items:

  1. Are the default values of all external inputs (parameters, environment variables, configuration files) reasonable?
  2. Are all exception paths swallowed (empty catch blocks or logs not recovered)?
  3. Do all asynchronous calls have timeout settings (especially for network requests)?
  4. Does the generated code introduce new dependencies that the project does not have (check import and build files)?
  5. Does the code style comply with the team's existing standards (indentation, naming, comment patterns)?

I posted this list for every team member next to the monitor. After two weeks of use, the online failure rate dropped by about 35%.

When to keep investing and when to change course

Conditions for continued investment: **When you see code generated by AI after passing the access list, the amount of modifications is less than 30% of the handwritten volume. ** If your scenario is creating new modules, writing sample code, writing test cases, generating SQL or scripts—these are AI's comfort zones, and you can keep using them.

Signal to change route: **Modify AI code more than twice the time spent writing it, or fix one bug that leads to three new bugs. ** For example, during that OAuth migration, I spent 4 hours debugging AI the configuration, but eventually gave up and spent 1.5 hours rewriting myself. This scenario indicates that the current task has exceeded the capability boundaries of AI—often involving legacy systems, complex context dependencies, or non-standard configurations.

There are two other situations where you should clearly stop: 1) You cannot understand the code logic generated by AI (complex lambda chains or abstract bridge patterns); 2) Code generated by AI contains external dependencies you cannot fully test (for example, directly calling third-party APIs without mocking). Manual implementation is safer at this point.

Comments

No comments yet. Be the first to share your thoughts.

Leave a comment