← Назад к вопросам

Как понимаешь что требует функция?

2.0 Middle🔥 132 комментариев
#JavaScript Core

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Чтение и понимание требований функции - мой методический подход

Это важный навык. Перед написанием функции я всегда глубоко разбираюсь, что от неё требуется. Вот мой систематический процесс.

1. Анализ типов (TypeScript/JSDoc)

// TypeScript показывает ЧТО требует функция
function calculateDiscount(
  price: number,           // Необходимо число
  discountPercent: number, // Процент скидки
  minAmount?: number       // Опциональный минимум
): number {
  // Возвращает число (итоговую цену)
  return price * (1 - discountPercent / 100);
}

// Если тип неправильный - TypeScript ругается:
calculateDiscount('100', 20);  // ERROR: Argument of type 'string' is not assignable to parameter of type 'number'
calculateDiscount(100, 20);    // OK

// JSDoc для документации функции
/**
 * Вычисляет финальную цену с учётом скидки
 * @param {number} price - Начальная цена в рублях
 * @param {number} discountPercent - Процент скидки (0-100)
 * @param {number} [minAmount=0] - Минимальная сумма для скидки
 * @returns {number} Финальная цена
 * @throws {Error} Если discountPercent < 0 или > 100
 */
function calculateDiscount(price, discountPercent, minAmount = 0) {
  if (discountPercent < 0 || discountPercent > 100) {
    throw new Error('Discount must be between 0 and 100');
  }
  if (price < minAmount) {
    return price;  // Скидка не применяется
  }
  return price * (1 - discountPercent / 100);
}

2. Анализ поведения (Unit тесты)

// Тесты показывают КАКОЕ поведение ожидается
describe('calculateDiscount', () => {
  test('должна применить скидку корректно', () => {
    expect(calculateDiscount(1000, 20)).toBe(800);
  });

  test('должна вернуть исходную цену если скидка 0%', () => {
    expect(calculateDiscount(1000, 0)).toBe(1000);
  });

  test('должна работать с минимальной суммой', () => {
    expect(calculateDiscount(500, 20, 1000)).toBe(500);  // Скидка не применена
    expect(calculateDiscount(1500, 20, 1000)).toBe(1200); // Скидка применена
  });

  test('должна выбросить ошибку при неправильных параметрах', () => {
    expect(() => calculateDiscount(1000, 150)).toThrow();
  });
});

// Читая тесты, я понимаю:
// - Какие edge cases нужно обработать
// - Какие значения считаются валидными
// - Какие исключительные ситуации возникают

3. Анализ сигнатуры функции

// Простая функция - простые требования
function sum(a: number, b: number): number {
  return a + b;
}

// Сложная функция - сложные требования
interface FetchOptions {
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
  headers?: Record<string, string>;
  body?: unknown;
  timeout?: number;
  retries?: number;
}

interface ApiResponse<T> {
  data: T;
  status: number;
  headers: Record<string, string>;
}

async function fetchWithRetry<T>(
  url: string,
  options?: FetchOptions
): Promise<ApiResponse<T>> {
  // Требования из сигнатуры:
  // 1. Принимает URL строку
  // 2. Опциональный объект конфигурации
  // 3. Generic тип T для типизации данных
  // 4. Возвращает Promise с типизированным ответом
  // 5. Может быть awaited (async function)
}

// Читаю сигнатуру и вижу требования:
// - Должна быть асинхронной
// - Должна работать с любым типом данных (generics)
// - Должна поддерживать множество опций
// - Должна возвращать структурированный ответ

4. Документация и комментарии

// Хорошая документация показывает требования явно
/**
 * Форматирует дату в русский формат
 * @example
 * formatDate(new Date('2024-01-15')) // '15 января 2024'
 * formatDate(new Date('2024-01-15'), 'short') // '15.01.2024'
 * 
 * @param date - Дата для форматирования
 * @param format - Формат ('long' | 'short'), по умолчанию 'long'
 * @returns Отформатированная дата на русском языке
 */
function formatDate(date: Date, format: 'long' | 'short' = 'long'): string {
  // ...
}

// Читая примеры в @example, я вижу ТОЧНОЕ поведение
// которое ожидается от функции

5. Анализ контекста использования

// Где функция используется - показывает требования
// В компоненте React:
export function UserProfile() {
  const user = fetchUser(123);  // Требует ID пользователя
  
  // Значит функция должна:
  // 1. Принимать number (ID)
  // 2. Загружать асинхронно (используется в компоненте)
  // 3. Возвращать user объект или null
}

// В form handler:
const handleSubmit = (data) => {
  const errors = validateFormData(data);
  if (errors.length === 0) {
    submitForm(data);
  }
};

// Требования из контекста:
// - validateFormData возвращает массив ошибок
// - пустой массив = валидные данные
// - submitForm принимает те же данные

6. Читаю код чтобы понять требования

// Если вижу функцию в эксплуатации, понимаю требования:
const apiClient = new ApiClient({
  baseUrl: 'https://api.example.com',
  timeout: 5000,
  retryCount: 3
});

// Требования для конструктора:
// - Принимает объект конфигурации
// - baseUrl должен быть строкой
// - timeout число в миллисекундах
// - retryCount число попыток

const response = await apiClient.get('/users', {
  params: { page: 1, limit: 10 },
  headers: { 'X-Api-Key': 'secret' }
});

// Требования для .get:
// - Асинхронная функция
// - Первый параметр - endpoint
// - Второй - опции (params, headers)
// - Возвращает Promise с ответом

7. Вопросы которые я себе задаю

// Когда видю функцию, я спрашиваю:

// 1. Какие типы параметров нужны?
//    - Принимает примитивы? Объекты? Arrays?

// 2. Какие параметры обязательные, какие опциональные?
//    - Должны быть дефолтные значения?

// 3. Что функция возвращает?
//    - Value, Promise, Observable, void?

// 4. Какие edge cases нужно обработать?
//    - null/undefined? Пустые строки? Отрицательные числа?

// 5. Какие ошибки может вызвать?
//    - throws ошибку или возвращает null?

// 6. Побочные эффекты (side effects)?
//    - Изменяет глобальное состояние?
//    - Делает API запросы?
//    - Логирует что-то?

// Пример применения вопросов:
function updateUserProfile(userId: string, updates: Partial<User>) {
  // 1. Типы: string, объект (Partial означает опциональные поля)
  // 2. Обязательны оба параметра
  // 3. Видимо возвращает Promise<User> (асинхронная)
  // 4. Edge cases: пустой userId? Пустой updates object?
  // 5. Может выбросить 404 если пользователь не найден
  // 6. Side effects: делает PUT запрос, обновляет базу
}

8. Я всегда проверяю наличие типов

// TypeScript делает требования ЯВНЫМИ
interface Button {
  text: string;
  onClick: () => void;  // Требует callback без параметров
  disabled?: boolean;   // Опциональное свойство
  variant?: 'primary' | 'secondary';  // Только эти варианты
}

// VS неясный JavaScript:
function Button(props) {
  // Что в props? Какие поля обязательны?
  // Это гадание!
}

// Хороший JavaScript (с JSDoc):
/**
 * @param {Object} props
 * @param {string} props.text
 * @param {Function} props.onClick
 * @param {boolean} [props.disabled]
 */
function Button(props) {
  // Теперь ясно
}

Итого: система понимания требований

  1. Сигнатура - первый источник информации (типы параметров и возврата)
  2. Документация - примеры и описание поведения
  3. Тесты - точное определение требуемого поведения
  4. Контекст использования - как функция применяется
  5. Исходный код - детали реализации
  6. Типы (TypeScript) - явное выражение требований

Чем полнее я вижу эту информацию, тем лучше я понимаю требования функции и могу её эффективно использовать или модифицировать.