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

Проектуємо та впроваджуємо системи штучного інтелекту: від прототипу до production-ready рішення. Наша команда поєднує експертизу в машинному навчанні, дата-інжинірингу та MLOps, щоб AI працював не в лабораторії, а в реальному бізнесі.
Показано 1 з 1Усі 1566 послуг
Розробка AI-рефакторингу коду
Середній
~1-2 тижні
Часті запитання

Напрямки AI-розробки

Етапи розробки AI-рішення

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1284
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1196
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    901
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1119
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    586
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    853

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 років розробки, 45 000 рядків. 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 тиждень