AIAI University/ Stadika Смотреть курсы
AI University / Промпты / Программисту
Программисту

Промпт: рефакторинг легаси-кода по шагам

Разбор неочевидного поведения, характеризационные тесты и рефакторинг маленькими безопасными шагами. Готовый промт на русском с ответами нейросетей: посмотрите, что выдают GigaChat, ChatGPT, Claude и Gemini, и откройте текст промпта, чтобы запускать его со своими данными.

Проверено на: GigaChatChatGPTClaudeGemini · Обновлено 01.10.2026

Текст промпта

Текст промпта открывается с доступом к библиотеке

Ответы нейросетей ниже получены этим промптом на примере из таблицы. Чтобы скопировать промпт и запускать его со своими данными, откройте доступ ко всем промптам или полный доступ к AI University.

Разовый платёж, без подписки. Новые промпты входят в доступ.

Что подставить в промт

ПолеПример
{context}PHP 8.1, интернет-магазин на самописном фреймворке, PHPUnit, функция вызывается из 6 мест
{code}function calcDelivery($order, $city, $isVip = false) {
$sum = 0;
foreach ($order['items'] as $i) { $sum += $i['price'] * $i['qty']; }
if ($city == 'Москва' || $city == 'москва' || $city == 'МСК') {
if ($sum > 5000) return 0;
$d = 350;
} else {
$w = 0;
foreach ($order['items'] as $i) { $w += $i['weight'] * $i['qty']; }
$d = 450 + ($w > 5 ? ($w - 5) * 60 : 0);
if ($sum > 15000) $d = $d / 2;
}
if ($isVip) $d = 0;
if (date('N') == 7) $d += 100;
return round($d);
}
{pain}не покрыть тестами из-за date(), правила по городам скоро расширятся, магические числа, непонятно, должна ли наценка в воскресенье действовать для бесплатной доставки

Ответы нейросетей на этот промпт

Один и тот же промпт с примером выше, ответы без правок: выберите нейросеть, которой пользуетесь, и посмотрите, что она выдаёт.

GigaChat 2 Max06.10.2026

1. Текущая функциональность

Функция calcDelivery рассчитывает стоимость доставки заказа исходя из следующих факторов:

Особенности текущего поведения:

2. Характеризационные тесты

Тестируемое поведение включает следующие случаи:

use PHPUnit\Framework\TestCase;

class DeliveryTest extends TestCase
{
    public function testFreeDeliveryInMoscowOverThreshold()
    {
        // Тест для Москвы, сумма заказа больше 5000 рублей -> бесплатно
        $order = ['items' => [['price' => 3000, 'qty' => 1]]];
        $this->assertEquals(0, calcDelivery($order, 'Москва'));
    }
    
    public function testPaidDeliveryInMoscowUnderThreshold()
    {
        // Тест для Москвы, сумма заказа меньше 5000 рублей -> платим 350 руб.
        $order = ['items' => [['price' => 1000, 'qty' => 1]]];
        $this->assertEquals(350, calcDelivery($order, 'Москва'));
    }
    
    public function testWeightBasedDeliveryOutsideMoscow()
    {
        // Стандартный случай вне Москвы, доставка зависит от веса
        $order = [
            'items' => [
                ['price' => 1000, 'qty' => 1],
                ['price' => 2000, 'qty' => 1]
            ]
        ];
        $expectedDeliveryCost = 450;
        
        $this->assertEquals($expectedDeliveryCost, calcDelivery($order, 'Санкт-Петербург'));
    }
    
    public function testHeavyOrderDeliveryOutsideMoscow()
    {
        // Ситуация, когда общий вес больше порогового (5кг)
        $order = [
            'items' => [
                ['price' => 1000, 'qty' => 1, 'weight' => 6], 
                ['price' => 2000, 'qty' => 1, 'weight' => 1]
            ]
        ];
        $expectedDeliveryCost = 450 + ((6+1)-5)*60; // Вес 7 кг, доплата за превышение нормы
        
        $this->assertEquals($expectedDeliveryCost, calcDelivery($order, 'Краснодар'));
    }
    
    public function testDiscountedDeliveryForBigOrdersOutsideMoscow()
    {
        // Скидочная ситуация для больших заказов вне Москвы
        $order = [
            'items' => [
                ['price' => 10000, 'qty' => 1],
                ['price' => 6000, 'qty' => 1]
            ]
        ];
        $expectedDeliveryCost = ceil((450)/2); // Цена делится пополам при большой сумме заказа
        
        $this->assertEquals($expectedDeliveryCost, calcDelivery($order, 'Ростов-на-Дону'));
    }
    
    public function testSundaySurcharge()
    {
        // Проверяем работу воскресной надбавки
        $originalDateFunction = function () {};
        setTimezone('Europe/Moscow');
        timecop_freeze(strtotime('next Sunday')); // замораживаем время на ближайшее воскресенье
        
        try {
            $order = ['items' => [['price' => 1000, 'qty' => 1]]]; // простой заказ
            
            $expectedDeliveryCost = 450 + 100; // Базовая ставка + надбавка за воскресенье
            $this->assertEquals($expectedDeliveryCost, calcDelivery($order, 'Питер'));
        } finally {
            timecop_return(); // возвращаем оригинальное время
        }
    }
    
    public function testVIPFreeDelivery()
    {
        // Бесплатная доставка для VIP-клиентов
        $order = ['items' => [['price' => 1000, 'qty' => 1]]];
        $this->assertEquals(0, calcDelivery($order, 'Питер', true));
    }
}

3. Рефакторинг пошагово

Рефакторинг будет состоять из нескольких этапов, каждый из которых стоит делать отдельным коммитом:

Шаг 1: Изоляция расчёта суммы заказа

Вынесем расчёт общей суммы заказа в отдельную функцию.

function getTotalAmount($order): float {
    $total = 0;
    foreach ($order['items'] as $item) {
        $total += $item['price'] * $item['qty'];
    }
    return $total;
}

// Использование новой функции
function calcDelivery($order, $city, $isVip = false) {
    $sum = getTotalAmount($order);
    ...
}

Комментарий: Так мы уменьшили дублирование и сделали первый шаг к выделению логики.

Шаг 2: Выделяем подсчёт общего веса

Аналогично создадим отдельную функцию для вычисления суммарного веса заказа.

function getTotalWeight($order): float {
    $totalWeight = 0;
    foreach ($order['items'] as $item) {
        $totalWeight += $item['weight'] * $item['qty'];
    }
    return $totalWeight;
}

// Использование новой функции
function calcDelivery($order, $city, $isVip = false) {
    $sum = getTotalAmount($order);
    $w = getTotalWeight($order);
    ...
}

Комментарий: Теперь логика разделения становится понятнее, и читаемость улучшается.

Шаг 3: Абстрагируем условие города

Заменим проверку строки имени города регуляркой или преобразованием регистра. Это улучшит поддержку новых правил в будущем.

function isMoscow($city): bool {
    return strcasecmp(trim($city), 'Москва') === 0 || trim($city) === 'МСК';
}

// Обновляем логику в основной функции
if (isMoscow($city)) {
    if ($sum > 5000) return 0;
    $d = 350;
} else {
    ...
}

Комментарий: Логика проверки стала более явной и гибкой.

Шаг 4: Вынос условия бесплатности VIP-заказов

Создаём отдельный блок обработки VIP-статуса, чтобы чётко выделить этот аспект.

function applyVIPStatus($deliveryCost, $isVip): int {
    return $isVip ? 0 : $deliveryCost;
}

// Вызываем новую функцию после расчётов
function calcDelivery($order, $city, $isVip = false) {
    ...
    $finalCost = applyVIPStatus($d, $isVip);
    return round($finalCost);
}

Комментарий: Теперь проверка статуса VIP-пользователя выполняется централизованно и ясно выражена.

Шаг 5: Заморозка даты через моки для тестов

Для тестирования воскресной наценки используем библиотеку TimeCop (для простоты примера можно использовать заглушку). Нужно обернуть использование текущей даты в функцию, которую можем контролировать в тестах.

function currentDayOfWeek(): string {
    return date('N'); // Возвращает номер дня недели
}

// Используем эту функцию
if (currentDayOfWeek() == 7) $d += 100;

Комментарий: Мы вынесли вызов даты в изолированную функцию, теперь её можно менять в тестах.

Шаг 6: Удаление магических чисел

Добавим константы для значений лимитов и базовых тарифов.

define('FREE_DELIVERY_THRESHOLD_MOSCOW', 5000);
define('DELIVERY_COST_MOSCOW', 350);
define('DELIVERY_COST_BASE', 450);
define('WEIGHT_SURCHARGE_RATE', 60);
define('SUNDAY_SURCHARGE', 100);
define('DISCOUNT_THRESHOLD_OUTSIDE_MOSCOW', 15000);

// Используем новые константы везде, где были магические числа
...

Комментарий: Чёткое обозначение используемых величин повысило прозрачность алгоритма.


4. Итоговый код после рефакторинга

<?php

define('FREE_DELIVERY_THRESHOLD_MOSCOW', 5000);
define('DELIVERY_COST_MOSCOW', 350);
define('DELIVERY_COST_BASE', 450);
define('WEIGHT_SURCHARGE_RATE', 60);
define('SUNDAY_SURCHARGE', 100);
define('DISCOUNT_THRESHOLD_OUTSIDE_MOSCOW', 15000);

function getTotalAmount($order): float {
    $total = 0;
    foreach ($order['items'] as $item) {
        $total += $item['price'] * $item['qty'];
    }
    return $total;
}

function getTotalWeight($order): float {
    $totalWeight = 0;
    foreach ($order['items'] as $item) {
        $totalWeight += $item['weight'] * $item['qty'];
    }
    return $totalWeight;
}

function isMoscow($city): bool {
    return strcasecmp(trim($city), 'Москва') === 0 || trim($city) === 'МСК';
}

function applyVIPStatus($deliveryCost, $isVip): int {
    return $isVip ? 0 : $deliveryCost;
}

function currentDayOfWeek(): string {
    return date('N');
}

function calcDelivery($order, $city, $isVip = false) {
    $sum = getTotalAmount($order);
    $w = getTotalWeight($order);

    if (isMoscow($city)) {
        if ($sum >= FREE_DELIVERY_THRESHOLD_MOSCOW) return 0;
        $d = DELIVERY_COST_MOSCOW;
    } else {
        $extraWeightCharge = max(($w - 5), 0) * WEIGHT_SURCHARGE_RATE;
        $d = DELIVERY_COST_BASE + $extraWeightCharge;
        if ($sum >= DISCOUNT_THRESHOLD_OUTSIDE_MOSCOW) $d /= 2;
    }

    if (currentDayOfWeek() == 7 && $d != 0) $d += SUNDAY_SURCHARGE;

    return round(applyVIPStatus($d, $isVip));
}

5. Возможные риски и места проверки

После рефакторинга рекомендуется провести дополнительные проверки на следующем этапе:

Таким образом, результаты теста помогут убедиться, что никаких неожиданных изменений поведения не произошло.

Советы

Как пользоваться
  1. Откройте доступ и скопируйте промпт кнопкой выше.
  2. Замените поля в фигурных скобках своими данными.
  3. Отправьте в нейросеть и сравните ответ с примером на этой странице.

Подробнее о структуре хорошего запроса: гид AI University.

Похожие промпты

ПрограммистуБесплатно Найти причину ошибки по стектрейсу и логамВероятная причина плавающей ошибки, гипотезы с проверками, исправление и защита от повторения. 4 ответаОткрытьПрограммистуБесплатно Ускорить медленный SQL-запрос по EXPLAINРазбор плана выполнения, индексы и переписанный запрос, безопасное создание индекса на проде. 4 ответаОткрытьПрограммистуБесплатно Ревью pull request по diffРевью изменений с приоритетами: блокирующие ошибки, безопасность, тесты, готовые комментарии. 4 ответаОткрыть

Все 435 промптов и 6 наборов

172 промптов открыты бесплатно. Остальные и наборы-цепочки открывает доступ к библиотеке за 1 490 ₽. Полный доступ за 4 900 ₽: все курсы AI University на русском и библиотека промптов. Разовый платёж, новые промпты входят.