Pull to refresh
-16
0.1
Send message

Успокойтесь уже, идите поработайте.

Это всё что вы можете сказать? То что ваш вариант в 20 раз медленнее работает чем традиционный и хуже читаемый/хуже воспринимаемый (и это только на супер простецком примере) это проблемы инопланетян и тех кто придет работать сюда после вас? А вы здесь и сейчас write-only once код написали и умыли руки. "Интересный" подход.

  • Развивайтесь. Не ограничивайте себя чем-то одним, одним framework-ом, одним подходом, одним языком программирования. Смотрите по сторонам, заимствуйте идеи и концепции.

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

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

Ага, действительно, ваше "решение" конечно капец какое "чисто" и "прекрасное". Всё что нужно было с делать с изначальный вариантом - выкинуть lodash и forEach заменить на конструкцию for(const item of items) { ... } и в принципе всё. Прекрасное, максимально очевидное, наглядное, понятное и чистое решение. А не write only и не дай боже к нему прикоснуться в дальнейшем хоть раз.

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

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

  • Будьте терпимей. И не будьте такими категоричными, как в ваших комментариях

У всего есть пределы, одно дело вместо for(const item of items) { ... } использовать forEach да ещё и из lodash или переменную назвать, ну или даже вместо await apiCall() использоваться apiCall().then(...) это ещё не так режет глаза и восприятие, хотя уже воспринимается как дичь, а другое дело вот это вот:

import groupBy from "lodash/groupBy";
import mapValues from "lodash/mapValues";
import innerJoin from "./innerJoin";
import take from "./pipe";

const _ = (childIds, parents) =>
  take(parents)
    .pipe($ => $.flatMap(e => e.Children.map(a => ({ Parent: e, Child: a }))))
    .pipe($ => innerJoin($, x => x.Child.Id, childIds, x => x, x => x))
    .pipe($ => groupBy($, x => x.Parent.Group?.Name || "NoGroup"))
    .pipe($ => mapValues($, o => o.map(x => ({ ...x.Child, ParentName: x.Parent.Name }))))
    .result();

export default _;

и вот это

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");
};

export default _;


Тут уж извините, но такое вообще не в какое ворота не лезет. Это настолько же противоестественно и возмутительно, как лечение насморка кровопусканием. А вы это преподносите под соусом мол вот смотрите после моих наводящих вопросов разработчик пришел к такому "прекрасному" и "чистому коду", теперь он познал дзен и "идеальный" write only once код, всем бы такой код в проекты(чтобы проекты были мертворожденными).

Вот же:

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;
};

Давайте, вот конкретно тут плохо? Именно реально плохо, а то ещё скажите for внутри for это плохо, но это же смешно, т.к. в конкретном случае это самое оптимальное решение.


И на самое интересно я оставил замеры. все поленились их сделать, а я нет)
Вот они - https://stackblitz.com/edit/vitejs-vite-hosyl5?file=main.js&terminal=dev

Традиционный подход и в этом аспекте превзошёл, хотя для меня и не является приоритетные если речь идёт о front-end, а если о backend, то другой разговор
Традиционный подход и в этом аспекте превзошёл, хотя для меня и не является приоритетные если речь идёт о front-end, а если о backend, то другой разговор

"Грязный", "Противный", "Фу фу фу" традиционный подход в среднем в 10-20 раз быстрее "чистого" кода. Такие дела.

Финальный код - там даже нечему ломаться, это тот случай, когда ты написал код и сразу знаешь, что он работает именно так, как тебе нужно

Допустим. а потом проходит месяца эдак 3-4 и нужно расширить этот функционал или изменить его, кстати вполне себе типичная ситуация.

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

И вот в противовес этому традиционный императивный вариант, ну 3-5 минут ты потратил чтобы понять как оно работает, и ещё 3-5 минут чтобы изменить поведение на нужное(т.к. внося изменения в традиционном стиле, всё более чем быстро, наглядно и очевидно) и вот через 10 минут задача готова, нервы на месте, завтрак на месте, глаза видят ясно и четко.

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

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

Императивные решения в случае 3-4 if else уже невозможно удержать в голове. Особенно если код поддерживает не один человек, а несколько, в разные моменты времени.

Серьезно? Вот прям так? Интересно получается, а как же вообще мы пишем проекты то огромные если 3-4 if'a и уже всё, в голове не удержать? Чудеса, да и только. Когда код легко читается слева на право, сверху вниз, то будь в нем хоть 20 if'ов в каждой точке ты понимаешь что происходит и при каких условия мы попадаем в ту или иную точку, ведь это прямо написано черным по белому, если это, то делаем вот так, а если вот это, то делает эдак.

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

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

Мужики, ну хорош! Проблема же банальная, и код должен быть таким же банальным:

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;
};

Всё правильно, вот единственно верный по сути адекватный вариант. Другие это уже из разряда жёстких извращений, глядя на которые кровь из глаз хлещет.

Так то изначально решение намного лучше чем финальное. Т.к. оно намного понятнее и гораздо легче подается будущим изменениями логики / фиксу багов. Сам по себе код изначального решения так себе, во первых lodash тут не нужен от слова совсем, во вторых forEach надо заменить на конструкцию for(const item of items) { ... }.

Как итог, то что вы получили - полная write only шляпа и проекты с таким кодом и подходом к разработке живут очень очень очень плохо, и разработчики на таких проектах тратят в РАЗЫ(без шуток) больше времени на элементарные задачи. Учите основу основ - KISS (Keep It Simple Stupid), YAGNI (You aren't gonna need it) и код должен быть императивным, максимально простым и читаться слева направо, сверху вниз, и для того чтобы понять как он работает не должно быть распутывания.

Так они об этом и не думают, да и не только об этом. Просто с пеной у рта берут next.js, redux и прочую дичь ни думая ни о чем. Единственно о чем они думают, что наверное они умные, они ведь видят упоминание в интернете о next, fsd и т.п., а раз упоминания есть, значит это "обязательно хорошо и нам надо".

Пример выше очень не плох для очень маленького проекта

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

Если проект все же крупнее вашего примера, то неизбежно будет расти беспорядок в этих папках.

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

Беспорядок будет заключаться в высокой связности.

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

Так как в данной структуре нет никаких ограничений на импорт модулей

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

 И нет возможности внести правки не поломав функционала на других страницах.

Серьезно? У вас весь мир делится только на черное и белое? Открою тайну, опять же в реальной жизни примерно 99% таких правок люди осознают что они делаю и ничего не ломают. Но бывают крайне редкие кейсы когда что-то может пойти не так, но увы ваш FSD вообще от этого никак не застрахует. Там все те же особенности и проблемы, просто файлов и папок в несколько раз больше.

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

Поздравляю, легаси длиною в 10 лет, даже 5 лет - это всё, мертвый плохо поддерживаемый проект. При чем тут структура файлов и папок??? Если в нем устарело всё, как технологии, так и подходы к разработке и написанию кода в целом. Оглянитесь назад на 5 лет. Вы писали и думали по другому. Опять же "аргумент" из разряда ну надо же хоть что-то придумать эдакое. Ну и всё так же, если вы наговнокодили дерьмовую архитектуру и т.п., то это сугубо ваши проблемы. А то, что вы говнокодите это я уже понял факт, т.к. вы используете Redux до сир пор, это уже даже не смешно.

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

И что? Она интуитивно понятна вообще всем. Ее описание будет выглядеть так - вот смотрите, вы ящик с надписью книги? Правильно, там лежат книги. Вы видите ящик с надписью вилки? Правильно, там лежат вилки. Вы же нигде не описываете и не читаете то, как дышать, вы просто дышите и всё. Так же и тут. Она такая же очевидная, как использование MobX в паре с реактом, а не убожество из прошлой цивилизации в виде redux.

а в случае частных моментов - есть чат, где можно спросить совета у грамотных людей

Которые называют беспорядком растущее количество страниц, общих компонентов, глобальных состояний? Или используют redux в связке с react'ом? Ахаха, ну уж нет, спасибо, пожалуй откажусь)

Основной принцип FSD не в "излишнем дроблении", а больше в том, что бы выстроить иерархию слоев и запретить хаотичных импорт, который повышает связность проекта.

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

Второй плюс, который дает FSD - легкий перенос функционала из одного проекта в другой. Надо лишь перенести несколько слайсов из 4-5 слоев. В случае с вашей архитектурой, надо будет бегать по файликам и копировать код буквально кусками - это знаем, проходили.

Да что вы говорите? Серьезно? Если речь про ваш говнокод, то может быть. Самое геморойное что я когда-либо переносил из проекта в проект заняло не более 1 часа. А в 99% случаев это копипаст папки с нужным компонентом и всё. Или копи паст конкретно функции/класса и всё. Более того, потребность такого рода переносов возникает примерно крайне редко. Но вы конечно же сделали из этого целую трагедию, конечно скопировать 1 папку в которой есть всё это намного тяжелее чем несколько слайсов из 4-5 слоев(говоря про FSD, это кстати очередное подтверждение бредовости данной "архитектуры"). Копировать 4-5 слоев чтобы перенести компонент, это уму не постижимо. Ну реально, это же смешно и абсурдно.

@zyetsТак вот вопрос, чем FSD реально лучше чем мой пример? Из этого комментария

Во первых я не соглашусь с Вашим мнением о бесполезности FSD. Вы же, очевидно, её даже не пробовали, не знаете плюсов и не знаете минусов

На самом деле тут всё просто, есть традиционная классическая структура фалов/папок/вложенностей аля здравый смысл и удобство:

Так вот, я попытался себе ответить на вопрос, чем FSD будет лучше/удобнее/быстрее в разработки чем классика, Ни в совокупности это ничем не лучше классики. Плюс у меня был проект на котором уже FSD, и приходилось много лишних телодвижений делать чтобы найти нужные места в коде, плюс тратить лишнее время на подумать а в какую же папку положить то или иное, в общем всё что на выходе мы получаем это трата extra time впустую. Плюс у меня есть друзья разработчики которые так же пробовали FSD и реальных плюсов не обнаружили, только сталкивались с проблемами и придумывали костыли для того чтобы вписываться хоть как-то в FSD. В итоге FSD это просто избыточное дробление, которое реально избыточно в 99% случаев, а это накладывает постоянные неудобства и увеличение времени разработки.
Но может быть вы мне ответе чем реально лучше FSD классической схемы что я привет выше на скрине, и если если реально по совокупности всех факторов она окажется удобнее, быстрее в разработке и т.п., то я с радостью буду ее применять. Так вот вопрос, чем FSD реально лучше чем мой пример?

А во вторых. Я говорил именно о том, что FSD своего рода "закрыла гештальт"

Да вот нет, ибо он уже много лет как закрыт классическим способом, пример выше.

Были десятки (если не сотни) стейт-менеджеров, сборщиков пакетов, эффект-менеджеров, API-клиентов, css-процессоров, видов роутинга и инициализации проекта. 

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

А вот архитектурных методологий такого уровня, с такой детализации - нет.

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

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

Ну опять преувеличение невероятного масштаба. Дополнительное избыточное дробление это конечно офигеть шаг) Вот просто вопрос, например какой реальный плюс разделять model и api?
Ну вот например слитно:

export class ItemsPageState {
    items: IItem[] = []

    constructor() {
        makeReactive(this);
    }

    fetchItems = async () => {
        const response = await new ApiReq(`GET /api/v1/items`).send();
        this.items = response.items;
    }
}

И даже если тут будет ещё 5-10 функций дергающих АПИ, это ни как не ухудшает читаемость/восприятие и т.п. ибо оно к этому относится и лежит рядом.

На мой взгляд сравнивать методологию с библиотеками крайне странно...

На самом деле сама суть была во фразе из статьи:

FSD — это, пожалуй, то, чего так не хватало в Frontend-мире.

Т.е. это преподносится как прям глоток свежего воздуха и Game Changer в мире Frontend'a. Но фактически, положительный импакт от FSD на столько минимален(в реальности скорее перевес в пользу отрицательного, по сравнению с традиционными подходами здравого смысла) что это про очередная аббревиатура которая появилась, но толку от нее нет.

А если вернуться к аналогии с библиотеками, то на примере того же React'a когда появился MobX, это был реальный очень сильный положительный импакт и Game Changer.
Т.е. если сравнить влияние на Frjntend, то эта библиотека улучшает жизнь в реальности на 98 из 100, а FSD если даже улучшает(в реальности скорее либо на том уровне всё остается в лучшем случае, а чаще хуже), то от силы это будет на 5 из 100. Поэтому вот эта фраза в статье о FSD это смешно)

FSD — это, пожалуй, то, чего так не хватало в Frontend-мире.

Пожалуй здравый смысл - это, то, чего так не хватает в Frontend-мире. Люди до сих пор используют Redux / RTK, или того хуже, всякие RxJS, Effector'ы, Zustand'ы и т.п. А некоторые вообще идут дальше и в принципе стейт менеджер не используют, использую чисто встроенные в реакт средства.

А FSD это очередная мимолётная чупуха, которая фактически приносит на 90% головную боль и геморрой и лишь на 10% пользу.

Зато с rxjs можно локаничненько сделать retry для http запросов. Типо как

Или так) Без rx'ов))

fetchData = async () => {
  this.fetching = true;
  try {
    this.items = await new ApiReq(`GET /api/v1/docs`).withRetries(3, 5000).send();
  } catch (e) {
    this.error = e.message;
  } finally {
    this.fetching = false;
  }
}

А больше плюсов для рядовых задач я пока не нашел))

Так и эта "фича" элементарно реализуется без rx'ов =) 10 минут и готово)

соединение с сокетом и получить два разных потока данных

Что конкретно вы тут подразумеваете под потоком данных? Каждое соединение/клиента который приконнектился и шлет данные или все подряд данные которые шлют все клиенты или что?

Вообще звучит как обычный EventEmitter))
const unsibscribeFn1 = wsEvents.on('data', dataOne);
const unsibscribeFn2 = wsEvents.on('data', dataTwo);

Ну и когда надо отписываемся
unsibscribeFn1();
unsibscribeFn2();

Но на беке активно его использовал именно для обработки потоков данных

Просто абстрактно и опять 0 конкретики, а именно что тут традиционный подход не канает или код будет нечитемым.

Вообще выучил его с 0 когда мне нужно было приоритезированную очередь сделать

И? При чем тут rxjs если это достаточно тривиальная штука. Опять же 0 конкретики, какая-то абстрактная очередь.

Еще rxjs всегда под капотом у nestjs

И что теперь? А если бы там был под капотом jQuery первой версии? Или Redux?

когда ты с потоками данных работаешь, а не с императивными функциями, просто с приставкой await

Опять максимально абстрактные слова без конкретики и кода.

P.S. Очередное подтверждение, что RxJs не может противопоставить традиционному подходу ничего, от слова совсем. Разве только write-only код, от которого кровь из глаз льется

Тут скорее кто к чему привык и какая задача стоит, мне, например, гораздо удобнее и понятнее RxJs, нежели async/await и промисы

Да, с async/await тоже некоторые подобные штуки можно делать, но выглядеть это будет "не очень", плюс достаточно сложно для прочтения это будет.

А можно пожалуйста пример из реальной жизни, т.е. то, что в реальности приходится решать разработчикам фронта, хотя бы в среднем на каждом пятом проекте где именно код с RxJs будет понятней/лучше, а традиционная разработка с тем же async/await просто не решит задачу или код будет непонятным по сравнению с RxJs? Прям ссылку на codesandbox/stackblitz пришлите, а я реализую то же поведение, но традиционными методами, просто сравним код хотя бы даже ради интереса. А то всё что я всегда слышу это о каких-то магических кейсах и сценариях где Rx это пушка, но реального сценария я так никогда и не видел где он выигрывает традиционный подход. Надеюсь вы такой сценарий предоставите, главный критерий это реальный, а не вымышленный или 1 на 10000 кейс. Буду очень благодарен.

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

Если бы пример был более нативный, то тогда было бы интереснее сравнить.

Вот пожалуйста, самый нативный пример https://stackblitz.com/edit/vitejs-vite-wgaaja?file=src%2Fmain.ts&terminal=dev

Если честно, то это вообще полная фигня. Просто посмотрите на MobX, он на 3 головы лучше и удобнее. Там все подписки/отписки автоматические, как и должно быть. Из "оверхеда" по коду только makeAutoObservable(this); в конструкторе классов с состоянием и observer() для заворачивая компонентов. Всё.
Просто посмотрите https://stackblitz.com/edit/vitejs-vite-y2qj7g?file=src%2FApp.tsx&terminal=dev

Бла бла бла.

// Писать вот это (Zustand )
set((state) => ({ bears: state.bears + 1 }))
set((state) => ({ bears: state.bears - 1 }))

// Вместо (MobX)
state.bears++
state.bears--



// Писать вот это (Zustand )
function Controls() {
  const increasePopulation = useStore((state) => state.increasePopulation)
  const decreasePopulation = useStore((state) => state.decreasePopulation)
  
  return (
    <div>
      <button onClick={increasePopulation}>one up</button>
      <button onClick={decreasePopulation}>one dowm</button>
    <div>
  )
}

// Вместо (MobX)
const Controls = observer(() {
  return (
    <div>
      <button onClick={state.increasePopulation}>one up</button>
      <button onClick={state.decreasePopulation}>one dowm</button>
    <div>
  )
})

Этого достаточно. Всё.

Вам нужно смотреть в сторону голого HTML и PHP, ибо реакт и т.п. это всё для вас не очевидно и страшная магия, как и mobx, а так глядишь нормально будет.

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

Object.defineProperty(target, key, {
      get() {
        // ...
      },
      set(v) {
        // ..
      },
    });

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

Поэтому все лидеры рынка и пишут до сих пор на Redux и на MobX не перейдут никогда. 

Да вы что? Вот прям так? Все лидеры рынка переходят с Redux на MobX и уже давно..

Сейчас все из них присматриваются и переходят на Zustand.

Спойлер, на самом деле все переходят на MobX.

По поводу всякой "магии" и черных волшебных ящиков у разработчиков выработалось защитное правило: все явное лучше не явного так проще найти и понять что и почему - в "магии" замучаешься искать

Да, но не в этом случае, ибо тут на get идёт подписка, а на set идут реакции. Всё. Достаточно это понимать, и сразу никакой "магии" и нет.

Information

Rating
3,153-rd
Registered
Activity