Introduction
Legacy code is the silent productivity killer in many software teams. According to the 2025 Stack Overflow Developer Survey, over 60% of developers report spending at least 30% of their time working with legacy systems. Refactoring legacy code is not just about cleaning up — it's about reducing technical debt, improving maintainability, and enabling faster feature delivery. However, the process can be daunting without a clear strategy. This article provides 10 ready-to-use prompts for refactoring legacy code, designed to guide you through analysis, decomposition, testing, and modernization. Each prompt is accompanied by a real-world example to help you apply it immediately.
Why Prompt-Based Refactoring Works
Refactoring legacy code requires systematic thinking. Prompts act as structured thought starters, forcing you to ask the right questions before making changes. They help you avoid common pitfalls like over-engineering, breaking existing functionality, or missing critical dependencies. By using prompts, you can standardize your refactoring process across the team and ensure consistency.
10 Prompts for Refactoring Legacy Code
1. Dependency Mapping Prompt
| Aspect |
Details |
| Task |
Identify all direct and transitive dependencies in a legacy module |
| Prompt |
"Analyze the class OrderProcessor in the src/legacy package. List every method call, import, and external library it uses. Group dependencies into: (a) internal core, (b) internal utility, (c) third-party, (d) database/API. For each dependency, note if it is used for reading, writing, or both. Output a dependency graph in Mermaid format." |
| Example |
A developer runs this prompt on a 2000-line C# class and discovers 14 unused imports and 3 circular dependencies, which are then removed or refactored, reducing build time by 15%. |
2. Dead Code Detection Prompt
| Aspect |
Details |
| Task |
Find unused methods, variables, or classes |
| Prompt |
"Scan the src/legacy directory for any function, method, or variable that is defined but never called or referenced anywhere in the codebase (excluding test files). For each candidate, provide the file path, line number, and reason why it appears unused. Then suggest safe removal steps, including any required import cleanup." |
| Example |
After applying this prompt to a Java project, the team removed 47 dead methods, cutting the codebase size by 8% and improving IDE performance. |
3. Test Coverage Gap Analysis Prompt
| Aspect |
Details |
| Task |
Identify untested code paths in a legacy function |
| Prompt |
"Given the function calculateDiscount(customer, order) in src/legacy/DiscountEngine.java, generate a list of all possible input combinations (null, edge cases, boundary values). For each combination, state whether a unit test exists (check test/ directory). If no test exists, write a JUnit 5 test case for that scenario. Use parameterized tests where appropriate." |
| Example |
The prompt reveals that the function has 6 branches but only 2 are tested. The generated tests catch a bug where customer being null caused a NullPointerException. |
4. SQL Query Optimization Prompt
| Aspect |
Details |
| Task |
Refactor inefficient SQL queries embedded in legacy code |
| Prompt |
"Extract all SQL queries from src/legacy/DataAccess.java. For each query, explain: (1) the execution plan using EXPLAIN, (2) which indexes are missing, (3) whether it can be rewritten using joins instead of subqueries, (4) whether it can be replaced with a stored procedure or ORM call. Rewrite the top 3 slowest queries with optimized versions." |
| Example |
A developer finds a query with a subquery that runs in 4.2 seconds. After rewriting it as a JOIN and adding an index, the query executes in 0.03 seconds — a 140x improvement. |
5. Extract Method Refactoring Prompt
| Aspect |
Details |
| Task |
Break down a large, monolithic function into smaller, testable methods |
| Prompt |
"The function processInvoice in src/legacy/InvoiceProcessor.java is 450 lines long. Identify distinct logical sections (e.g., validation, calculation, formatting, logging). For each section, propose an extracted method with a meaningful name, input parameters, and return type. Show the refactored code with the original function calling the new methods. Ensure no side effects are introduced." |
| Example |
The function is split into 7 methods. Unit test coverage increases from 10% to 85%, and a bug in the tax calculation is isolated and fixed. |
6. Error Handling Standardization Prompt
| Aspect |
Details |
| Task |
Replace inconsistent error handling with a unified approach |
| Prompt |
"List all exception types caught and thrown in src/legacy/*.php. Identify places where exceptions are swallowed (empty catch blocks) or where generic Exception is caught. Propose a hierarchy of custom exceptions (e.g., ValidationException, ProcessingException) and refactor the code to use them. Also add proper logging using Monolog for each exception." |
| Example |
The team finds 23 empty catch blocks. After refactoring, 15 critical bugs are exposed and fixed, and error logs become actionable. |
7. Configuration Externalization Prompt
| Aspect |
Details |
| Task |
Move hardcoded configuration values to external config files |
| Prompt |
"Search src/legacy for hardcoded strings that look like configuration values: database connection strings, API keys, URLs, timeouts, page sizes. For each, suggest a configuration key name and where it should be stored (e.g., .env, config.yaml, environment variables). Provide a migration plan that includes backward compatibility for existing deployments." |
| Example |
32 hardcoded values are moved to a .env file, enabling the application to be deployed to staging and production without code changes. |
8. Duplicate Code Consolidation Prompt
| Aspect |
Details |
| Task |
Find and merge duplicate code blocks |
| Prompt |
"Run a clone detection tool (e.g., PMD-CPD or Simian) on the src/legacy directory. For each set of duplicate code blocks (minimum 10 lines, similarity >80%), provide: (1) file paths and line numbers, (2) the duplicate code snippet, (3) a refactored version that extracts the common logic into a shared utility or base class. Avoid introducing coupling by keeping the extraction in the same module." |
| Example |
The team finds 12 duplicate blocks totaling 800 lines. After consolidation, the codebase shrinks by 5% and maintenance time decreases by 20%. |
9. API Migration Prompt (REST to GraphQL or gRPC)
| Aspect |
Details |
| Task |
Plan migration of legacy REST endpoints to a modern API paradigm |
| Prompt |
"Given the legacy REST API in src/legacy/api/, list all endpoints with their HTTP methods, parameters, and response formats. For each endpoint, determine: (1) if it can be mapped to a GraphQL query or mutation, (2) which fields are unused by clients (based on logs), (3) the new schema definition in SDL. Provide a step-by-step migration plan that allows both old and new APIs to coexist for 3 months." |
| Example |
A REST API with 50 endpoints is replaced with 4 GraphQL queries, reducing network payload by 60% and client-side code by 40%. |
10. Performance Profiling and Refactoring Prompt
| Aspect |
Details |
| Task |
Identify and fix performance bottlenecks in legacy code |
| Prompt |
"Profile the src/legacy module using Xdebug or Blackfire. List the top 5 functions with the highest execution time. For each function, provide: (1) the current implementation, (2) the bottleneck (e.g., N+1 query, loop overhead, inefficient algorithm), (3) a refactored version with benchmarks showing expected improvement. Focus on changes that do not alter the API contract." |
| Example |
A function that loops over a database query 1000 times is refactored to use a single batch query, reducing response time from 12 seconds to 0.4 seconds. |
Practical Recommendations
- Always refactor with tests: Before making any changes, ensure you have a safety net. Use the Test Coverage Gap Analysis prompt to add missing tests.
- Work in small batches: Refactor one module at a time. Use the Dependency Mapping prompt to understand the impact before touching code.
- Use automation: Integrate prompts with tools like ChatGPT API or local LLMs to automate analysis. ASI Biont supports connecting to large language models through API for automated refactoring code review — подробнее на asibiont.com/courses.
- Document decisions: Keep a log of what was refactored and why. This helps onboard new team members and justifies time spent.
Conclusion
Refactoring legacy code is a continuous process that requires discipline, strategy, and the right tools. The 10 prompts provided in this article give you a concrete starting point for analyzing, testing, and modernizing your codebase. By using these prompts, you can reduce technical debt, improve performance, and make your code more maintainable for future developers. Start with the Dependency Mapping prompt to understand what you're dealing with, then tackle Dead Code Detection and Test Coverage Gap Analysis to build a safety net. The rest of the prompts will help you systematically improve your legacy system without breaking existing functionality.
Remember: the goal of refactoring is not to rewrite everything from scratch, but to make incremental improvements that compound over time. Each small refactoring step reduces complexity and makes the next step easier. Use these prompts as a checklist for your next refactoring session, and you'll see measurable improvements in code quality and team productivity.
Comments