Andrei Chmelev @andry36
Senior Full Stack Engineer / Tech Lead
Information
- Rating
- Does not participate
- Registered
- Activity
Specialization
Fullstack Developer, Software Architect
Lead
JavaScript
Node.js
React
TypeScript
Vue.js
Web development
NestJS
React Native
Java
Docker
Спасибо за комментарий!
Понимаю, что такая постановка задачи может показаться искусственной, но для собеседований она довольно типична: нам нужно в ограниченное время проверить, как кандидат мыслит в контексте React, понимает ли он тонкости хуков и асинхронных запросов.
На интервью часто задают подобные микро-задачи, чтобы быстро увидеть, как разработчик работает со стейтом, эффектами и обработкой ошибок на практике - без вдавания в детали полной архитектуры приложения.
Т.е. что это не замена реального проектного кода, а тестовое окружение, где проявляются навыки кандидата.
Пример из статьи не призывает каждый микро-компонент делать собственный запрос. Это лишь иллюстрация ключевых вопросов, которые помогают оценить понимание React-хуков и потенциальных ловушек асинхронности. Для боевого применения, конечно, нужно распределять логику так, чтобы не превратить приложение в зоопарк из сотен запросов. Но на собеседовании хочется увидеть, как кандидат работает именно с базовой механикой React - тогда уже понятно, сможет ли он грамотно её применить внутри более продуманной архитектуры.
Спасибо за комент!
"Весь мир использует..." громкое утверджение, сразу хочется попросить пруфы :)
Не все компании применяют именно tanstack-query. К тому же в задаче проверяются общие принципы работы с асинхронностью в React: если человек хорошо понимает эту логику, он без труда освоит и любую абстракцию вроде React Query или SWR.
В статье я специально упомянул, что у нас якобы нет возможности вызвать
abort()
, чтобы проверить реакцию кандидата на ситуацию неуправляемого запроса. А Strict Mode помогает увидеть возможные побочные эффекты и дважды вызываемые функции - это тоже важно учитывать для корректной реализации асинхронной логики.В последнем абзаце речь идёт о том, что полноценная реализация Suspense для произвольных запросов (без специальных фреймворков, типа Relay или Next.js) всё ещё считается нестабильной API. Другими словами, официальной документации и гарантий для общего случая пока нет, и React-команда может менять поведение или интерфейсы в будущем. Поэтому, если вы хотите «чистый» Suspense без дополнительных библиотек, стоит учесть, что это пока не является полностью поддерживаемым сценарием, и ваши решения могут сломаться в следующих версиях React.
Хук внутри себя всё равно будет использовать
useEffect
для запроса данных, так что это вопрос именно композиции и структурирования кода, а не принципиального отличия в подходе. Пример был упрощен оставляя пространство для вопроса "А как бы вы сделали это?" :)Да, в статье показан только упрощённый фрагмент компонента
App
. Он служит примером того, как использовать<Profile>
на практике - без лишнего кода, не относящегося к сути задачи.Благодарю за мнение.
Этот пример с функцией в
children
демонстрирует, что это обычный React-проп, которому можно передавать функцию как значение.Сама идея упрощена для собеседования (в статье это указано), чтобы оценить именно понимание жизненного цикла и эффектов - в боевом проекте, конечно, принято грамотно разделять ответственность и не плодить запросы во всех мелких компонентах.
Спасибо, что обратили внимание на задачу!
Я бы задал вопросы, связанные с производительностью и оптимизацией, например:
Как организовать параллельную загрузку нескольких профилей и синхронизировать их результат в одном компоненте?
Как выстроить отказоустойчивость при сбоях сети (ретраи, отмена запросов, механизмы кэширования)?
Как решать проблему при работе в среде SSR, где запросы нужно делать ещё до рендера?
Как совместить подход с Suspense и Error Boundaries для более реактивной UX-модели?
спасибо за совет!)
Были долгие зимние каникулы, было скучно 😁
Спасибо за обратную связь!
Я не мастер баннеров, но решил этот сделать сам :)
Надеюсь, он вам больше понравится.
Ребята, я вас услышал! Спасибо за обратную связь!
Поправил заголовок в статье, описание к посту и оставил цитату, что данные проблемы не только для JSON, но так же есть и в других форматах.
спасибо за фидбек!
соглашусь, что подобные сложности (большие числа, даты, объёмные данные) могут возникать в любом текстовом формате, не только JSON. Однако JSON сегодня является стандартом для большинства веб-приложений на JavaScript/Node.js, поэтому именно в нём эти грабли встречаются чаще всего. Статья призвана показать, как обходить их в контексте JSON и когда стоит рассмотреть альтернативные форматы.
Правильно ли я понимаю, что вас смущает именно то, что в статье рассмотрены проблемы в контексте JSON (хотя они встречаются и в других форматах), и сам заголовок подаёт их как уникальные для JSON?
Спасибо за фидбек!
1) Я определяю интерфейс репозитория в доменном слое, чтобы выразить, какие операции нужны для работы с доменными объектами, но при этом реальную работу (вызовы save(), findById() и тд) провожу из приложения (use cases). Так домен остаётся чистым и не зависит от инфраструктуры, а слой приложения решает, когда именно обращаться к репозиторию. В статье это не опечатка, а просто демонстрация того, что интерфейс живет рядом с доменными сущностями, а использование - на уровне приложения.
2) Я не призываю полностью "очищать" сущности от логики. Если метод напрямую меняет состояние или проверяет инварианты (например, order.markAsPaid() с проверкой статуса), то ему место в сущности. Если нужно задействовать инфраструктуру или другие сущности, лучше вынести это в сервис. В статье я критиковал ситуации, где сущность - это просто набор геттеров/сеттеров без логики.
3) Бывает полезно заворачивать простые типы в ValueObject, чтобы защититься от ошибок и явно отразить бизнес-понятийный уровень. Считаю это своего рода "логикой", поскольку мы запрещаем смешивать несовместимые типы. Однако, если никакого смысла и валидации в VO нет, можно оставить примитив.
4) Вы правы, лучше назвать markAsPaid(), чтобы сразу отражать суть. Если там нет процесса списания денег, то название pay() может путать. Если же есть реальная финансовая логика, тогда это уже задача сервиса, а сущность лишь меняет свой статус.
Спасибо за комментарий!
Интерфейс не всегда является обязательным элементом. Существуют сценарии, где главная ценность - это API или служебная библиотека. Сущности и репозитории часто действительно сводят к хранению ради удобства ORM, что может отдалять от исходных целей DDD. Перенос логики в сервисы может облегчить сущности, но усложнить связь между ними и состоянием, если бизнес-правила тесно привязаны к жизненному циклу объекта. Value Objects сокращают использование примитивов и делают код выразительнее, однако важно соблюдать баланс, чтобы не превратить проект в набор мелких обёрток.
Маппинг может казаться обременительным, но он помогает чётко отделить доменную модель от инфраструктуры и даёт гибкость при изменениях. Если домен сложный и будет расти, эта боль окупается. ORM (например, EF Core) тоже не всё делает по магии: да, для базового случая работает автоконфигурация, но при нетривиальных требованиях (сложные связи, собственные схемы, специальные правила маппинга) придётся немало прописывать вручную.
Для простых проектов DDD может быть избыточным, а при серьёзных требованиях маппинг - адекватная плата за структурированную архитектуру.
Спасибо за комментарий!
DDD сам по себе не навязывает луковичную или слоистую архитектуру — это просто один из удобных способов изолировать доменную логику от инфраструктуры. В книге Эванса упомянуто разделение на «application» и «domain», но нигде не сказано «слой обязателен». В статье я показал именно такой подход, потому что в реальных NestJS-проектах он часто упрощает поддержку. Но да, формально DDD не требует какой-то одной архитектурной схемы.
Нет, но мы с командой следим за развитием TanStack и планируем попробовать его в новом проекте. Если успеете опробовать раньше - будет интересно услышать ваш опыт! 🙂
Интересный и полезный обзор! Спасибо за реальные кейсы с примерами. Было бы здорово добавить пару слов о производительности mask-image на сложных SVG в реальных приложениях - особенно на мобильных устройствах.
Спасибо, что поделились мнением!
Cогласен: наиболее жесткие типовые конструкции обычно остаются в инфраструктуре и фреймворках, а конечные пользователи получают более удобные интерфейсы, без лишней магии в каждом методе. Вопрос поиска баланса между сложностью и безопасностью кода действительно ключевой, и здесь у каждого проекта своя "золотая середина".