Pull to refresh

Comments 62

Хмм… это только мне кажется, или у Vue и React такое развитие, что сначала в React сделают крутую фичу, а потом Vue сделают себе то же, но намного круче, как на примере с хуками/Composition API?

А чем эти фичи во Вью круче, чем в Реакте? Не спец по Вью, поэтому интересно.

Во Vue это сделано лучше чем в реакте, для этого достаточно пописать на реактовских хуках и всё станет ясно

А не поясните, чем именно? Я много писал на реактовских хуках, вообще не писал на вью, было бы интересно почитать.

Лень расписывать, недостатки очевидны, а вот если бы в реактовских функциональных компонентах рендер это была функция которая возвращается, тогда это уже было бы совсем другое дело. Тогда можно было бы пользоваться замыканием полноценно и без костылей в виде useCallback и т.п.
function MyComponent() {
    return () => (
        <div>Hello world</div>
    );
}

А как тогда со стейтом быть? Разве что-то типа как в вью делать через .value?

Использовать MobX вместо Redux и вместо локального useState и будет счастье

Один глобальный стейт и компоненты вообще без стейта? Это как так О_о?

Нет, локальный стейт тоже будет, просто не useState, а MobX'овский

Теперь понял. Спасибо.

Сейчас это можно реализовать используя такой фокус, но зато все недостатки кривого замыкания улетучиваются и замыкание работает как надо.
codesandbox.io/s/flamboyant-mclean-tzjfp
Проблема в том, что это изолированно тестировать почти невозможно. (И вообще с хуками геморрой). При этом обычный React+Redux раскладывался на ComponentTest,ActionTest,ReducerTest прямиком, тем и был силен.
Интересный подход. Но у меня появляется вопрос, как быть с пропсами? Там же при изменении пропса будет ресетится стейт всего компонента (ререндер внешнего компонента, который содержит стейт + колбеки).
Да, поэтому это костыль который не для всех случаев подходит, это больше для демонстрации того, что если бы разработчики реакта чуток больше пораскинули мозгами, то сделали бы сразу по человечески, чтобы замыкание было нормальным, но они рак не сделали почему-то, вот мне и реализацию Vue больше понравилась, а в реакте для меня это ещё 1 пункт, почему всё таки классовые компоненты удобнее и более гибкие, а реализация useEffect для классов простая, так что можно также делать кастомные хуки для классов.
Хмм… это только мне кажется, или у Vue и React такое развитие, что сначала в React сделают крутую фичу, а потом Vue сделают себе то же, но намного круче, как на примере с хуками/Composition API?

А в конце концов выясняется что это всё было сто лет назад в эмбере или нокауте =)
Тот же самый "Composition API" — это почти полная копипаста нокаута.


Заголовок спойлера

Vue 3:


import { ref, computed, onMounted } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const double = computed(() => count.value * 2)

    function increment() {
      count.value++
    }

    onMounted(() => console.log('component mounted!'))

    return {
      count,
      double,
      increment
    }
  }
}

Ko (если не путаю):


import {ko} from "knockout"

export class ExampleController {
    count = ko.observable(0);
    double = ko.computed(() => this.count() * 2, this);

    constructor() {
        console.log('component mounted!')
    }

    increment () {
        this.count(this.count() + 1);
    }
}
это безусловно так, китайская библиотека, копирующая фичи и упрощающая синтаксис. Vue на больших проектах очень трудно использовать уже сейчас (я работал недавно на проекте в 60+ человек), потому что кто-то пишет коммуникацию через VueX, а кто-то через ивенты, и никогда не знаешь, что еще придет в голову и логика расползается повсюду. Тестить это практически невозможно. Кроме того, простота входа привлекает не самых лучших разработчиков. С реактом еще въехать надо, что можно и что нельзя, а тут вперед и с шашкой.
UFO just landed and posted this here
отчего же ярлык?:) Я, кажется, конкретно объяснил почему вью сложнее использовать. Слишком много фич. Фичи не сочетаются друг с другом.

Сравните, например, как выкатываются и обкатываются фичи на реакте.

Китайский в данном случае подход — скопировать идею без понимания и чтоб как будто просто. Там не один разработчик, а целое коммьюнити такое.

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

нет, давайте установим правила, а не будем давать джуниорам гранаты
UFO just landed and posted this here
Vue не хватает целостности подхода. Документация написана так, что не уделяет внимание каким-то общим подходам и лучшим практикам. Вида если вы пишете приложение с более чем одной страничкой и сложными данными делайте лучше так. В итоге каждый пишет по своему и одна и та же задача решается по разному разными людьми.
Я фреймворк брал чтобы задача у всех похоже решалась, а не для того чтобы изучать как там у кого было сделано.
Я в последнее время думаю, что надо бы уже сделать во фронтенде несколько общих сводов правил по подходам и лучшим практикам независимо от фремворка (с какими-то поправками под возможности конкретных фреймворков). Где была бы описана файловая структура проекта, какие основные сущности есть в проекте и как они должны взаимодействовать с другими. Какие сущности могут или не могут использоваться в том или ином месте. Как передаются в другие сущности. Главное не намудрить, а то мало кто вдаваться в детали захочет.
Есть же всякие code style guide, почему бы и для архитектуры аналогично не сделать.
Не могу сказать насчет angular, но вот для react и vue (да и не только для их), такое вполне можно сделать.

Мне кажется, несмотря на свои недостатки, Redux именно из-за этого и взлетел. Там написаны правила, где и что должно быть, поэтому у разных разработчиков получается более-менее одинаковая структура проекта.
Ну вот чтобы начать использовать vuex мне пришлось идти и читать redux и гайды по нему. Так-как по умолчанию в документации vuex не написано про это ровным счетом ничего. Документация фактически сводится к простым примерам дерганья API и если ты эту концепцию видишь в первый раз это никак не помогает.
Это потому что вы слышали про redux). А я встречал, например, «зачем нам вообще эти мутации, ужасный бойлерплейт, давайте их все завернем в одну общую».
Я просто ленивый чтобы писать что-то свое когда это явно есть и на это есть стандарт. А так да бойлерплейта там километр, но зачем становится понятно только на более менее сложном проекте, где приходится делать переиспользуемые компоненты.
Ну что за чушь, серебряной пули не существует с точки зрения архитектуры, каждый проект уникальный и для каждого своя архитектура пригодна, а не одна общая для любого типа проекта. Главное придерживаться KISS и DRY, и тогда всё остальное будет вообще не проблема.
а что уникального во Vue?
Большинство проектов типовые. У типовых проектов плюс-минус, но можно сделать схожую структуру. Иначе бы откуда появились всякие конструкторы сайтов, CMS системы и прочее.
Конечно, инструменты (языки/парадигмы/фреймворки) даже для одних и тех же вещей разные и не способствуют этому. Если же они сделаны по схожим методологиям и имеют примерно одинаковые возможности, то какие-то общие принципы/правила выделить можно.

Например, что в react-е, что в vue есть понятие store. Да и много где можно аналогичную сущность успешно добавить. Мы же можем сказать как-то так: «В store можно писать только то, что связано с работой с данными (преобразование данных при записи в стор или извлечении из стора). Нельзя писать запросы к API или код для работы с DOM. Повторяющиеся или объемные алгоритмы выносить вне стора.»
Или такое правило: «Запросы к API не должны писаться в сторах компонентах, хуках, директивах, а должны писаться отдельно. В запросах к API не должно быть кода, работающего с DOM.

“Главное придерживаться KISS и DRY, и тогда всё остальное будет вообще не проблема.” — это слишком общие рекомендации. На них одних далеко не уедешь.
С KISS и DRY я был знаком с первых месяцев работы. Но это мне не давало понимания, как лучше делать систему в целом, не давало понимания, хороший код я написал или плохой. Не мог сказать, почему он плохой, хотя c с моей точки зрения тех времен, он этим принципам следовал.
Вот оно ключевое отличие специалистов разного уровня, одним подавай все однотипное и одинаковое, лишь бы головой лишний раз не подумать, а делать по туториалам, а другие каждый раз делают всё сами чтобы добиться все лучшей и лучшей архитектуры и все лучшего и лучшего кода. Таким образом одни развиваются и растут постоянно, вторые остаются на месте и их навык только снижается со временем т.к. однотипная работа, и сплошной копи-паст кода. И не надо отмазываться про то, что надо бизнесу, бизнес разный бывает, если проблема в работе, то ее просто меняют и начинают дышать и развиваться. А не жаждить чтобы все люди были одной тупой серой массой и писали всё одинаково. Каждый человек это личность и каждый вправе писать код так, как считает нужным и правильным без этого, он реально без самообмана дальше junior+ не уедет. И вот, когда этот человек пишет код чтобы он был простой на сколько это возможно, то как бы он не был написан, вы его поймете, потому что он простой. В этом ключевая особенность KISS.
Я тоже люблю своё пописать, но не делаю это за деньги заказчика, если это не оправдано.
другие каждый раз делают всё сами
Чувствуется «опытность». Случится что с человеком и всю его коллекцию велосипедов придется выкинуть и писать проект с нуля. Расширить команду тоже проблема, как следствие велосипедов. И это не говоря о том, что вместо того, чтобы как нормальный разработчик, потратить 5 часов на задачу, такой «опытный» разработчик потратит 50.

Я смотрю, вы любите похвастаться, что вы такой умный и правильный, а большинство глупые. Ума вы этим не продемонстрируете.
От Сократа, для таких самоуверенных: «Я знаю только то, что ничего не знаю, но другие не знают и этого».

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

И не важно оптимально это или нет, грамотная ли архитектура или нет и т.п. Просто хавай и всё тут. Терпи гавнокод, тебе же платят зарплату и больше ведь работы нет вообще, это твой единственный шанс.
Чувствуется «опытность». Случится что с человеком и всю его коллекцию велосипедов придется выкинуть и писать проект с нуля. Расширить команду тоже проблема, как следствие велосипедов. И это не говоря о том, что вместо того, чтобы как нормальный разработчик, потратить 5 часов на задачу, такой «опытный» разработчик потратит 50.

Тут речь именно об архитектуре, а не о том, что весь код написан на ваниле и своя имплементация абсолютно на все, в том числе на webpack.
Я смотрю, вы любите похвастаться, что вы такой умный и правильный, а большинство глупые. Ума вы этим не продемонстрируете.
От Сократа, для таких самоуверенных: «Я знаю только то, что ничего не знаю, но другие не знают и этого».

Это не я какой-то особенный и умный, умных и грамотных специалистов относительно много, мне просто не нравится что рынок перенасыщен серой массой которые в IT только ради денег. И приходится после них работать с кодом в котором без бутылки водки не разберешься.
но в команде будь добр, пиши как все
И не важно оптимально это или нет, грамотная ли архитектура или нет и т.п.
Ну так надо пробовать донести это до команды. От того, что одно и то же одним реализовано так, вторым по-другому, третьим еще как-нибудь, ни к чему хорошему не приведет.

мне просто не нравится что рынок перенасыщен серой массой которые в IT только ради денег. И приходится после них работать с кодом в котором без бутылки водки не разберешься.
К сожалению, с этим ничего не поделать. Кто как может, тот так и зарабатывает. Не было бы нищеты, жили бы в достатке, гораздо меньше лезли бы в IT.
Да и среди тех, кому это интересно, каждый будет в чём-то хорош, в чём-то плох. Далеко не каждый хорошо прокачается в проектировании.
Ну так надо пробовать донести это до команды. От того, что одно и то же одним реализовано так, вторым по-другому, третьим еще как-нибудь, ни к чему хорошему не приведет.

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

Согласен. Людей много, проектов много, просто бесит когда не дают с нуля переписать реальный ад) Приходится другую работу искать, чтобы нервы дольше оставались в порядке) Да вообще чтобы чувствовать себя хорошо)
Так он ещё не готов? То есть статья на будущее, и применять то, что в ней описывается, пока нельзя? Или можно, но всё ещё может поменяться? Может быть, в статье об этом где-то говорится, но хотелось бы понять прежде, чем потратить время на её изучение.
Не удержался и изучил, и ещё погуглил: использовать можно, но это, очевидно, не production ready и, да, может измениться, но чем ближе релиз, тем меньше вероятность изменений.

Vue 3 крут, если не знать про svelte. Virtual DOM сразу выглядит крайне архаичной идеей (svelte — компилятор и работает без virtual DOM)

Ага, а свой кастомный js прям отличная идея?
sveltejs ничего нового в js не добавляет

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

знак $ и: это вполне валидный синтаксис для JS

export тоже безусловно валидный синтаксис js, только в svelte он используется совсем не для экспорта. в итоге это свой над-js который просто использует зарезервированные в js синтаксические конструкции.

по поводу экспорта были жаркие споры в телеграмм канале. Если смотреть на то что sveltejs компонент является некий черный ящик, а слово export экспортирует интерфейс этого ящика, то особых противоречий в логике не возникает. Да это не совсем то же самое что и экспорт в обычном js модуле, но у нас тут и не js модуль, а sveltejs компонент который экспортирует свой интерфейс. Вроде бы даже логично.

По крайней мере мне с самого начала пришла именно такая ассоциация когда я познакомился с sveltejs и в целом никакого дискомфорта у меня это не вызвало.

Что касается $: то такой синтаксис computed свойств мне даже кажется очень удачным. Потому что краток и нагляден, и при необходимости туда можно запихать целые блоки кода.
это всего лишь пример. Здесь инициализируется реактивная переменная-счетчик со стартовым значением 0.

А почему примитивные обсерверы в современном JS принято называть "реактивными"?


P.S. Это немного оффтоп вопрос =)

Это один из паттернов раализации реактивности.

Я с Vue практически не знаком, но хочу вставить свои 5 копеек.
Как ни странно, новый вариант с функцией setup для меня выглядит более удобным)
Другие улучшения в новой версии тоже на мой взгляд есть, но…

export default {
  mixins: [CounterMixin]
}

Самая большая проблема такого подхода — мы ничего не знаем о том, что добавляется в наш компонент. Это затрудняет понимание и может приводить к коллизиям с существующими свойствами и методами.
Касательно «может приводить к коллизиям с существующими свойствами и методами». А зачем вообще нужно было делать именно смешиванием? Использовались бы вместо миксин объекты с изолированными свойствами и методами, и проблемы бы не было.

Сейчас, если мы хотим использовать какой-то кусок кода в нескольких компонентах, у нас есть два варианта: миксины (mixins) и слоты с ограниченной областью видимости (scoped slots). Оба варианта имеют свои недостатки.
А как же директивы? Не для все случаев, но все-таки это довольно удобный способ добавить к компонентам логику, да еще и без необходимости создавать новый компонент. Но возможно в Vue какие-то большие ограничения для директив, я не в курсе.

API пользовательских директив немного изменится во Vue 3, чтобы больше соответствовать жизненному циклу компонента.
Так ли было необходимо делать API жизненных циклов разными? Мне кажется для компонентов, миксин и директив можно было сделать одно API.
Если это вдруг так, то из этого следует еще интересный момент. Стоило ли разделять миксины и директивы? Возможно достаточно было сделать одну общую сущность и добавить опцию, отвечающую за то, где можно использовать эта сущность. Только в коде компонента, только в коде шаблона, в обоих местах.

Ну и последнее, думаю компоненты будут писаться
так
export default {
  setup(props) {
    // куча кода
    useCustomHook1(),
    useCustomHook2()
    return {
    }
  }
}

или так
export default {
  setup(props) {
    // куча кода
    return {
      ...useCustomHook1(),
      ...useCustomHook2()
    }
  }
}
вместо чего-то такого, когда в самом компоненте логика не пишется
// просто гипотетический код
export default {
  setup: {
      ...useCustomHook1(),
      ...useCustomHook2()
    }
  }
}


У вас во всех примерах хуки подобны миксинам, которые каждый вносят какую-то свою независимую лепту в компонент и с друг другом не связаны даже косвенно. Но по моему опыту работы с React hooks — там порой получаются увесистые деревья из хуков. В 2, 3 и даже 4 уровня вложенности. И вся малина именно в комбинировании их с друг другом. Думаю во Vue получится тоже самое.

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

которые каждый вносят какую-то свою независимую лепту в компонент и с друг другом не связаны даже косвенно
С чего вы взяли? Есть много способов связать 2 объекта. Например, теоретически можно сделать в хуках ссылку на компонент, в который они добавлены. Тогда через эту ссылку, можно было бы обращаться к другим хукам.

И вся малина именно в комбинировании их с друг другом.
Вот и я отчасти к этому веду в 3-ем примере) А логика в самом компоненте уменьшает возможности комбинирования в целом.

Но по моему опыту работы с React hooks — там порой получаются увесистые деревья из хуков. В 2, 3 и даже 4 уровня вложенности.
Здорово, вместо иерархии наследования сделали иерархию из хуков.
Я думаю именно это в будущем будет называться hooks hell)))
Может быть вместо добавления новых уровней вложенности, стоило подумать, как уменьшить вложенность за счет вынесения кода по другому и расположения некоторых хуков на одном уровне?

С чего вы взяли? Есть много способов связать 2 объекта. Например, теоретически можно сделать в хуках ссылку на компонент, в который они добавлены. Тогда через эту ссылку, можно было бы обращаться к другим хукам

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


Обычных языковых средств в языке для этого более чем достаточно. Не нужно никаких компонент никуда передавать, никаких реестров, никаких обвязок. Просто методы, просто переменные.


Здорово, вместо иерархии наследования сделали иерархию из хуков.
Здорово, вместо иерархии наследования сделали иерархию из хуков.
Я думаю именно это в будущем будет называться hooks hell)))

Это называется программирование, а не hooks hell :) Разделяй и влавствуй. Дроби сложное на мелкое и делай это мелкое хорошо. Чем-то напоминает философию linux.


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

Это как тыкать в себя вилкой. Можно то можно, но гарантировано будут только плохие последствия. Зачем делать плохо, когда уже сделано хорошо? :) В случае плоской модели с классами хорошо сделать было необычно сложно. В случае хуков многие вещи стало получаться писать и просто и понятно. Легко дробить, легко объединять, легко делать generic вещи. Если совсем коротко — The Single Responsibility Principle.

Пока писал предыдущее сообщение, местами подзабывал, что пишу о функциях. Я не придумываю, я делюсь своим 3-летним опытом работы в геймдеве. Где проблемы с повторным использованием кода успешно решены с помощью композиции на классах за много лет до появления react и vue.
Я не говорю, что функциями делать плохо, а классами хорошо.
Схожими подходами можно и там и там пользоваться.

Касательно всего того, что вы написали во второй части сообщения. Разделять и комбинировать надо тоже с умом. То, что кто-то получил новый инструмент с возможностью писать более качественно код, не значит, что это сразу сделает из него эксперта.
Мой опыт использования композиции говорит, что 3-4 уровня вложенности пользовательских хуков — это ошибка проектирования. Но, т.к. у меня мало опыта использования композиции именно в виде хуков, я пока не стану это утверждать. Как обычно, годика через 2 будет видно. Когда хуки будут немного проверены временем и станет понятно, как стоит их использовать, а как нет.
Мой опыт использования композиции говорит, что 3-4 уровня вложенности пользовательских хуков — это ошибка проектирования

А стек-трейсы длиннее 3 строк тоже ошибка проектирования? :) По сути это тоже самое.

Корректнее будет сравнивать не сами стек-трейсы, а то, что они возвращают.
Где проще разобраться, во вложенных вызовах или в последовательных?

Я бы с таким сравнивал:
refactoring.guru/ru/smells/message-chains
refactoring.guru/ru/replace-nested-conditional-with-guard-clauses

такой же код понятней
func1();
func2(){
  func3();
  func4();
}
func5() {
  func6();
  func7();
}

чем такой?
func1(){
  func2();
  func3() {
    func4();
    func5() {
      func6();
      func7();
  }
}


Где проще разобраться, во вложенных вызовах или в последовательных?

  1. В последовательных вызовах разобраться проще тогда, когда эти вызовы завязаны друг на друга. Делают одну вещь.
  2. Во вложенных вызовах проще разобраться тогда, когда этим самым разделяются не связанные с друг другом явным образом вещи. Т.е. углубившись на уровень глубже мы попадаем в п1.

Всё тот же Single Responsibility Principle. Это относится не к хукам, это относится к программированию в целом. Т.е. эти вещи НЕ противопоставляются друг другу. Есть однозначная область применения каждому из них.


Отсюда вывод, ваше сопоставление этих двух примеров не имеет решительно никакого смысла без явного описания за что отвечает каждая функция и как они друг на друга завязаны. Нужно знать какие задачи они решают и за что ответственны. В каких-то случаях код-ревью не пройдёт 1-ый пример, в каких-то 2-й пример.

Мне тоже нравится первый принцип SOLID, но наша дискуссия не про него. Ни ваш, ни мой вариант ему не противоречат.

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

Я изначально не рассматривал какие-то конкретные ситуации. Но вот поразмышлял еще немного и понял, что скорее всего не так представлял вложенность хуков.
Изначально видел только вариант, что если хуки делаются вложенными, то между всеми ними явная зависимость. Например, изменил хук 3-го уровня, придется менять не только хук 2-го уровня, но и первого. Теперь предположу, что если хуки вложенные, это не значит, что между хуками 1-го и 3-го уровня есть такая зависимость. И думаю между хуками соседних уровней можно убрать зависимость.
func1(func2(func3())) — например, можно так сделать вложенность. Никакой конкретики, а следовательно и зависимости между ними нет. Любая из них может быть заменена какой-нибудь другой.
Если не спешить и думать головой наперед прежде чем делать, то все будет хорошо. Хуки нормальная тема в исполнении Vue, а вот в реакте не самая удачная из-за того, что вся функция в которой всё описано перевызывается отсюда костыли в виде useCallback и т.п., а могли бы сделать проще и элегантнее если просто рендер это была возвращаемая функция из функции в которой все описано(жизненный цикл, состояние и т.п.)
если не спешить и думать головой наперед, можно и на c++ хорошо написать:) вопрос в том, во что превращается проект, когда на нем спешат и не успевают думать.
В таком случае он всегда и неизбежно превращается в каку, но если делать периодические рефакторинги, то это можно более менее сгладить)
Вы совершенно правы, и глядя на большие vue проекты уже сейчас, у меня сложилось ясное понимание, что там хелл из всего, что уже намешано. Т.е. логика стихийно попадает в любое из мест: вычисляемые свойства, вотчеры, ивенты, экшены, мутации — и тут мы добавляем еще несколько опций. А поскольку фронтенд — это еще и традиционное место для джуниоров, то их регулировать особенно трудно.
Vue движется в сторону улучшения опыта разработчика

Ну всё, очередной инструмент в экосистеме JS заговорил про "девелопер икспиренс", можно закапывать.

Sign up to leave a comment.