Разработка AI-рефакторинга кода

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1 услугВсе 1566 услуг
Разработка AI-рефакторинга кода
Средняя
~1-2 недели
Часто задаваемые вопросы
Направления AI-разработки
Этапы разработки AI-решения
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1218
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    853
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1047
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    825

AI-система рефакторинга кода

Рефакторинг без AI упирается в стоимость: senior-разработчик понимает, что нужно сделать, но 80% работы — механическое переписывание. AI берёт эту механику на себя, оставляя человеку архитектурные решения и ревью результата.

Виды рефакторинга и подходы

Структурный рефакторинг (extract method, move class, rename) — хорошо поддаётся автоматизации, высокая точность AI.

Паттерновый рефакторинг (переход с callbacks на async/await, добавление dependency injection) — требует понимания контекста, AI справляется при правильном промпте.

Архитектурный рефакторинг (monolith → microservices, God Object → SRP) — AI генерирует план и черновик, финальные решения за человеком.

Система рефакторинга

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

client = Anthropic()

REFACTORING_TYPES = {
    "extract_function": "Выдели повторяющийся код в отдельные функции",
    "simplify_conditions": "Упрости сложные условные выражения",
    "add_type_hints": "Добавь аннотации типов везде где их нет",
    "async_migration": "Преобразуй синхронный код в async/await",
    "error_handling": "Добавь явную обработку ошибок",
    "dataclass_conversion": "Преобразуй dict-based структуры в dataclasses/Pydantic",
    "dependency_injection": "Добавь dependency injection вместо глобальных объектов",
    "remove_duplication": "Устрани дублирование кода (DRY)",
}

class CodeRefactorer:

    def refactor(
        self,
        source_code: str,
        refactoring_type: str,
        context: str = "",
        preserve_interface: bool = True,
    ) -> dict:
        """Выполняет рефакторинг и возвращает diff"""

        instructions = REFACTORING_TYPES.get(refactoring_type, refactoring_type)

        response = client.messages.create(
            model="claude-sonnet-4-5",
            max_tokens=8096,
            system=f"""Ты — senior разработчик, выполняющий рефакторинг Python кода.

Задача рефакторинга: {instructions}

Правила:
- {"Сохраняй публичный интерфейс (имена функций, аргументы, возвращаемые типы)" if preserve_interface else "Интерфейс можно менять"}
- Не меняй логику — только структуру кода
- Если добавляешь новые вспомогательные функции — размещай их выше основных
- Сохраняй все существующие комментарии и docstrings
- Добавляй комментарий # REFACTORED: <краткое описание> где были ключевые изменения""",
            messages=[{
                "role": "user",
                "content": f"""Выполни рефакторинг:

```python
{source_code}

{f"Контекст проекта:{chr(10)}{context}" if context else ""}

Верни:

  1. Рефакторированный код
  2. Список изменений (bullet points)
  3. Потенциальные риски если есть

Формат ответа:

<рефакторированный код>

Изменения:

  • ...

Риски:

  • ...""" }] )

      text = response.content[0].text
    
      # Парсим ответ
      refactored_code = ""
      if "```python" in text:
          refactored_code = text.split("```python")[1].split("```")[0].strip()
    
      changes = []
      risks = []
      if "**Изменения:**" in text:
          changes_section = text.split("**Изменения:**")[1].split("**Риски:**")[0]
          changes = [line.strip("- ").strip() for line in changes_section.splitlines() if line.strip().startswith("-")]
    
      if "**Риски:**" in text:
          risks_section = text.split("**Риски:**")[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 — пример реального рефакторинга

```python
def migrate_to_async(source_file: str) -> str:
    """Мигрирует синхронный код на async/await"""

    source = Path(source_file).read_text()

    response = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=8096,
        system="""Мигрируй Python код с синхронного на async/await.

Правила:
- requests → httpx.AsyncClient
- time.sleep(n) → asyncio.sleep(n)
- threading.Thread → asyncio.create_task
- queue.Queue → asyncio.Queue
- Добавь async/await к функциям, которые делают I/O
- Оставь синхронными функции без I/O (чистые вычисления)
- Замени for loop на asyncio.gather где функции независимы""",
        messages=[{
            "role": "user",
            "content": f"Мигрируй на async/await:\n\n```python\n{source}\n```\n\nВерни только код."
        }]
    )

    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:
    """Добавляет аннотации типов к функциям"""
    source = Path(source_file).read_text()

    # Находим функции без аннотаций
    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"""Добавь аннотации типов Python (PEP 484) к функциям: {', '.join(unannotated)}

Правила:
- Используй from __future__ import annotations для forward references
- Для Optional используй X | None (Python 3.10+)
- Для коллекций: list[str], dict[str, int], tuple[int, ...]
- Для неизвестных типов используй Any из typing

```python
{source}

Верни полный файл с добавленными аннотациями.""" }] )

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

### Рефакторинг с тестовой страховкой

```python
def safe_refactor(
    source_file: str,
    refactoring_type: str,
    test_file: str = None,
) -> dict:
    """Выполняет рефакторинг только если тесты проходят"""

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

    # Сначала запускаем существующие тесты
    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}

    # Выполняем рефакторинг
    refactoring = refactorer.refactor(source, refactoring_type)

    # Создаём backup
    backup_file = source_file + ".bak"
    Path(backup_file).write_text(source)

    # Записываем рефакторированный код
    Path(source_file).write_text(refactoring["refactored"])

    # Запускаем тесты снова
    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:
            # Откатываемся
            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,
    }

Практический кейс: Django-монолит

Ситуация: Django-проект, 6 лет разработки, 45000 строк. 3 проблемы: нет type hints (новые разработчики тратят много времени на понимание типов), много дублирования в view-функциях, 12 God Object классов.

Применённые рефакторинги (за 3 недели):

  1. add_type_hints для всех views.py файлов — автоматически, 2 часа
  2. extract_function для view-функций > 50 строк — автоматически + ревью, 1 неделя
  3. remove_duplication в сервисном слое — автоматически, 3 дня

Результаты:

  • Type annotations coverage: 12% → 87%
  • Средняя длина функции: 68 строк → 23 строки
  • Дублирование кода (SonarQube metric): -43%
  • Время онбординга нового разработчика: 3 недели → 1.5 недели

Один God Object (OrderService, 1800 строк) потребовал ручного архитектурного решения — AI предложил 3 варианта декомпозиции, разработчики выбрали оптимальный.

Сроки

  • Базовый рефакторинг одного типа для файла: 1–2 дня
  • Система safe_refactor с тестовой страховкой: 3–5 дней
  • Batch-рефакторинг всей кодовой базы: 2–3 недели
  • Интеграция в IDE как команда: 1 неделя