Проблемы больших проектов: сопровождение компонентов и фанатичность принципу 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}`;
Преимущества
Модульность: каждая функция отвечает за одну задачу.
Переиспользование: функции можно комбинировать в любом порядке.
Сопровождение: изменения в базовой логике автоматически применяются ко всем комбинациям.
Практика на 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
<script setup> import { useSum, useQuotes } from './composables'; const props = defineProps({ a: Number, b: Number, }); const { sum } = useSum(props.a, props.b); const { quotedValue } = useQuotes(sum); </script> <template> <span>{{ quotedValue }}</span> </template>
Компонент SumComponentAndTag
<script setup> import { useSum, useQuotes, useTag } from './composables'; const props = defineProps({ a: Number, b: Number, tag: String, }); const { sum } = useSum(props.a, props.b); const { quotedValue } = useQuotes(sum); const { taggedValue } = useTag(quotedValue, props.tag); </script> <template> <span>{{ taggedValue }}</span> </template>
3. Преимущества подхода
Модульность: Каждая логика изолирована в отдельном композабле.
Переиспользование: Композаблы можно использовать в разных компонентах.
Реактивность: Все значения автоматически обновляются при изменении пропсов.
Сопровождение: Легко вносить изменения, так как логика разделена на мелкие части.
Тестируемость: Каждый композабл можно тестировать независимо.
4. Пример использования компонентов
<template> <div> <!-- Простая сумма --> <SumComponent :a="2" :b="3" /> <!-- Сумма с тегом --> <SumComponentAndTag :a="2" :b="3" tag="result" /> </div> </template> <script setup> import SumComponent from './components/SumComponent.vue'; import SumComponentAndTag from './components/SumComponentAndTag.vue'; </script>
5. Итог
Использование useComposable во Vue 3 позволяет:
Создавать гибкие и модульные компоненты.
Избегать дублирования кода.
Упрощать сопровождение и тестирование.
Легко адаптироваться к изменениям требований.
Options API
Проблемы
Слоты: сложно сопровождать в больших проектах.
Миксины: могут вызывать конфликты и неявные зависимости.
Обычные функции с замыканиями: отсутствие автоматической реактивности.
Модульный подход позволяет соблюдать DRY и упрощает сопровождение.
Композиция функций делает код гибким и переиспользуемым.
Composition API во Vue — современный и удобный способ организации кода.
Избегайте монолитных компонентов: разделяйте логику на мелкие, независимые части.
Этот подход особенно полезен в больших проектах, где важно поддерживать баланс между гибкостью и читаемостью кода.
