AI Code Refactoring System Development

We design and deploy artificial intelligence systems: from prototype to production-ready solutions. Our team combines expertise in machine learning, data engineering and MLOps to make AI work not in the lab, but in real business.
Showing 1 of 1All 1566 services
AI Code Refactoring System Development
Medium
~1-2 weeks
Frequently Asked Questions

AI Development Areas

AI Solution Development Stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1284
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1197
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    902
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1119
  • image_logo-advance_0.webp
    B2B Advance company logo design
    586
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    853

AI-Powered Code Refactoring System

Refactoring without AI hits a cost ceiling: a senior developer understands what needs to be done, but 80% of the work is mechanical rewriting. AI handles this mechanics, leaving humans responsible for architectural decisions and result review.

Types of Refactoring and Approaches

Structural refactoring (extract method, move class, rename) — highly amenable to automation, high AI accuracy.

Pattern refactoring (transition from callbacks to async/await, adding dependency injection) — requires context understanding, AI handles it well with proper prompting.

Architectural refactoring (monolith → microservices, God Object → SRP) — AI generates plan and draft, final decisions rest with humans.

Refactoring System

from anthropic import Anthropic
from pathlib import Path
import subprocess
import ast
from typing import Literal

client = Anthropic()

REFACTORING_TYPES = {
    "extract_function": "Extract repeated code into separate functions",
    "simplify_conditions": "Simplify complex conditional expressions",
    "add_type_hints": "Add type annotations everywhere they're missing",
    "async_migration": "Transform synchronous code to async/await",
    "error_handling": "Add explicit error handling",
    "dataclass_conversion": "Transform dict-based structures into dataclasses/Pydantic",
    "dependency_injection": "Add dependency injection instead of global objects",
    "remove_duplication": "Eliminate code duplication (DRY)",
}

class CodeRefactorer:

    def refactor(
        self,
        source_code: str,
        refactoring_type: str,
        context: str = "",
        preserve_interface: bool = True,
    ) -> dict:
        """Performs refactoring and returns diff"""

        instructions = REFACTORING_TYPES.get(refactoring_type, refactoring_type)

        response = client.messages.create(
            model="claude-sonnet-4-5",
            max_tokens=8096,
            system=f"""You are a senior developer performing Python code refactoring.

Refactoring task: {instructions}

Rules:
- {"Preserve public interface (function names, arguments, return types)" if preserve_interface else "Interface can be changed"}
- Do not change logic — only code structure
- If adding new helper functions — place them above main ones
- Preserve all existing comments and docstrings
- Add comment # REFACTORED: <brief description> where there were key changes""",
            messages=[{
                "role": "user",
                "content": f"""Perform refactoring:

```python
{source_code}

{f"Project context:{chr(10)}{context}" if context else ""}

Return:

  1. Refactored code
  2. List of changes (bullet points)
  3. Potential risks if any

Response format:

<refactored code>

Changes:

  • ...

Risks:

  • ...""" }] )

      text = response.content[0].text
    
      # Parse response
      refactored_code = ""
      if "```python" in text:
          refactored_code = text.split("```python")[1].split("```")[0].strip()
    
      changes = []
      risks = []
      if "**Changes:**" in text:
          changes_section = text.split("**Changes:**")[1].split("**Risks:**")[0]
          changes = [line.strip("- ").strip() for line in changes_section.splitlines() if line.strip().startswith("-")]
    
      if "**Risks:**" in text:
          risks_section = text.split("**Risks:**")[1]
          risks = [line.strip("- ").strip() for line in risks_section.splitlines() if line.strip().startswith("-")]
    
      return {
          "original": source_code,
          "refactored": refactored_code,
          "changes": changes,
          "risks": risks,
      }
    

### Async Migration — Real Refactoring Example

```python
def migrate_to_async(source_file: str) -> str:
    """Migrates synchronous code to async/await"""

    source = Path(source_file).read_text()

    response = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=8096,
        system="""Migrate Python code from synchronous to async/await.

Rules:
- requests → httpx.AsyncClient
- time.sleep(n) → asyncio.sleep(n)
- threading.Thread → asyncio.create_task
- queue.Queue → asyncio.Queue
- Add async/await to functions doing I/O
- Keep synchronous functions without I/O (pure computations)
- Replace for loops with asyncio.gather where functions are independent""",
        messages=[{
            "role": "user",
            "content": f"Migrate to async/await:\n\n```python\n{source}\n```\n\nReturn code only."
        }]
    )

    text = response.content[0].text
    if "```python" in text:
        return text.split("```python")[1].split("```")[0].strip()
    return text

def add_type_hints(source_file: str) -> str:
    """Adds type annotations to functions"""
    source = Path(source_file).read_text()

    # Find functions without annotations
    tree = ast.parse(source)
    unannotated = []
    for node in ast.walk(tree):
        if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
            has_annotations = (
                any(arg.annotation for arg in node.args.args) or
                node.returns is not None
            )
            if not has_annotations:
                unannotated.append(node.name)

    if not unannotated:
        return source

    response = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=8096,
        messages=[{
            "role": "user",
            "content": f"""Add Python type annotations (PEP 484) to functions: {', '.join(unannotated)}

Rules:
- Use from __future__ import annotations for forward references
- For Optional use X | None (Python 3.10+)
- For collections: list[str], dict[str, int], tuple[int, ...]
- For unknown types use Any from typing

```python
{source}

Return full file with added annotations.""" }] )

text = response.content[0].text
if "```python" in text:
    return text.split("```python")[1].split("```")[0].strip()
return text

### Refactoring with Test Insurance

```python
def safe_refactor(
    source_file: str,
    refactoring_type: str,
    test_file: str = None,
) -> dict:
    """Performs refactoring only if tests pass"""

    source = Path(source_file).read_text()
    refactorer = CodeRefactorer()

    # First run existing tests
    if test_file and Path(test_file).exists():
        result = subprocess.run(
            ["python", "-m", "pytest", test_file, "-v", "--tb=short"],
            capture_output=True, text=True
        )
        if result.returncode != 0:
            return {"success": False, "error": "Tests failing before refactoring", "test_output": result.stdout}

    # Perform refactoring
    refactoring = refactorer.refactor(source, refactoring_type)

    # Create backup
    backup_file = source_file + ".bak"
    Path(backup_file).write_text(source)

    # Write refactored code
    Path(source_file).write_text(refactoring["refactored"])

    # Run tests again
    if test_file and Path(test_file).exists():
        result = subprocess.run(
            ["python", "-m", "pytest", test_file, "-v", "--tb=short"],
            capture_output=True, text=True
        )

        if result.returncode != 0:
            # Roll back
            Path(source_file).write_text(source)
            return {
                "success": False,
                "error": "Tests failing after refactoring — rolled back",
                "changes": refactoring["changes"],
                "test_output": result.stdout,
            }

    return {
        "success": True,
        "changes": refactoring["changes"],
        "risks": refactoring["risks"],
        "backup": backup_file,
    }

Practical Case: Django Monolith

Situation: Django project, 6 years of development, 45,000 lines. 3 problems: no type hints (new developers spend much time understanding types), lots of view-function duplication, 12 God Object classes.

Applied refactorings (over 3 weeks):

  1. add_type_hints for all views.py files — automatic, 2 hours
  2. extract_function for view-functions > 50 lines — automatic + review, 1 week
  3. remove_duplication in service layer — automatic, 3 days

Results:

  • Type annotations coverage: 12% → 87%
  • Average function length: 68 lines → 23 lines
  • Code duplication (SonarQube metric): -43%
  • New developer onboarding time: 3 weeks → 1.5 weeks

One God Object (OrderService, 1800 lines) required manual architectural decision — AI proposed 3 decomposition options, developers chose the optimal one.

Timeline

  • Basic refactoring of one type for a file: 1–2 days
  • safe_refactor system with test insurance: 3–5 days
  • Batch refactoring of entire codebase: 2–3 weeks
  • IDE integration as a command: 1 week