Классическая жизнь фронтенд-приложений и их сопровождение

72ae9d91e43da918021a91b39cf41ef6

Проблемы больших проектов: сопровождение компонентов и фанатичность принципу DRY

Рассмотрим типичный сценарий разработки фронтенд-приложений. Бизнес выдвигает требования, которые постепенно усложняют компоненты. Это приводит к проблемам сопровождения, особенно в больших проектах.

Пример: компонент для вывода суммы двух чисел

Первое требование: сумма двух чисел в кавычках

const SumComponent = (a, b) => `"${a + b}"`;

Второе требование: добавить вывод знака в конце

const SumComponent = (a, b, tag) => `"${a + b}"-${tag}`;

Третье требование: добавить умножение

const SumComponent = (a, b, tag, isMultiple) => 
  `${isMultiple ? a * b : ''}-"${a + b}"-${tag}`;

Проблема

Компонент превращается в «монстра» с кучей аргументов. Новые пропсы зависят от старых, что усложняет сопровождение. В больших проектах это становится критичным.

Выход из ситуации: простое решение (но с дублированием)

Один из подходов — создавать отдельные компоненты для каждого кейса. Это противоречит принципу DRY, но упрощает сопровождение.

// Простая сумма
const SumComponent = (a, b) => `"${a + b}"`;

// Сумма с тегом
const SumComponentAndTag = (a, b, tag) => `"${a + b}"-${tag}`;

// Сумма с тегом и умножением
const SumComponentAndTagAndMultiple = (a, b, tag, isMultiple) => 
  `${isMultiple ? a * b : ''}-"${a + b}"-${tag}`;

Проблема этого подхода

Дублирование кода. Если логика суммы изменится, придется вносить изменения во всех компонентах.

Модульный подход: композиция функций (лучшая практика функционального программирования)

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

Базовые функции

// Базовая логика суммы
const sum = (a, b) => a + b;

// Добавление кавычек
const withQuotes = (fn) => (a, b) => `"${fn(a, b)}"`;

// Добавление тега
const withTag = (fn) => (a, b, tag) => `${fn(a, b)}-${tag}`;

// Добавление умножения
const withMultiplication = (fn) => (a, b, isMultiple) => 
  isMultiple ? `${a * b}-${fn(a, b)}` : fn(a, b);

Комбинирование функций

// Простая сумма с кавычками
const SumComponent = withQuotes(sum);

// Сумма с кавычками и тегом
const SumComponentAndTag = (a, b, tag) => withTag(withQuotes(sum))(a, b, tag);

// Сумма с кавычками, тегом и умножением
const SumComponentAndTagAndMultiple = (a, b, tag, isMultiple) => 
  withMultiplication(withTag(withQuotes(sum)))(a, b, isMultiple) + `-${tag}`;

Преимущества

  1. Модульность: каждая функция отвечает за одну задачу.

  2. Переиспользование: функции можно комбинировать в любом порядке.

  3. Сопровождение: изменения в базовой логике автоматически применяются ко всем комбинациям.

Практика на Vue.js

Composition API

1. Создаем композаблы (composables)

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

useSum.js — логика суммы

import { computed } from 'vue';

export function useSum(a, b) {
  const sum = computed(() => a + b);
  return { sum };
}

useQuotes.js — добавление кавычек

import { computed } from 'vue';

export function useQuotes(value) {
  const quotedValue = computed(() => `"${value.value}"`);
  return { quotedValue };
}

useTag.js — добавление тега

import { computed } from 'vue';

export function useTag(value, tag) {
  const taggedValue = computed(() => `${value.value}-${tag}`);
  return { taggedValue };
}

useMultiplication.js — добавление умножения

import { computed } from 'vue';

export function useMultiplication(a, b, value, isMultiple) {
  const multipliedValue = computed(() => 
    isMultiple.value ? `${a.value * b.value}-${value.value}` : value.value
  );
  return { multipliedValue };
}

2. Создаем компоненты с использованием композаблов

Базовый компонент SumComponent



Компонент SumComponentAndTag



3. Преимущества подхода

  1. Модульность: Каждая логика изолирована в отдельном композабле.

  2. Переиспользование: Композаблы можно использовать в разных компонентах.

  3. Реактивность: Все значения автоматически обновляются при изменении пропсов.

  4. Сопровождение: Легко вносить изменения, так как логика разделена на мелкие части.

  5. Тестируемость: Каждый композабл можно тестировать независимо.

4. Пример использования компонентов



5. Итог

Использование useComposable во Vue 3 позволяет:

  • Создавать гибкие и модульные компоненты.

  • Избегать дублирования кода.

  • Упрощать сопровождение и тестирование.

  • Легко адаптироваться к изменениям требований.

Options API

Проблемы

  1. Слоты: сложно сопровождать в больших проектах.

  2. Миксины: могут вызывать конфликты и неявные зависимости.

  3. Обычные функции с замыканиями: отсутствие автоматической реактивности.

  1. Модульный подход позволяет соблюдать DRY и упрощает сопровождение.

  2. Композиция функций делает код гибким и переиспользуемым.

  3. Composition API во Vue — современный и удобный способ организации кода.

  4. Избегайте монолитных компонентов: разделяйте логику на мелкие, независимые части.

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

© Habrahabr.ru