Pull to refresh
-16
0.1
Send message

Вы изначально написали

Уже на двух проектах из за mobx были проблемы.

В итоге, из-за mobx у вас не было проблем, у вас были проблемы из-за кривых рук разработчиков.
А значит, нет разницы Mobx, Zustand, Redux и т.п. они в любом случае будут писать гуано.
Просто используя MobX по сути большую времени ты просто пишешь нативный JS код и всё. А если просто тупо писать нативный код, читать свойства объекта/модифицировать свойства объекта и т.п. это проблема, поздравляю, вы джун) Не унывайте, рано или поздно наберетесь опыта и начнете делать все по красоте.

И используя таким образом mobx можно выстрелить себе в ногу.

И используя таким образом "подставь любое"(т.к. контекст говорит об использовании джунами) можно выстрелить себе в ногу.

Был у меня проект, где mobx отлично себя показывал. Там вся логика была в классах, а реакт только для отображения. Его конечно тоже видоизменили потому, что люди, которые заложили ООП паттерны тоже ушли и следить за чистотой было некому.

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

Проблема была в том что порог входа был выше чем на типичных реактовских проектах.

Для кого? Для джунов? А с каких пор мы на них ориентируемся? В >90% они обычно отсутствуют на проектах ибо сильно тормозят его и срут в него, либо только там где максимально жадный работодатель который не хочет платить ЗП.

Ни за что не поверю что это завышает порог входа:
https://stackblitz.com/edit/vitejs-vite-dspjoj?file=src%2FApp.tsx&terminal=dev

1 раз объяснил что делает makeAutoObservable и observer (1-2 минуты времени) и любой джун способный вообще писать код на реакте, с точно таким же успехом справится если будет MobX.

Это сложно разве?
Это сложно разве?
А вот это?
А вот это?
Может быть вот это сложно?)
Может быть вот это сложно?)

Так в чем проблемы MobX'a то? Пока всё что я вижу из ваших комментариев это чисто проблемы низкой компетенции людей, а mobx/redux/и т.д. и т.п. тут не виноваты. Я так понимаю вы работаете там где вся команда состоит из таких, может конечно кто-то пытается прикидываться не джуном, но действия говорят за себя, тем более если у вас текучка, то понятное дело никто из серьезных специалистов работать на ваших условиях не будет

Уже на двух проектах из за mobx были проблемы.

Какие именно проблемы? Проблемы именно из-за MobX или из-за чрезмерно умных разработчиков?)

Основная проблема в том что у mobx богатый функционал

Серьезно?) makeAutoObservabble, reaction, autorun, when и observer из mobx-react-lite, а всё остальное не нужно использовать.

В двух командах остановились на том что для работы с данными с сервера используем react-query

Зачем? Не догадались свою обертку для запросов к АПИ использовать внутри класса с состоянием компонента/или глобального состояния? Это же элементарно Ватсон.

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

Эм, простите, а вы нарочно взяли малое кол-во элементов childs?

У меня там 1000 parent и каждого 1000 child и того 1млн элементов, реальной жизнью не пахнет так то, в 99.99% случаев в такого рода задачах элементов значительно меньше. Этого разве мало?

Просто если их увеличивать, то производительность резко падает вниз.

Правда?) А могло быть как-то иначе?)

И возвращаясь к читаемости кода, вы 3 раза так или иначе правили функцию

Я ее не трогал, я просто взял как есть. У меня даже не было цели выжимать производительность, а сравнить тупо в лоб. Поэтому я и не пытался ничего оптимизировать. Вот:

Ссылка на коммент

Из-за которой, у вашего решения производительность ЗНАЧИТЕЛЬНО хуже на большом кол-ве данных чем у "freakSolution"

Вот запустил по вашей ссылке, производительность всё равно выше. Но вообще для чистоты тестов нужно сделать так

https://stackblitz.com/edit/vitejs-vite-smsi3c?file=main.js&terminal=dev

А теперь да, делаем простейшую оптимизацию и самое очевидное как вы говорили, заменить

if (!childIds.includes(child.Id)) continue;

И получаем:

https://stackblitz.com/edit/vitejs-vite-c7yd3i?file=main.js&terminal=dev

Можно пойти ещё дальше, просто мутировать child'a, т.к. в реальном кейсе добавление к нему ParentName дает ровно 0 негативных эффектов, а вот к производительности дает много

Получаем ещё ускорение ~30%

https://stackblitz.com/edit/vitejs-vite-puaqos?file=main.js&terminal=dev

Итого приложив 0% усилий и 30 секунд времени ускорили getChildrenByGroup в ~4 раза. С нулевым ущербом читаемости.

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

Но забавней оказался факт, что функция которая заявляется как самая медленная, работает быстрее, чем та что заявляется оптимизированной. И везде вариант функции flatMap, filter и groupBy оказывался быстрее.

Видите ли, в отличии от вас, я не заявляю, а показываю и подтверждаю приводя ссылку с кодом, по которой может перейти любой и воспроизвести, а вы сейчас просто сделали утверждение у которого 0% подтверждения. С таким же успехом вы можете сказать что - "Земля плоская, я проверил. "
Кидайте ссылку на repl где ваши результаты подтверждаются performance.now()

Вот ещё раз дублирую ссылку с замером.

https://stackblitz.com/edit/vitejs-vite-hosyl5?file=main.js&terminal=dev

А язык Go как раз и создавали, чтобы уйти от проблем ООП языков

Интересно девки пляшут

wiki

Ни слова про "проблемы" ООП или уход от ООП.

wiki #2

Да, сразу видно они решили вырубить всё на корню что связано с ООП.

Даже в языке СИ(~1972г.) в с помощью struct можно делать подобием класса/объекта

struct student
{
    int name;
    int address;

    void (*speak)();
};

void speak_func() {/*...*/}

int main()
{
  //code ..
  struct student student;
  student.speak = speak_func;

  student.speak();
}

И как раз таки можно создать функцию обертку которая будет сразу возвращать экземпляр student и связанные с ним методы. Проверено ещё лет 7 назад когда писал на СИ.

Классы это всегда было и будет удобным способам организации код, только там где это действительно удобно. Ты обращаешься к экземпляру класса/объекта и тебе IDE сразу подсказывает все его свойства и методы, ну разве это не прекрасно?

Я стараюсь руководствоваться логикой

Вы апеллируете к "авторитетам". А это значит полное и тотальной отсутствие реальной логики, здравого смысла и критического мышления. Отсутствие этих качеств - крайне плохо влияет на способность быть талантливым разработчиком.

Он имеет в виду, что использовать redux(и всё что вокруг и около него) вместо mobx в наше время, это нелепо. Да и в 2019 году уже было нелепо)

По Supercat Store без проблем отвечу тоже.

Он сейчас схож более менее с MobX, поэтому к нему претензий принципиальных нет и к тем, кто его возьмет для управления состоянием.
Если сравнить с MobX, я все равно бы взял MobX.
Если сравнить с Effector, Redux, Zustand, Reatom и т.п. мусором, то Supercat Store на порядки лучше их, и если выбирать между ними, я бы однозначно взял Supercat.

Далее отвечу @nin-jinв этом же треде, т.к. из-за кармы могу только раз в сутки писать

Забавно, что по поводу $mol_wire у человека нет никаких вопросов. В нём что, недостатков нету?!

API MobX'a всё же лучше и плевать мне если он весит больше.
Если сравнить с MobX, я бы взял MobX.
Если сравнить с Supercat Store, я бы взял Supercat Store.
Если сравнить с Effector, Redux, Zustand, Reatom и т.п. мусором, то $mol_wire однозначно.

Но если говорить с целом просто о $mol где всё пишется вот так:

Нет, спасибо) Да, символов меньше чем в JSX, да, пускай работает быстрее(только на уровне синтетики, в реальных приложениях нет разницы), но тут уже надо знать грань и баланс) И заплатить за это ценой такого синтаксиса так себе идея)

Я вижу все комментарии и не отвечаю на те, которые уже зашли в тупик, потому что кто-то ходит по кругу и не слышит ответов которые ему уже давали :)

Come on, что за дешёвые приемы семиклассницы? Это же уровень детского сада и капризных девчонок - соскакивать с темы когда задали не удобный вопрос. В нормальном обществе принято на вопросы отвечать и на критику тоже, да. а не махать рукой и говорить "Ой всё".
Я же задал вам конкретные вопросы, на которые не получил ответа, любой может это проверить, ссылки же есть, а вы начинаете выдумывать сказки, что якобы вас не слышат и т.п. Ну т.е. типичная дешевая манипуляция для соскакивания с темы.

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

Итого, первый момент, ждёмс:

Раз
https://habr.com/ru/companies/ruvds/articles/737114/#comment_25586780
Два
https://habr.com/ru/companies/ruvds/articles/737114/#comment_25786550
Три (Ответить нормально на этот комментарий)
https://habr.com/ru/companies/ruvds/articles/737114/#comment_25582614


Второй момент
:
Я у вас увидел в пример на сайте вот это:
https://stackblitz.com/github/artalar/reatom/tree/v3/examples/react-notifications?file=src%2Fmodel.ts
Вот с таким пафосным описанием

И вот решил повторить, но уже используя MobX
Вот что получилось
https://stackblitz.com/edit/github-ohhv1d?file=src%2Fmodel.ts

И о чудо, как же так вышло, что за таким пафосным описание скрывается элементарные вещи?
Более того, как же так вышло, что по сути с помощью тупо нативного кода всё это сделано легко и непринужденно и любой человек посмотрев на него сразу будет понимать что тут происходит, т.к. для этого не нужно вникать и углубляться с то, как работает MobX, чего нельзя сказать про reatom.

Что вы скажете по этому поводу?

Третий момент

Наткнулся на ваше видео с очень пафосным названием

Как решить главную проблему управления состояния раз и навсегда с Reatom.

Собственно вот такое название ^
И вот что получается, 20 минут вы рассказывали о "проблеме" глобального состояниях, в случаях когда нужно локальное состояние. Очередной раз вы сами придумали какую-то "проблему", которая вообще проблемой не является и не являлось никогда и грозно ее "решаете". Более того, код которым вы "решаете" данную "проблему" это конечно что-то с чем-то.

Вот вы там так же приложили код:
https://stackblitz.com/edit/reatom-computed-factory-pattern-example?file=src%2Fpages%2FSearch.tsx,src%2Fpages%2FSearch%2Fmodel.ts

А вот я его повторил, но используя MobX:
https://stackblitz.com/edit/reatom-computed-factory-pattern-example-kt19hn?file=src%2Fpages%2FSearch%2Fmodel.ts

Как говориться результат на лицо.

Что вы скажете по этому поводу?

В сухом остатки решение вашей "проблемы" такое:

Если нужно глобальное состояние (не обнуляется при смене страниц и т.п.)
Если нужно глобальное состояние (не обнуляется при смене страниц и т.п.)
И вот если нужно локальное состояние компонента
И вот если нужно локальное состояние компонента

И всё карл, эта вся суть "проблемы".


Или может я "опять хожу по кругу и не слышу ответов(которых нет)"?

Да конечно. Еще вот очень рекомендую для личного ознакомления: https://habr.com/ru/companies/ruvds/articles/737114/

Уважаемый @artalar будьте так любезны ответить на комментарии:
Раз
https://habr.com/ru/companies/ruvds/articles/737114/#comment_25586780
Два
https://habr.com/ru/companies/ruvds/articles/737114/#comment_25786550
Три (Ответить нормально на этот комментарий)
https://habr.com/ru/companies/ruvds/articles/737114/#comment_25582614

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

В результате в лидеры выбились Redux, MobX и Effector.

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

Серьезно? Покажите пожалуйста конкретный код этих коротких приложений, прям очень интересно, это как же надо написать код с MobX'ом чтобы предпочесть ему Effector... Сдается мне, что тот кто писал это приложение с MobX'ом вообще либо первый раз с ним знаком, либо не понимает в чем его суть и как нужно писать код используя MobX.

В голове не укладывается, как вот это


Променять на не это.

Вот например тут есть и фетчинг данных и подписки на события т.п.

https://stackblitz.com/edit/vitejs-vite-ffchmx?file=src%2Fpages%2Fmain%2Findex.tsx&terminal=dev

Бонусом там же ещё сделал чтобы все асинхронные функции в классе имели реактивные свойства fetching, error, callsCount (лежит в helpers/makeReactive)

  • Но а что если вы захотите использовать эту функцию загрузки постов еще где-то, но без того, чтобы что-то обновлялось?

Вообще не понял в чём цимус, но окэй как говориться, так то элементарно

Вариант номер раз (отдельный метод внутри класса)
Вариант номер раз (отдельный метод внутри класса)
Вариант номер два (просто функция)
Вариант номер два (просто функция)

.Какой больше по душе, такой можно выбрать.

  • А что если вы захотите при logout очищать массив постов?

Вам нужно будет из некого class Auth из метода logout дергать PostsState.clear()? А потом не только посты, а еще десятки других классов и методов?

Всё в итоге это становится более запутанным..

Да нет, можно сделать ровно так же как вы сделали в своем примере ниже в этом же комментарии

Раз
Раз
Два
Два
 ()Ну и чтобы их дергать
()Ну и чтобы их дергать

И вуаля, всё так же как у вас, одном месте, рядом с данными, просто в традиционном нативном для js стиле.


Вот сам код https://stackblitz.com/edit/vitejs-vite-ffchmx?file=src%2Fpages%2Fmain%2Findex.tsx&terminal=dev

Бонусом там же ещё сделал чтобы все асинхронные функции в классе имели реактивные свойства fetching, error, callsCount (лежит в helpers/makeReactive)

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

Создаете отдельно Action. Например получение списка постов. Это просто запрос на сервер, валидация данных их возвращение.

Создаете парочку Model. postsIsPending и postsList, например.

Создаете Effect обертку над Action, подписываетесь на неё моделями и всё.

Дальше просто рендерите эти данные.

Вот вариант с постами
https://stackblitz.com/edit/vitejs-vite-3ajbxs?file=src%2Fpages%2Fmain%2Findex.tsx,src%2FglobalState%2Fposts%2Findex.ts&terminal=dev
Там всё реально ультра просто и очевидно:

Нажать сюда
Нажать сюда

Минимум лишних файлов, папок и кода, и главное всё предельно наглядно и очевидно.

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

А второй как? Снизу вверх и обрабатывает данные не по очереди, а в хаотичном порядке?))

в то время как первый имеет условия, которые влияют на поток исполнения

хоспадя, ещё как назовете простую вещь чтобы она казалась сложнее?)

и мутирует данные.

Иииии?

let ageType = 'young';
if (age > 60) ageType = 'old';

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

Как насчет того, мутация данных удобнее, намного быстрее и намного меньше оперативной памяти съедает? Или это всё не важно, важна типичная мнимая отмазка, что якобы ты что-то мутировал и всё, всё сломалось. Ну пожалуй если ты вообще не в адеквате и не ведаешь что делаешь, то да, но этот "довод" в 99.9999% не состоятельный.

А откуда у вас статистика?

Да так, за 12 лет перевидал огромное кол-во проектов и разработчиков и знаю какой код для большинства людей быстрее и лучше воспринимается(кроме индивидуумов конечно). И не забывайте, вариант 1 и вариант 2, это варианты очень простой логики, когда речь заходит о реальной логике которая посложнее чем 2 + 2, то функциональщина становится невосприимчивым write only once кодом для для авторов этого кода, и понять что в уже в таком коде происходит куда сложнее чем в этом банальном примере. Понятное дело что с точки зрения кода такого рода вещи воспринимаются легко всеми

const filteredResult = items.map(item => item.age).filter(age => age >= 18);

т.к. это тоже элементарный пример, но он всё равно значительно медленнее императивного аналога и жрёт памяти сильно больше, и когда мы оперируем исключительно очень малым объемом данных, то разницы нет, я предпочти например для такого кейса вариант с map => filter, т.к. читаемость не страдает, а экономия на ресурсах тут мизенрая, но если данных не мало и весь код соткан из такой функиональной фигни(я имею ввиду не этот детский сад аля map => filter, а конкретные такие цепочки), то суммарно приложение начинает тормозить и есть оперативку как не в себя.

Я искренне считаю, что это очень крутая архитектура. Очень простая.

Использовать Effector и Redux в 2024 году. С такими инструментами она априори не может быть крутой и простой. Открою вам страшную тайну, в связке с React'ом можно и нужно использовать только MobX, тут без альтернативно, разве что только самописный аналог.

Вот это я понимаю реально супер просто и круто:
https://stackblitz.com/edit/vitejs-vite-y2qj7g?file=src%2FApp.tsx&terminal=dev

SOLID не работает на практике и в реальной жизни во фронтенд разработке, вообще никак, никогда, без вариантов. Да и не только на фронте, в принципе он очень сильно мешает комфортной разработке, и плюсы которые он дает никаким образом не перекрывают минусы. Слишком уж серьезные минусы.

На hello world'ах которые вы показываете и сами пробуете для тестов, это ещё более менее терпимо, но когда речь заходит о реальном проекте где множество страниц, логики, компонентов, взаимосвязей и т.п. то это всё, там начинается полнейшая дичь, видел я несколько таких попыток применения SOLID'a на реальных проектах. это нечто) Сложность на ровном месте просто повышается в разы, по сравнению с так сказать традиционными подходами.

И самые жирные минусы как раз кроются в том, какой "классный и удобный код" приходится писать если придерживаться всех этих принципов, бонусом как раз таки усложнение серьезное и увеличения кода как таковое и отсюда вытекает ещё один жирнющий минус, это время затраченное на написание кода.

Возможно это странно, но по моему опыту работы я сталкивался с большинством описанных трудностей на проектах без fsd

Потому что не умеете? Неужели интуитивно понятная структура вызывает трудности? Ну это же откровенное вранье, ни за что не поверю что вы не понимаете для что такое папка layouts, pages, hooks, components, globalState и т.п. Всё что касается страницы лежит в папке со страницей, все что касается конкретного компонента, лежит в папке с компонентом, глобальный стейт соответственно в папке с глобальными состояния и т.д. и т.п. всё максимально интуитивно, логично и просто. Захотел перенести компонент из проекта в проект? Просто одну папку с компонентом скопировал и вуаля.

Поэтому я склонен считать, что эти беды не от fsd, а от непонимания его.

Да нет, как раз таки все эти беды от fsd.

Если у вас проект прям сильно крутится вокруг одной большой сущности, Которая связана сразу со всем в системе (а я встречал такие проекты) ну тогда может быть fsd тут не уместен. Это ж не панацея всё таки.

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

Я общался в чате на эту тему и мне сторожилы fsd предупредили, что не надо дробить, ради дробления. Всё должно быть компактно по возможности.

Только это не работает на практике, вы и все кто использует fsd именно дробите ради дробления, потому что если так не делать, то получится традиционная структура, но вы же хотите выделится, поэтому приходится извращаться.

  • зачастую сложно понять, в какой слой поместить тот или иной файл.

Забавно, но у меня эта проблема возникала всегда на предыдущих проектах, но не в fsd. В fsd я как-то разобрался за пару дней и всё наоборот стало предельно ясно. В моём случае fsd наоборот помог решить данную дилемму.

Серьезно?
Хм, куда бы положить страницу, в папку pages или в папку assets...
Хм, куда бы положить компонент который используется более 1 раза в разных местах, в папку components или в папку hooks...
Хм, куда бы положить глобальное состояние. в папку globalState или в папку compontns...
Хм, куда бы положить helper функцию в папку helpers или в папку pages...

Ну вы понимаете да насколько это нелепо? Говорить про то, что вы не понимаете что где лежит и должно лежать, а вот FSD вам открыл глаза, хахаха ну это просто реально очень смешно, на серьезных щах такое задвигать это конечно прикол.

Цель была улучшить читаемость

Увы, вы её не достигли. Если быть максимально честным, то как минимум >90% людей поймут значительно быстрее что делает вот этот код:

const getChildrenByGroup = (childIds, parents) => {
  const result = {};
  for (const parent of parents) {
    for (const child of parent.Children) {
      if (!childIds.includes(child.Id)) continue;
      
      const groupName = parent.GroupName || 'NoGroup';
      if (!result[groupName]) result[groupName] = [];
      result[groupName].push({ ...child, ParentName: parent.Name });
    }
  }
  return result;
};

Чем вот этот:

const _ = (childIds, parents) => {
  const set = new Set(childIds);
  const data = parents
    .flatMap(e => e.Children.map(x => ({ ...x, ParentName: e.Name, Group: e.Group?.Name })))
    .filter(e => set.has(e.Id));
  return Object.groupBy(data, e => e.Group || "NoGroup");
};

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

Получается на выходе:
1) Вы получили решение которое в 20 раз медленнее работает и в N раз потребляет больше памяти(тут я поленился замерить).
2) Оно не фига не лучше читается/поддерживается и т.п. Но т.к. это совсем элементарный пример, то будем считать, что в лучшем случае(для единичных уникумов) примерно так же.
3) Вы потратили на это много лишнего времени.
А время самый ценный ресурс, который в нашей жизни, его нельзя вернуть, откатить, купить за деньги. Вместо этой пустой траты времени, просто сказали бы выкини lodash и всё. Освободили бы много времени и себе и этому разработчику. Это время можно потратить как на себя/на семью, так и на реализацию новых фич, фикса багов, а не на вот это вот всё.

Извините, но метрика цикломатической сложности у последнего варианта лучше.

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

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

Вы получается пожертвовали скоростью в 20 раз, но в замен получили код, чтобы понять который надо потратить больше времени, чем на традиционный вариант, который к тому же в 20 раз быстрее работает. очень странный обмен и жертвы. Плюс вы потратили на всё это время как своё, так и других людей, причем главное что напрасно потратили. И теперь гордитесь этим и гордо написали про это статью)

мы не ставили цели поднять перформанс

Ещё бы вы такие цели ставили, я был бы очень удивлен. У вас так сказать немного другой девиз)) Утилизируй время в пустую, властвуй и унижай разработчиков заставляя их писать противоестественный и ультра медленный код. Лучше бы вы ругали их за теранарки в теранарках, но мне почему-то кажется что для вас теранарки в теранарках это норма)

1
23 ...

Information

Rating
3,149-th
Registered
Activity