Очень крутая идея и реализация. Сначала подумал "еще один фреймворк", но когда увидел схожесть с trpc, когда увидел простые примеры и настолько читаемые, то был в восторге)
Но эта статья - документация. Если хочется продвигать библиотеку, кажется нужно показать меньше примеров, но которые бьют в самое сердце)
А что если, клиент бы отправлял какой-то ключ, который был хешом из его состояния оплат? Оплаты изменились, например на другом устройстве сделал оплату, пока планшет отключен. Включил планшет - вторая бронь пришла. А если сделать хеш из состояния, то конфликтов не будет
А вот представьте, если реально ИИ заменит программиста полностью. Это же какое счастье будет, ведь если можно заменить настолько сложную профессию, значит ИИ достаточно умен чтобы ввести бизнес. Он достаточно умен чтобы программировать роботов, а потом этими роботами управлять. Тогда достаточно недели, и через неделю будет автоматизирован весь мир.
А знаете почему все эти проблемы с архитектурой возникают? Может просто потому, что каждый проект уникален, и для каждого проекта нужна своя уникальная структура, со своими уникальными ограничениями? И тогда вместо FSD, люди бы учили, а как правильно разделить код, зачем вообще его разделять, почему бы не писать все в одном файле и тд
Высокоуровневые языки давали абстракцию, скорость но что-то забирали. Например контроль над памятью. И программы стали тяжелее, но мы смирились.
А теперь ИИ сделала все еще абстрактнее, но забрало детерменированность (один и тот же промт, и совершенно разные программы), контроль над исполнением (уже абсолютно непонятно что программа делает, если сценарий выходит за рамки промта), полное понимание (раньше можно было прочесть код и понять что как работает, а сейчас нужно спрашивать ИИ, и то он может что-то утоить).
Ну окей, вложенность сильная, рекурсивные запросы. А что, индексы не помогли? Почему запросы такими долгими были? Или там было прям очень много запросов одновременно? Имхо база справится спокойно, если корректно индексы настроить.
Здесь в UserInfo передаётся весь объект user, хотя используются только два поля из всего объекта: name и age. Это делает компонент зависимым от структуры объекта и усложняет изменения.
А вот и неправда) все зависит от того, какой уровень абстракции у вашего компонента. Если это UI компонент, то да, ваш пример имеет место быть. А если это компонент с бизнес логикой, то правильнее передать весь user, а не отдельные поля. Потому что может произойти так, что в компоненте нужным станет еще и поле 'gender'. И если вы все передавали через пропсы, а компонент использовали в 100-200 местах, то получается что все 100-200 мест нужно изменить, а если передавали бы user, то при потребности в новом поле изменения бы коснулись только одного места.
Все ваши примеры контекстозависимы, их нельзя рассматривать как совет. Потому что где-то это будет полезно, а где-то навредит.
Если бы было все так просто как вы показали, то мы бы давно написали линтер, который работает по вашим советам, и делает код лучше
Автор говорит о проблемах тестирования, что оно делается сложным из-за того что нужно много зависимостей внедрить.
Хотя в своем примере тестирования тоже мокает зависимости, просто в новом подходе это делается чуть проще.
Ну а что мешает один раз написать моки для этих зависимостей и переиспользовать?
Новая архитектура нарушает SOLID, хотя автор этого не видит. Автор не понимает, что принцип единственной ответственности нужно рассматривать на определённом уровне абстракции. Например:
/router.tsx отвечает и за создание роутера, и за рендеринг
Нет, router.tsx отвечает за роутинг (единственная ответственность). А роутинг в себя включает и определение роутов, и их отображение отталкиваясь от window.location, и их композицию и тд.
И не стоит забывать, что хорошая архитектура нужна часто для удобства пользователей.
А роутинг в одном файле - очень удобно, нежели искать по проекту кто как и где рендерится
Я не понял, почему когда абстрагируемся, связи остаются такими же, что и на низких уровнях (HTTP запрос между микросервисами).
Пример: На уровне класса, связи - прямые вызовы. Дальше по абстракции может быть например несколько процессов, которые вызывают друг друга через IPC. Дальше несколько сервисов через общую шину. Дальше несколько систем через gRPC.
И вот вызовы на разных уровнях могут отличаться не только количеством, но и сутью. Тут может показаться что я говорю про транспорт, но я имел ввиду, что когда мы абстрагируемся, то должны не только абстрагировать компоненты, но и связи между ними.
Окей проблема понятно. А вот почему через typescript решили, непонятно. Посмотрите в сторону zod (валидатор). Схема описывается через JS, но можно вывести typescript типы. + вам для low code платформы нужна будет валидация данных, например чтобы число было положительным, или чтобы строка была не длиннее чем X символов. А как вы это сделаете через typescript? Решение я описал в первом комментарии, и как будто больше подходит. А еще вопрос поддержки. Вот вы разобрались, понимаете как парсить ast дерево, но задача у вас простая, и придется поддерживать этот кому-то этот костыль....
А мне так и непонятно, какую проблему вы решили? Вы хотели использовать и typescript и proptypes, но описывать одну схему? Если да, то не легче было просто общую схему описать, которая бы генерила proptypes, и выводила typescript схему? То есть использовать code first, а не schema first
Да, простите, пропустил. Но мой пример лучше, так как пример в статье сломается, если дочерний компонент вызывет этот коллбэк в useLayoutEffect сразу при маунте.
Зачем он нужен? Это тоже самое что и useCallback, но без зависимостей. И его можно безопасно использовать в useEffect, а еще безопасно передавать как props
Очень крутая идея и реализация. Сначала подумал "еще один фреймворк", но когда увидел схожесть с trpc, когда увидел простые примеры и настолько читаемые, то был в восторге)
Но эта статья - документация. Если хочется продвигать библиотеку, кажется нужно показать меньше примеров, но которые бьют в самое сердце)
Ага, я понял вас
Спасибо что разобрали)
Сервер проверяет хэш:
Совпал - значит запись новая
Не совпал - значит клиент не знает актуального состояния.
Если сервер атомарно пишет в базу, то получается что и дублей не будет. Потому что при дубле сервер сверит хэш, и увидит что хеш устарел.
Так что, мой предложенный вариант полностью покрывает идемпотентное общение между клиентом и сервером.
А что если, клиент бы отправлял какой-то ключ, который был хешом из его состояния оплат?
Оплаты изменились, например на другом устройстве сделал оплату, пока планшет отключен. Включил планшет - вторая бронь пришла.
А если сделать хеш из состояния, то конфликтов не будет
А вот представьте, если реально ИИ заменит программиста полностью. Это же какое счастье будет, ведь если можно заменить настолько сложную профессию, значит ИИ достаточно умен чтобы ввести бизнес. Он достаточно умен чтобы программировать роботов, а потом этими роботами управлять.
Тогда достаточно недели, и через неделю будет автоматизирован весь мир.
Да, можно выделить общее. Но FSD и прочие предлагают выделять не общее, а сразу диктуют структуру.
Можно выделять общие рецепты, и мы о них уже знаем (Solid, Grasp)
Можно выделять паттерны для компонентов, и мы о них тоже знаем (render props)
А знаете почему все эти проблемы с архитектурой возникают? Может просто потому, что каждый проект уникален, и для каждого проекта нужна своя уникальная структура, со своими уникальными ограничениями?
И тогда вместо FSD, люди бы учили, а как правильно разделить код, зачем вообще его разделять, почему бы не писать все в одном файле и тд
Высокоуровневые языки давали абстракцию, скорость но что-то забирали. Например контроль над памятью. И программы стали тяжелее, но мы смирились.
А теперь ИИ сделала все еще абстрактнее, но забрало детерменированность (один и тот же промт, и совершенно разные программы), контроль над исполнением (уже абсолютно непонятно что программа делает, если сценарий выходит за рамки промта), полное понимание (раньше можно было прочесть код и понять что как работает, а сейчас нужно спрашивать ИИ, и то он может что-то утоить).
Нужна ли нам такая абстракция?
Это открыли еще в прошлом веке. Сейчас есть решения поинтереснее, например tRPC, и скорость разработки взлетает x2-x3
Ага, а можно было бы еще вместо картинок отображать видео с одним кадром, и загнать под DRM. И не придумывать такую сложную архитектуру
Ну окей, вложенность сильная, рекурсивные запросы. А что, индексы не помогли? Почему запросы такими долгими были? Или там было прям очень много запросов одновременно? Имхо база справится спокойно, если корректно индексы настроить.
Читал статью и были точно такие же мысли. В статье классический алгоритм несчастья:
Обесценить то, что имеем, и переоценить то, что не имеем.
А вот и неправда) все зависит от того, какой уровень абстракции у вашего компонента. Если это UI компонент, то да, ваш пример имеет место быть. А если это компонент с бизнес логикой, то правильнее передать весь user, а не отдельные поля. Потому что может произойти так, что в компоненте нужным станет еще и поле 'gender'. И если вы все передавали через пропсы, а компонент использовали в 100-200 местах, то получается что все 100-200 мест нужно изменить, а если передавали бы user, то при потребности в новом поле изменения бы коснулись только одного места.
Все ваши примеры контекстозависимы, их нельзя рассматривать как совет. Потому что где-то это будет полезно, а где-то навредит.
Если бы было все так просто как вы показали, то мы бы давно написали линтер, который работает по вашим советам, и делает код лучше
Автор говорит о проблемах тестирования, что оно делается сложным из-за того что нужно много зависимостей внедрить.
Хотя в своем примере тестирования тоже мокает зависимости, просто в новом подходе это делается чуть проще.
Ну а что мешает один раз написать моки для этих зависимостей и переиспользовать?
Новая архитектура нарушает SOLID, хотя автор этого не видит. Автор не понимает, что принцип единственной ответственности нужно рассматривать на определённом уровне абстракции. Например:
Нет, router.tsx отвечает за роутинг (единственная ответственность). А роутинг в себя включает и определение роутов, и их отображение отталкиваясь от window.location, и их композицию и тд.
И не стоит забывать, что хорошая архитектура нужна часто для удобства пользователей.
А роутинг в одном файле - очень удобно, нежели искать по проекту кто как и где рендерится
А тот факт, что бот Яндекса будет иметь доступ к каналу, и сможет выкладывать что угодно, и когда угодно?
Я не понял, почему когда абстрагируемся, связи остаются такими же, что и на низких уровнях (HTTP запрос между микросервисами).
Пример: На уровне класса, связи - прямые вызовы. Дальше по абстракции может быть например несколько процессов, которые вызывают друг друга через IPC. Дальше несколько сервисов через общую шину. Дальше несколько систем через gRPC.
И вот вызовы на разных уровнях могут отличаться не только количеством, но и сутью. Тут может показаться что я говорю про транспорт, но я имел ввиду, что когда мы абстрагируемся, то должны не только абстрагировать компоненты, но и связи между ними.
Окей проблема понятно. А вот почему через typescript решили, непонятно.
Посмотрите в сторону zod (валидатор). Схема описывается через JS, но можно вывести typescript типы.
+ вам для low code платформы нужна будет валидация данных, например чтобы число было положительным, или чтобы строка была не длиннее чем X символов.
А как вы это сделаете через typescript?
Решение я описал в первом комментарии, и как будто больше подходит. А еще вопрос поддержки. Вот вы разобрались, понимаете как парсить ast дерево, но задача у вас простая, и придется поддерживать этот кому-то этот костыль....
А мне так и непонятно, какую проблему вы решили? Вы хотели использовать и typescript и proptypes, но описывать одну схему?
Если да, то не легче было просто общую схему описать, которая бы генерила proptypes, и выводила typescript схему?
То есть использовать code first, а не schema first
Да, простите, пропустил. Но мой пример лучше, так как пример в статье сломается, если дочерний компонент вызывет этот коллбэк в useLayoutEffect сразу при маунте.
А я бы еще добавил важный хук:
Зачем он нужен? Это тоже самое что и useCallback, но без зависимостей. И его можно безопасно использовать в
useEffect, а еще безопасно передавать какprops