Коллеги, всем привет!

Давайте честно: сколько из вас за последний год успели если не впрогреть, то хотя бы посмотреть в сторону нового JS-фреймворка? Qwik, Solid, Svelte — список можно продолжать. Я сам постоянно ловлю себя на этом: вижу хайп, читаю доки, даже пет-проект пытаюсь сделать... А потом прихожу на работу и видим тот же легаси-код, который всё сложнее поддерживать.

И тут я задал себе простой вопрос: а что, если дело не в фреймворках? Что, если мы просто лечим симптомы, а не болезнь?

Болезнь под названием "хочу новый фреймворк"

Знакомо:

  • Начинаешь новый проект — руки чешутся взять что-то модное

  • Через полгода код превращается в спагетти, даже с самым крутым фреймворком

  • Рефакторинг становится болью

  • Тесты писать сложно

  • Команда боится вносить изменения

Я прошел через это. Потратил кучу времени на изучение новых инструментов, но проблемы оставались. Пока не понял одну простую вещь...

Лекарство: три принципа, которые перевернули мой подход

Принцип 1: Делай одну вещь, но делай её хорошо

Помните тот ужасный компонент, который:

  • Ходит за данными

  • Форматирует их

  • Рендерит

  • И ещё аналитику отправляет?

Я называл это "компонент-бог". И таких у меня было полно. Пока не попробовал разбивать всё на мелкие сущности с одной ответственностью.

Вот как это выглядит сейчас:

userApiService.js → только запросы к API
userDataMapper.js → преобразование данных
AnalyticsTracker.js → только аналитика
UserProfileView.js → только отображение

Да, файлов стало больше. Зато теперь:

  • Если падает API — я знаю, где искать

  • Если дизайнер поменял вёрстку — правлю один файл

  • Если нужно добавить аналитику — не трогаю компонент

Принцип 2: Не прячь зависимости — покажи их

Раньше я постоянно импортил axios прямо в компонентах. Казалось, что так быстрее. Пока не попробовал написать тесты для такого кода...

Теперь я явно передаю все зависимости:

// Было
const UserList = () => {
    useEffect(() => {
        axios.get('/api/users').then(...)
    }, [])
}

// Стало
const UserList = ({ userService }) => {
    useEffect(() => {
        userService.getUsers().then(...)
    }, [userService])
}

Разница кажется небольшой, но на практике:

  • Тесты пишутся в 3 раза быстрее

  • Легко подменить реализацию (например, для моков)

  • Код становится предсказуемым

Принцип 3: Завись от интерфейсов, а не от реализаций

Это звучало для меня как какая-то магия, пока я не попробовал на практике.

Вместо того чтобы компонент знал про конкретный API:

// Плохо: компонент знает слишком много
const UserList = () => {
    const [users, setUsers] = useState([])
    
    useEffect(() => {
        fetch('/api/v2/users') // А если бэкенд поменяет API?
            .then(response => response.json())
            .then(setUsers)
    }, [])
}

Я создаю прослойку-абстракцию:

// userRepository.js
class UserRepository {
    async getUsers() {
        // Здесь может быть REST, GraphQL, моки - не важно
        const response = await fetch('/api/users')
        return response.json()
    }
}

// В компоненте
const UserList = ({ userRepository }) => {
    const [users, setUsers] = useState([])
    
    useEffect(() => {
        userRepository.getUsers().then(setUsers)
    }, [userRepository])
}

Теперь если бэкенд поменяет API, мне нужно поправить всего один файл, а не 15 компонентов.

Что изменилось в моей работе

После того как я начал применять эти принципы:

  1. Скорость разработки сначала немного упала (привыкал к новому подходу), но потом выросла в разы

  2. Качество кода стало заметно лучше — коллеги теперь понимают мой код с полуслова

  3. Рефакторинг перестал быть болью

  4. Тесты пишутся легко и быстро

Да, я всё ещё смотрю в сторону новых фреймворков. Но теперь я понимаю: не важно, React у меня или SolidJS — эти принципы работают везде.

Выводы, которые я сделал

  1. Фреймворки приходят и уходят, а архитектурные принципы остаются

  2. Инвестиция в архитектуру окупается быстрее, чем кажется

  3. Простота важнее модных фич

Я не призываю вас забросить изучение нового. Просто предлагаю сначала построить прочный фундамент.

А какие архитектурные принципы помогают вам в работе? Давайте обсудим в комментариях — возможно, я упустил что-то важное!

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


  1. vkomp
    04.10.2025 05:09

    В react повсеместно юзаю useSWR. Типа useState+useEffect+кэш. Хорошая штука, рекомендую в концепции "один источник истины": компонент получает состояние, что-то поменялось - вызываешь mutate() и спишь спокойно.
    Выношу url в отдельный файл редко - в случаях когда юзается в нескольких местах. Обычно один url для одного компонента - и легко во Ctrl+Shift+F находится. Да и вообще есть какой-то критерий управляемости, по которому не разбиваю компонент.


  1. sunUnderShadow
    04.10.2025 05:09

    Когда только-только узнаешь про SOLID.

    Правда, не очень понятно при чем тут вообще фреймворки и почему мы опять застряли в реакте, хотя речь идёт про "чистый код", ну да ладно


    1. lrmpsm53
      04.10.2025 05:09

      Чистый код и Реакт в принципе не особо совместимы


  1. dominus_augustus
    04.10.2025 05:09

    Поздравляю, вы изобрели Solid, но реакт это слой рендеринга, так что тут это как костыль


  1. souls_arch
    04.10.2025 05:09

    Не совсем понял автора. Я конечно всех фреймворков js не знаю и ручаться за них не буду, но писал сам не раз и работал с Angular и ReactJs (речь о самом архитектурном каркасе принятом, хоть на функциях js, хоть на ооп typescript, а не о хуках, рендере и прочем). Разве там не используется тот же принцип многослойности, разделения ответственности, слабой связанности и прочие плюшки SOLID и чистого кода? Все отлично подерживается и расширяется. По моему в статье изобретен личный велосипед. )


  1. nin-jin
    04.10.2025 05:09

    Давайте честно: сколько из вас за последний год успели если не впрогреть

    Давайте откровенно: вы спалились в первой же строчке и получаете заслуженный минус в карму за нейрослоп.


  1. arfedulov
    04.10.2025 05:09

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


  1. pepelnyy
    04.10.2025 05:09

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

    Все описанные в статье моменты, начиная с разделения комбайна на элементарные операции (ешь слона по кусочкам) до вынесения повторяющихся действий в отдельное место (про абстракцию/прослойку) - это же не про эту вашу джаву или, там, Бейсик! Это, насколько, я могу судить, универсальные правила, которые экстраполируются практически на любой вид созидательной деятельности. Странно, что к ним пришлось сколько-то времени идти.

    (Ессессн, могу быть не прав)

    И, да, при чём тут желание применять новые фреймворки (или любые другие инструменты)? Это наоборот, я полагаю, верно - развиваться и познавать, применяя на практике. Код превращается в спагетти не из-за смены инструмента, а из-за каши в мыслях.

    (Опять же, могу быть не прав)